feat(cli)!: remove deprecated per-client boolean flags#465
feat(cli)!: remove deprecated per-client boolean flags#465
Conversation
Replace 19 individual boolean flags (--opencode, --claude, --codex, ...) with a single repeatable, comma-separated --client/-c flag backed by a clap ValueEnum. Cleans up --help (19 lines collapse to 1) and stops flag-list growth as new clients are added. Legacy boolean flags remain functional but are hidden from --help and will be removed in the next major release; using them prints a one-line deprecation warning to stderr only when stderr is a TTY (so JSON pipelines and tests stay clean). The Synthetic meta-client is exposed as a first-class --client value without changing tokscale-core: ClientFilter mirrors ClientId on the CLI side, leaving the core crate's clap-free layering and synthetic post-processing semantics intact. Updates filtering docs in README.md, README.ko.md, README.ja.md, and README.zh-cn.md.
…ients setting Replace the split TUI state (HashSet<ClientId> + bool include_synthetic) with a single HashSet<ClientFilter>, so the source picker, in-memory app state, disk cache key, and CLI flag parser all share one representation. The Synthetic meta-client now lives as a regular set member instead of a parallel boolean. Cache schema unchanged on disk: load_cache and save_cached_data still serialize (enabled_clients: Vec<String>, include_synthetic: bool) so caches written by older releases keep loading without a migration step. The projection happens at the read/write boundary. Add ClientFilter::to_client_id / from_client_id / from_filter_str helpers for boundary code that still needs Vec<ClientId> (the loader API) or parses canonical id strings (settings.json). Reorder ClientFilter variants to mirror ClientId::ALL declaration order so --help possible values, the TUI picker rows, and value_variants() iteration all agree on a single chronological ordering, with Synthetic appended at the end. Add a defaultClients setting (top-level in settings.json) that applies when the user passes neither --client/-c nor a legacy boolean flag. CLI flags always override defaults completely — no merging — so 'tokscale --client codex' is not surprised by extra entries from settings. Unknown ids in defaultClients are silently dropped to keep stale config from breaking tokscale. Refactor source_picker.rs to drop its local SourceOption enum and walk ClientFilter::value_variants() directly. Hotkey for Synthetic stays 'x' to preserve current display; it collides with Mux which also binds 'x' in client_ui — pre-existing bug noted with a TODO, scoped out of this change. Update README.md / README.ko.md / README.ja.md / README.zh-cn.md Configuration sections to document defaultClients.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
…ADME examples
Two related issues caught in code review:
1. The no-filter TUI default and the `submit` warm-cache filter set
drifted apart. TUI launch with no `--client` flag enabled every
ClientFilter including Synthetic; `run_warm_tui_cache()` warmed the
cache with Synthetic excluded. Result: every TUI launch after
`submit` was a stale-cache hit instead of fresh, defeating the
warming. Pre-refactor behavior was 'every ClientId, include_synthetic
= false'; this restores it.
Fix: introduce `ClientFilter::default_set()` as the single source of
truth for 'no filter' semantics. Both code paths (App constructor in
tui/app.rs, the cache lookup in tui/mod.rs, and run_warm_tui_cache in
main.rs) now consult it. Drop the now-unused `clap::ValueEnum`
imports in tui/app.rs and tui/mod.rs.
Synthetic detection has always been opt-in because it post-processes
other clients' sessions to re-attribute messages — flipping it on
silently for everyone is a real behavior change.
Add unit tests:
- `test_client_filter_default_set_excludes_synthetic` — guards the
contract directly.
- `test_app_no_filter_default_matches_default_set` — guards that
App's constructor stays in lockstep.
2. Replace stale legacy-flag examples that still appeared in README
sections unrelated to the 'Filtering by Platform' deprecation block:
`tokscale models --week --claude`, `tokscale submit --opencode
--claude ...`, `tokscale graph --opencode --claude`. After the major
bump that removes the deprecated flags these examples become outright
wrong; even before that they contradict the canonical interface.
Updated in all four READMEs (en/ko/ja/zh-cn).
Test plan: 369 unit + 83 integration = 452 pass, 0 fail.
40ebeba to
f1caf3d
Compare
Update: Oracle review — addressed LOW finding + rebased on updated #464LOW: legacy-rejection guard was too narrowThe original `test_client_flags_legacy_long_flags_rejected` only checked `--claude`. Expanded to a table over all 19 removed flags with `--synthetic` called out explicitly — it's the only legacy flag without a matching `ClientId`, so its handling has always been special-cased and is the most likely to regress if anyone resurrects a boolean field. Also added a positive sanity sweep to verify `--client opencode`, `--client claude`, and `--client synthetic` all still parse, so the negative test cannot silently pass via an over-tight parser. Pushed as `f1caf3d test(cli): expand legacy-flag rejection guard to all 19 removed flags`. Rebased on updated #464Branch was rebased after `308b471` landed on `feat/cli-client-filter-flag`. The rebase pulls in:
So once #464 lands, this branch's diff collapses cleanly to just the removal commits with no carryover noise. Numbers (this branch only)
PR remains DRAFT — DO NOT MERGE until v3.0.0. |
… tests hermetic Two issues caught in PR code review: 1. **`run_warm_tui_cache` ignored `defaultClients`** (devin-ai-integration P2) `run_warm_tui_cache` always used `ClientFilter::default_set()` (every real client, Synthetic excluded), regardless of the user's `defaultClients` setting. `tui::run` on a no-flag launch DOES honor `defaultClients` via `build_client_filter` upstream. Result: a user with `defaultClients = ["opencode", "claude"]` got a warm cache storing all 18 clients while the next `tokscale` launch wanted only the 2 configured ones — guaranteed cache miss, defeating the warming. Fix: extract `resolve_default_tui_filter_set` mirroring the no-flag-launch resolution chain (defaultClients → fall back to default_set). Both `run_warm_tui_cache` and the documentation comment now consult it. 2. **`build_client_filter` tests were non-hermetic** (cubic-dev-ai P2) The 5 unit tests for `build_client_filter` were calling the wrapper that loads `~/.config/tokscale/settings.json`. They passed for me (no `defaultClients` set) but a developer with their own `defaultClients` would get unrelated filter ids appended to every assertion. Pure variant `build_client_filter_with_defaults` already existed; these tests now use it with `&[]` for hermetic input. Adds: - `resolve_default_tui_filter_set_with(&[String])` — pure variant of the resolver, unit-testable. - 4 new tests: configured defaults override, empty fallback, unknown id drop, all-unknown fallback to `default_set`, synthetic supported via `defaultClients` for opt-in power users. Test plan: 374 unit + 83 integration = 457 pass, 0 fail.
BREAKING CHANGE: The legacy single-client flags (--opencode, --claude, --codex, --copilot, --gemini, --cursor, --amp, --droid, --openclaw, --hermes, --pi, --kimi, --qwen, --roocode, --kilocode, --kilo, --mux, --crush, --synthetic) are removed. Use --client/-c instead: tokscale --client opencode,claude tokscale -c opencode -c claude The flags were marked deprecated and hidden from --help on the same release that introduced --client. They have always been a strict subset of --client's functionality, so migration is a mechanical rename. This commit: - Drops the 19 hidden bool fields from ClientFlags - Simplifies build_client_filter_with_defaults: single canonical path plus the defaultClients fallback - Removes emit_legacy_client_flag_warning and the IsTerminal-gated stderr emission - Drops the four legacy-only unit tests; replaces the canonical+legacy-mix test with a guard test that asserts --claude now produces a clap parse error - Migrates every --opencode / --claude / etc. usage in cli_tests.rs to the --client form (61 sites) - Drops the 'Deprecation notice' paragraph from README.md / README.ko.md / README.ja.md / README.zh-cn.md Adds id="client_filter" + value_name="CLIENTS" to the --client arg. The id rename disambiguates the flattened arg from the outer struct's also-named clients field (clap requires globally unique arg ids and the legacy bool fields previously diluted this collision). The explicit value_name preserves the <CLIENTS> placeholder in --help instead of auto-deriving <client_filter>. Net change: -159 lines.
Per code review feedback, the original guard only checked --claude. Make the test table-driven over every removed flag, with --synthetic called out explicitly because it is the only legacy flag that did not have a matching ClientId — its handling has always been special-cased and is the most likely surface to regress if anyone resurrects the boolean fields. Also adds a positive sanity sweep to ensure --client opencode / claude / synthetic still parse, so the test does not silently pass via an over-tight parser.
467c10f to
d87330b
Compare
Warning
DO NOT MERGE until next major release (v3.0.0).
This PR removes deprecated CLI flags. Merging before the deprecation window closes will break user scripts that still use
--opencode,--claude,--codex, etc.Depends on
--client/-cand thedefaultClientssetting; deprecates the per-client booleans this PR removes.This PR cannot be reviewed in isolation until #464 lands. Until then, the diff here includes #464's content. Once #464 merges into
main, this branch's diff collapses to just the removal commits.Summary
Removes the 19 legacy per-client boolean flags that were hidden from
--helpand marked deprecated by #464:The deprecation has been visible to users for the entire window between #464 and v3.0.0. Anyone running tokscale interactively on a TTY has been seeing a one-line stderr warning every time they used a legacy flag.
Migration
tokscale --opencodetokscale --client opencodetokscale --opencode --claudetokscale --client opencode,claudetokscale --synthetictokscale --client syntheticWhat changed
crates/tokscale-cli/src/main.rsClientFlags.build_client_filter_with_defaults: single canonical-path resolution, no legacy fallback loop.emit_legacy_client_flag_warning(and its TTY-gated stderr emission).--claude(and every other removed flag, table-driven) now produces a clap parse error. Plus a positive sweep verifying--client opencode|claude|syntheticstill parse.id = "client_filter"andvalue_name = "CLIENTS"to the--clientarg. The id rename disambiguates the flattened arg from the outer struct's also-namedclientsfield — clap requires globally unique arg ids and the legacy bool fields previously masked this collision. The explicitvalue_namepreserves the<CLIENTS>placeholder in--helpinstead of leaking the auto-derived<client_filter>.crates/tokscale-cli/tests/cli_tests.rsMigrate 61
--<client>usages to--client <id>form (mechanical sed rename plus two manual.arg→.argsfixes forassert_cmd's single-arg API).READMEs
Diff size
Net -159 lines.
Test plan
cargo test -p tokscale-cli --bin tokscale— 369 pass, 0 fail (removed 4 legacy-only tests; kept the table-driven rejection guard).cargo test -p tokscale-cli --test cli_tests— 83 pass, 0 fail (every test migrated to--clientform).tokscale --opencode→error: unexpected argument '--opencode' found✓tokscale --client opencode --json→ works ✓tokscale --helpshows-c, --client <CLIENTS>(no<client_filter>leak) and no legacy flags ✓Release notes
Suggested entry for the v3.0.0 changelog: