Skip to content

feat(tui): interactive config screen with identity and model memory - #8

Merged
duyet merged 5 commits into
mainfrom
feat/config-settings-tui
Aug 23, 2026
Merged

feat(tui): interactive config screen with identity and model memory#8
duyet merged 5 commits into
mainfrom
feat/config-settings-tui

Conversation

@duyet

@duyet duyet commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Settings screen in the TUI: config (and the launcher) now opens a grouped, navigable settings screen — sections for Account, Model, and Defaults with current values right-aligned and tone-colored, ↑↓/jk to move, to edit, x to reset, non-TTY falls back to the existing status output / dump mode.
  • Account identity: new MeInfo + fetch_me (GET /v1/me) shows username · email on the account line; the account entry opens the picker to switch accounts or re-auth.
  • Model entry: focusable to pick from /v1/models, saved to the profile's default_model.
  • Remember launched model: anyr claude --model X persists X as the session default, so a bare anyr claude next time starts with it. First launch on a fresh machine seeds a profile instead of silently skipping persistence.
  • Hermetic tests: launch dry-run tests now run against a temp ANYROUTER_HOME; they previously read the developer's real config and passed only by coincidence.

Test plan

  • cargo test — 108 lib + 45 cli + 7 release-lock pass
  • cargo clippy --all-targets — no new warnings (baseline 5 pre-existing)
  • cargo fmt --check — changed files clean (pre-existing diffs untouched)
  • New integration test: launch with --model, relaunch dry-run asserts remembered model, config records it

🤖 Generated with Claude Code

duyet and others added 5 commits August 22, 2026 16:24
MeInfo carries email, name, username, and balance from GET /v1/me
(accepted with sk-ar- inference keys). display_label renders the
username · email form used by the launcher and settings screens.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Co-authored-by: Duyet Le <me@duyet.net>
Co-authored-by: duyetbot <bot@duyet.net>
SettingsState models grouped rows (section headers + label/value
entries) with a cursor that skips sections. Surface::Settings maps
x to a new Unset action for resetting a row to its default; j/k,
enter, esc/q behave like the launcher. Rendering right-aligns each
current value with a tone color (green enabled, teal model id,
orange warning, dim unset) inside a wider centered dialog.
plain_settings_frame keeps --dump-tui ANSI-free.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Co-authored-by: Duyet Le <me@duyet.net>
Co-authored-by: duyetbot <bot@duyet.net>
config on a TTY now opens a grouped settings screen instead of the
flat action menu: Account (identity from /v1/me, api key), Model
(default + haiku/sonnet/opus/fable slots), Agent, General
(auto-update, channel) — every row showing its live value. Enter
edits via the existing pickers (account switch/add/reauth/logout,
keys use, model picker, agent picker, toggles); x resets a row to
its built-in default; esc closes and the frame re-renders fresh.

CreditsCache now also caches identity so the launcher header shows
username · email once per TTL. Dump mode stays offline-deterministic;
wasm builds keep the legacy menu. Isolate upgrade_check_flag_is_known
from a real ~/.anyrouter whose channel skewed it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Co-authored-by: Duyet Le <me@duyet.net>
Co-authored-by: duyetbot <bot@duyet.net>
Launching with --model now persists it as the profile's default_model,
so a bare `anyr claude` next time starts with the same model. First
launch on a fresh machine seeds a profile from what resolved (key, base
URL, model) instead of silently skipping persistence.

Also makes the launch dry-run tests hermetic via a temp ANYROUTER_HOME:
they previously read whatever lived in the developer's real config and
passed only by coincidence.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Co-authored-by: Duyet Le <me@duyet.net>
Co-authored-by: duyetbot <bot@duyet.net>
/bin/true only exists on Linux; CI failed on macOS and Windows. Use
`true` (resolved via which) on unix and `cmd` on Windows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Co-authored-by: Duyet Le <me@duyet.net>
Co-authored-by: duyetbot <bot@duyet.net>
@github-actions

Copy link
Copy Markdown
Contributor

anyr size and startup

Startup is wall time for a cold anyr --version / anyr --help (median of 21 runs). Size is the stripped release binary, or the .wasm for the browser demo.

Size budget: anyr-linux-x86_64 must stay ≤ 4.0 MiB (4194304 bytes) stripped.

Asset Kind Size --version median --help median
anyr-darwin-arm64 native 2.3 MiB 3.26 ms 3.51 ms
anyr-linux-arm64 native 2.3 MiB 0.7 ms 0.69 ms
anyr-linux-x86_64 native 2.5 MiB 0.58 ms 0.59 ms
anyr-windows-x86_64.exe native 2.1 MiB 8.7 ms 8.63 ms
anyr.wasm wasm 170.6 KiB

Budget check: ok

raw timings
[
  {
    "asset": "anyr-darwin-arm64",
    "kind": "native",
    "path": "/Users/runner/work/cli/cli/anyr-darwin-arm64",
    "bytes": 2417992,
    "size": "2.3 MiB",
    "version": "0.1.10 (built 2026-08-22 22:11:05)",
    "target": "aarch64-apple-darwin",
    "os": "macos-latest",
    "startup_version": {
      "n": 21,
      "min_ms": 3.06,
      "median_ms": 3.26,
      "p95_ms": 4.56,
      "mean_ms": 3.52
    },
    "startup_help": {
      "n": 21,
      "min_ms": 3.01,
      "median_ms": 3.51,
      "p95_ms": 5.3,
      "mean_ms": 3.91
    }
  },
  {
    "asset": "anyr-linux-arm64",
    "kind": "native",
    "path": "/home/runner/work/cli/cli/anyr-linux-arm64",
    "bytes": 2364384,
    "size": "2.3 MiB",
    "version": "0.1.10 (built 2026-08-22 22:10:55)",
    "target": "aarch64-unknown-linux-gnu",
    "os": "ubuntu-24.04-arm",
    "startup_version": {
      "n": 21,
      "min_ms": 0.67,
      "median_ms": 0.7,
      "p95_ms": 0.78,
      "mean_ms": 0.72
    },
    "startup_help": {
      "n": 21,
      "min_ms": 0.66,
      "median_ms": 0.69,
      "p95_ms": 0.77,
      "mean_ms": 0.71
    }
  },
  {
    "asset": "anyr-linux-x86_64",
    "kind": "native",
    "path": "/home/runner/work/cli/cli/anyr-linux-x86_64",
    "bytes": 2671328,
    "size": "2.5 MiB",
    "version": "0.1.10 (built 2026-08-22 22:11:05)",
    "target": "x86_64-unknown-linux-gnu",
    "os": "ubuntu-latest",
    "startup_version": {
      "n": 21,
      "min_ms": 0.55,
      "median_ms": 0.58,
      "p95_ms": 0.61,
      "mean_ms": 0.58
    },
    "startup_help": {
      "n": 21,
      "min_ms": 0.56,
      "median_ms": 0.59,
      "p95_ms": 0.64,
      "mean_ms": 0.6
    }
  },
  {
    "asset": "anyr-windows-x86_64.exe",
    "kind": "native",
    "path": "D:\\a\\cli\\cli\\anyr-windows-x86_64.exe",
    "bytes": 2213376,
    "size": "2.1 MiB",
    "version": "0.1.10 (built 2026-08-22T22:12:01Z)",
    "target": "x86_64-pc-windows-msvc",
    "os": "windows-latest",
    "startup_version": {
      "n": 21,
      "min_ms": 8.51,
      "median_ms": 8.7,
      "p95_ms": 9.56,
      "mean_ms": 8.91
    },
    "startup_help": {
      "n": 21,
      "min_ms": 8.45,
      "median_ms": 8.63,
      "p95_ms": 8.79,
      "mean_ms": 8.64
    }
  },
  {
    "asset": "anyr.wasm",
    "kind": "wasm",
    "path": "/home/runner/work/cli/cli/target/wasm-pkg/anyr_cli_bg.wasm",
    "bytes": 174670,
    "size": "170.6 KiB",
    "version": "wasm",
    "target": "wasm32-unknown-unknown",
    "os": ""
  }
]

@duyet
duyet merged commit 8a343d6 into main Aug 23, 2026
8 checks passed
@duyet
duyet deleted the feat/config-settings-tui branch August 23, 2026 03:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant