On this page
#Changelog
#0.20.1
Guardrail correctness fixes, a repaired --dump-schema/--version, and new guardrail documentation.
Context
Hardens the command-guardrail system and fixes release-adjacent CLI bugs. Guardrail: colon-refspec remote-branch deletion (git push origin :branch) is now hard-denied for everyone (previously only ask-gated for the main agent); a cross-separator false-positive that could wrongly block chained pushes is fixed; and the kill/pkill advice no longer fires on commands like 'npm run kill'. The rule patterns are now built through anchoring helpers so a weak anchor is structurally impossible, and each hook-backed rule carries a settings-coverage annotation. CLI: claudewheel --dump-schema and --version both worked incorrectly (the former failed outright; the latter reported a stale version) and are fixed. Docs: a new Guardrails page explains the tiers and subagent handling, with a per-rule table generated from the model so it can't drift; claudewheel health gains a deployed-hook drift check.
#Features
- New Guardrails documentation page covering the four enforcement tiers, subagent-vs-main-agent handling, and the command-string caveat, with an always-in-sync per-rule reference table generated from the guardrail model.
- **
claudewheel healthnow detects deployed-hook drift** — it warns when the hook scripts installed for a profile differ from the current model.
#Fixes
- Guardrail fixes. Remote-branch deletion via the colon-refspec form (
git push origin :branch) is now hard-denied for everyone, matching--delete; a cross-separator false-positive that could wrongly block chained pushes is fixed; andkill/pkilladvice no longer fires spuriously on commands likenpm run kill. - **Fixed
claudewheel --dump-schema**, which previously failed because the CLI injected an implicit launch subcommand before the flag was parsed. - **Fixed
claudewheel --version** reporting a stale version in editable/source checkouts; it now reads the project's actual version from package.json.
#0.20.0
Subagent-aware command guardrails, a reconcile-permissions command, and a canonical-drift health check.
Context
This release overhauls the command-guardrail system that claudewheel deploys to Claude Code profiles into a single canonical protocol driven by one model (claudewheel/guardrail.py). Guardrail hooks now distinguish subagents from the main agent via the PreToolUse agent_id field: escalate-tier commands (git push, git reset, rebase, saferm purge, gh workflow run, forced switch) are hard-denied for subagents with instructions to escalate to the parent agent, while the main agent falls through to a confirmation prompt. git checkout is steered to git switch, and kill/pkill trigger advice to build graceful stop scripts. The new reconcile-permissions command sweeps every profile and the shared defaults to the canonical rule set, and the new canonical-drift health check reports any divergence.
#Features
- New patch-profiles command syncs existing profiles and shared settings to canonical hook/disallowedTools defaults
- **New
reconcile-permissionscommand.** Reconciles each profile's permission rules and the shared defaults to the canonical guardrail set: adds missing rules, removes obsolete ones, and strips dead allow entries. Requires an explicit--dry-runor--apply. - Guardrail hooks now distinguish subagents from the main agent. Escalate-tier commands (git push, git reset, rebase, saferm purge, gh workflow run, forced switch) are hard-denied for subagents with instructions to escalate to the parent agent, while the main agent falls through to a confirmation prompt.
git checkoutis steered togit switch, andkill/pkillnow trigger advice to build graceful stop scripts. - **New
canonical-drifthealth check.**claudewheel healthnow reports when a profile's permission rules or hook wiring diverge from the canonical guardrail set. - Added Claude Opus 4.8 model variants to the model selection defaults.
#Fixes
- Health check /tmp/claude now measures real tmpfs usage (excludes symlink targets, uses block size); threshold lowered to 1 GB
- Fixed the rm hard-block hook emitting invalid JSON (rm commands were never blocked) and hardened it to catch sudo/env/xargs/find -exec rm
#0.19.1
Profile rename command, inline auth-shadow fix on inspect page, faster detection, and a state-save race fix.
#Features
- Terminal background detection timeout reduced from 1s to 500ms, halving worst-case startup latency on unsupported terminals.
- Profile inspect page now offers to fix auth shadow inline when detected (press
f). - New
profile rename <old> <new>command with automatic recovery if interrupted mid-rename.
#Fixes
- Fixed a race where concurrent sessions could lose the remembered browser choice on state save.
#0.19.0
CLI profile command group, auth shadow fix, hook guard, rate-limit tier, live theme switching, and online token validation.
Context
Breaking: profile commands are now grouped under claudewheel profile (create/delete/show/fix-auth/check-tokens). Old flat names print a redirect and exit.
New features: auth-shadow detection and fix (profile fix-auth strips session credentials shadowing long-lived tokens), a PreToolUse hook blocking unsafe git/rm patterns in AI sessions, rate-limit tier capture from session-login credentials for downstream tools, a themed install-confirmation dialog, online token validation (profile check-tokens), and Mode 2031 live theme switching for terminals that support it.
Fixes: CSI decoder handles private-mode sequences without byte leakage, and SIGTERM/SIGHUP are cleanly saved/restored during forms and PTY sessions.
#Breaking
- Breaking. Profile commands renamed to a group:
new-profile->profile create,delete-profile->profile delete,show-profile->profile show. Old names print a redirect and exit.
#Features
- New
profile fix-authcommand strips session credentials that shadow a long-lived token, and a health check detects the condition. - New
hook-block-unsafe-commandshook blocks rawgit add,git stash,git restore,git checkout --, andrmin AI agent sessions, directing to safegit/saferm. - Rate-limit tier is captured from session-login credentials and exposed to downstream tools (e.g., howmuchleft) via a
.credentials.jsonstub at launch. - Version install uses a themed confirmation dialog and result page instead of a bare text prompt.
- New
profile check-tokenscommand validates stored tokens against the Anthropic API and reports per-profile status. - Live theme switching: terminals supporting Mode 2031 (kitty, Ghostty, foot, VTE 0.82+) automatically switch claudewheel's theme when the OS dark/light mode changes mid-session.
#Fixes
- Fixed CSI decoder to handle private-mode sequences (ESC[?...) without leaking bytes into the input stream.
- SIGTERM and SIGHUP are now handled cleanly during forms and PTY sessions, preventing terminal corruption on kill.
#0.18.2
Profiles now launch without a login screen, and the theme adapts to light/dark terminals automatically.
#Features
- Terminal background color is now auto-detected at startup (via OSC 11). Light-terminal users automatically get the light theme without manual configuration.
#Fixes
- Profiles created via the wizard now work immediately without Claude Code showing a login screen. Previously, CC's onboarding gate blocked token-injected profiles.
- Form text is now fully theme-driven — readonly fields and radio selections no longer use hardcoded colors that were invisible on light backgrounds.
#0.18.1
Hint bar now automatically reflects available keybindings and wraps on narrow terminals.
#Features
- Keyboard shortcuts are now shown automatically in the hint bar based on current context — new bindings no longer require manual hint-string updates.
- Hint bar wraps to a second line on narrow terminals instead of truncating.
#0.18.0
Themed form system, zero-paste token capture with API validation, profile inspect and delete in the TUI, and six new internal modules.
Context
The profile creation and auth flows are rebuilt on a themed widget layer (new forms theme section, focus-bg idiom matching the segment bar) running in one continuous fullscreen session. Token capture uses a PTY proxy to scrape setup-token's output automatically -- no more copy-paste. Every token is validated against the Anthropic API before saving (hard 401 rejection; the warn-and-save path is gone). Profiles can be inspected (i key / show-profile CLI) and deleted (Ctrl-D/Delete key / delete-profile CLI) from the TUI, with a data-destruction hard-block for profiles whose shared dirs are real directories.
Infrastructure: fsutil.py consolidates all atomic JSON writes (the permission-loss bug class is structurally eliminated), tokens.py consolidates token I/O, the CSI decoder handles Delete/PgUp/PgDn/Insert/parametric Shift-Tab without leaking bytes, and Terminal.cooked() replaces hand-rolled raw-mode transitions.
Breaking: delete-profile now requires --force-delete-data (in addition to --force-delete) to remove profiles with real shared directories.
#Features
- Continuous fullscreen create-profile flow. The profile wizard, auth method/browser forms, and a new creation summary page now run as one uninterrupted fullscreen session (no more bouncing between the TUI and scrollback), themed via the new
formstheme section. Theclaude auth login/setup-tokensubprocess and token paste open in a temporary cooked window and return to the session. The CLI new-profile path gets the same flow. - Zero-paste token auth with hard validation. The long-lived token flow now captures
claude setup-tokenoutput directly -- no manual paste needed -- and validates every token against the API before saving. Tokens the API rejects (401) are never saved (one manual re-paste is offered); when the API is unreachable, saving unvalidated requires an explicit choice and is reported as "unverified". The pre-launch auth prompt now launches only on an explicit skip. - Profile inspect. Press
ion the profile segment to open a fullscreen inspection page for the focused profile, or runc show-profile <name>from the CLI. The report covers registration, credentials, token expiry, shared-dir symlink health (with a danger flag for real data at shared names), settings/permission summary, active session count, and disk usage. - TUI profile delete. Press Ctrl-D or Delete on the profile segment to delete the focused profile after an informed confirmation (Cancel default-focused). Profiles holding real data at shared-dir names are hard-blocked with a pointer to the new
delete-profile --force-delete-dataCLI flag -- the TUI offers no override.
#Fixes
- Fix:
tokens.jsonno longer loses its 0600 permissions when a token is updated or a profile is deleted (previously triggered health-check warnings after any token update).options.json,state.json, andinodes.jsonlikewise keep their existing permissions across updates, and a corrupttokens.jsonnow produces a clear error instead of a crash. - Fixed silent data loss on profile delete.
delete-profileused to rmtree shared-dir names (e.g.projects/) even when they were real directories holding conversation data instead of symlinks. Deletion now refuses with the at-risk dir names; the built-indefaultprofile is refused outright; profiles on disk but missing from options.json can now be deleted; a stalelast_configprofile reference is purged from state.json. - Fixed a bug where Delete, PgUp, PgDn, and Insert keys leaked stray bytes into the search buffer. Also added support for parametric Shift-Tab (ESC[1;2Z).
- Fixed a bug where updating tokens.json lost its restrictive file permissions (0600 reverted to 0644 on every write).
#0.17.0
Auth flow UX overhaul: wizard-style prompts, browser choice with copy-URL option, remembered browser, and return-to-TUI after auth.
Context
The v0.16.x auth flow worked but was rough: a bare numbered input() prompt, forced browser auto-open with no control over which browser, whitespace-fragile token pasting, and being dropped straight into Claude Code after authenticating. This release rebuilds the flow on a reusable raw-mode selection form (new ui.py module), adds browser detection across native/flatpak/snap installs with a copy-URL fallback (via the BROWSER env var, which Claude Code honors directly), remembers the browser choice in state.json, and returns to the segment bar after auth so the user confirms the launch themselves.
#Features
- The auth setup prompt is now an arrow-key selection form matching the wizard's style. Esc safely cancels instead of skipping auth.
- Auth setup now lets you choose which browser to open (auto-detected from native, flatpak, and snap installs) or copy the login URL instead of opening any browser.
- After authenticating a profile from the launch intercept, you return to the segment bar (with a status flash) instead of being dropped straight into Claude Code. Only the explicit "Launch without auth" option launches directly.
- Your browser choice for auth is remembered and pre-focused on the next auth flow.
#Fixes
- Long-lived token paste now strips all whitespace and linebreaks automatically, so tokens copied from the terminal with wrapping artifacts work correctly.
#0.16.1
Launching an unauthenticated profile now prompts for auth setup before starting Claude Code.
#Features
- Launching an unauthenticated profile now prompts for auth setup (session login, long-lived token, or skip) before starting Claude Code.
#0.16.0
Profile wizard overhaul: new profiles appear instantly, inline auth setup, and visual indicators for unauthenticated profiles.
Context
Previously, profiles created via the wizard were invisible in the segment bar because discovery required .credentials.json or a tokens.json entry, neither of which the wizard created. This release fixes the root cause (broadened discovery to accept settings.json, added pinned to collection order) and adds a post-wizard auth flow so users can authenticate immediately instead of manually running CLI commands. Unauthenticated profiles now appear dimmed in the UI.
Also includes a breaking rename of --force to --force-delete/--force-overwrite and a fix for machine-local path dependencies in uv.lock.
#Breaking
- Breaking. Renamed
--forceto--force-delete(delete-profile) and--force-overwrite(deploy-hooks). Boolean flags now require explicit--flag/--no-flagwhere no default is set.
#Features
- Profile discovery now accepts profiles with only
settings.json, so newly created profiles appear immediately without requiring auth setup first. - Unauthenticated profiles are visually dimmed in the segment bar, indicating they need auth setup.
- Profile wizard now offers inline auth setup (session login, long-lived token, or skip) immediately after profile creation.
#Fixes
- Dependency installation no longer requires a machine-local checkout:
uv.lockpreviously carried a local path forstrictcli, breaking installs and CI outside the author's machine. It now resolves from PyPI (strictcli 0.24.0). - Newly created profiles now appear in the segment bar immediately after the wizard completes, without requiring a restart.
#0.15.1
Thread safety fix for background discovery and wizard UX overhaul
Context
The background discovery thread shared a mutable state dict with the main thread, creating a race condition on npm_versions_cache writes. Fixed by passing a deep copy and copying results back on the main thread after completion.
The profile creation wizard was overhauled: 6 checkbox fields are now hidden behind a collapsible Advanced toggle (defaulting to sensible values), Enter from the Name field submits immediately, errors persist until the user takes a meaningful action, context-sensitive keyboard hints appear at the bottom, Shift-Tab navigates backward, and the text input has visible brackets. The Cancel button was removed (ESC suffices).
#Features
- Wizard UX overhaul. Collapsible Advanced toggle hides 6 checkboxes by default, Enter from Name field submits, persistent error display, context-sensitive keyboard hints, Shift-Tab backward navigation, improved visual clarity (bracketed text input, bold radio selections).
#Fixes
- Fix. Background discovery thread no longer shares mutable state dict with the main thread; uses a deep copy to prevent race conditions on npm version cache writes.
#0.15.0
Option provenance architecture: SegmentState separates discovered, pinned, and default options with staleness policies, value-based selection, deferred discovery apply, and a provenance overlay
Context
A pre-registry build (0.1.0) accidentally shipped with the maintainer's personal data hardcoded in DEFAULT_OPTIONS (GitHub handles, profile names). This seeded into users' ~/.claudewheel/options.json on first run. Even after the fix (making defaults empty + adding discovery), stale data persisted because gh_auth appended (never replaced) and claude_config_scan fell back to stale values when discovery returned empty.
This release introduces SegmentState -- a new data model that cleanly separates discovered (runtime), pinned (user-added), and default (shipped) option collections. Discovery always replaces the discovered collection; pinned values are never touched by discovery. A staleness policy (IMMEDIATE for credentials, VERIFY for filesystem objects) controls what happens when previously-discovered values disappear. The entire discovery system was refactored from a monolithic match/case dispatch into a typed registry of individual functions returning DiscoveryResult dataclasses.
Selection tracking switched from index-based (fragile when options change) to value-based. The "+" creation sentinel moved from a real option to a virtual UI element via display_options. Slow discovery results are now deferred for the focused segment and applied on defocus, preventing option list disruption during interaction. A provenance overlay (toggle with ?) shows where each option came from.
#Features
- Staleness policy. Discovery registry entries now carry verify callbacks; set_discovered uses them to retain values that still exist on disk when a re-scan omits them.
- Directory discovery. Recent dirs are now validated (must exist on disk) and stale entries are pruned from state. Static values no longer mixed into discovery results.
- Virtual '+' button. The '+' creation sentinel is now a virtual UI element, no longer stored in segment state collections. Freeform values are promoted from ephemeral to pinned on launch.
- Deferred discovery apply. Slow discovery results for the focused segment are now buffered and applied on defocus, preventing option list disruption while the user is interacting. A pending indicator (*) appears in the segment label when results are waiting.
- Provenance overlay. Press
?to toggle a source overlay on fan-out options:*discovered,^pinned,.default,~ephemeral. The status bar shows a legend while active. - Docs. Added installation instructions (pipx/uv) and deprecation notice for the old Node/npm package.
#0.14.0
Add import command for importing session data from external Claude Code directories
Context
The new claudewheel import command enables importing Claude Code session data from external directories (e.g., Windows backups onto a Linux machine). It handles cross-OS path rewriting (Windows backslashes to Unix forward slashes), collision detection for sessions that already exist in the store, optional session re-identification (reid), and a dry-run mode for previewing what would be imported.
#Features
- New command.
claudewheel importimports Claude Code session data from external directories (e.g., Windows backups) into the shared store, with cross-OS path rewriting, collision detection, reid support, and dry-run mode.
#0.13.1
Instant TUI startup via async discovery, KeyboardInterrupt fix, SEO improvements
#Features
- Improvement. TUI launches instantly. Slow discovery calls (GitHub auth, npm versions) now run in a background thread instead of blocking startup.
#Fixes
- Fix. Ctrl-C during npm version fetch no longer produces a traceback.
#0.13.0
Proactive directory rename detection via inode tracking
#Features
- New feature. Proactive directory rename detection via inode tracking. On every launch, claudewheel records the project directory's inode. The health check detects when a recorded path was renamed and suggests
claudewheel mv --post-hocto fix it.
#0.12.0
Fable 5 model support, model auto-sync, full orphan scan for --cont
#Features
- New feature. Model list now auto-syncs from defaults on startup. New models added to claudewheel are automatically available without resetting options.
- New feature. Added Fable 5 (
claude-fable-5andclaude-fable-5[1m]) to the default model list. - Improvement.
--contnow scans all orphaned session directories, not just same-parent. Cross-parent directory renames are now detected.
#0.11.0
mv now renames directories by default, --post-hoc for session-only migration
#Breaking
- Breaking.
mvnow renames the directory on disk by default, then migrates sessions. Use--post-hocfor session-only migration (the old behavior).
#0.10.1
CI workflow improvements: idempotent publish steps for npm and PyPI
Context
Scaffold update added skip-if-already-published checks to both npm and PyPI publish workflows, making CI re-runs safe. Also added separate CI check workflows.
#Fixes
- Fix. CI publish workflows are now idempotent -- re-running a partially failed publish no longer fails on already-published packages.
#0.10.0
New permission command group for managing profile permission rules
#Features
- New command group.
permission add,permission remove, andpermission listsubcommands for managing profile permission rules from the CLI.
#0.9.1
--cont interception, mv merge fix, cleaner dry-run UX
#Features
- New feature.
--contnow detects directory renames the same way--resumedoes, scanning for orphaned sessions in sibling directories. - Improvement. Resume/cont interception shows the
claudewheel mvcommand when the old path still exists, and uses a concise human-readable dry-run summary instead of per-file log spam.
#Fixes
- Bug fix.
mvnow merges sessions into an existing target directory instead of silently skipping the move.
#0.9.0
Rename redir to mv, add resume interception for directory renames, fix path encoding bug
Context
The redir command is renamed to mv for better discoverability. When --resume can't find a session under the current directory, claudewheel now searches the shared store, detects that the project directory was renamed, and offers to move all sessions to the new path. The path encoding function is also fixed to replace dots (not just slashes) with hyphens, matching Claude Code's internal encoding -- this fixes mv operations on dotfile paths.
#Breaking
- Breaking. Renamed
redircommand tomv.
#Features
- New feature. Resume interception: when
--resumecan't find a session under the current directory, claudewheel searches the shared store, detects directory renames, and offers to move sessions to the new path.
#Fixes
- Bug fix. Path encoding now replaces both
/and.with-, matching Claude Code's internal encoding. Previously, dotfile paths (e.g.~/.claude-common) would encode incorrectly.
#0.8.0
Rename gc command to stats
Context
The gc command only reports shared-store statistics now (sentinel cleanup and origins compaction were removed in v0.7.0). Renamed to reflect its actual purpose.
#Breaking
- Renamed.
gccommand renamed tostatsto reflect its actual purpose (reporting shared-store statistics).
#0.7.0
Remove profile attribution system, add --picker flag, unify shared settings
Context
The profile attribution system (hook-stamp-origin, xattr stamping, sentinels, origins log) had unfixable race conditions and 30% of session files could never be attributed. Removed entirely rather than patching. Also adds --picker for argless session resume and unifies shared settings with drift detection.
#Breaking
- Breaking. Removed the profile attribution system (hook-stamp-origin, xattr stamping, sentinel files, origins log). The system had unfixable race conditions and 30% of files could never be attributed.
#Features
- New flag.
--pickeropens the Claude session resume picker without requiring a session ID argument. - Unified shared settings. Replaced per-profile profile-defaults.json with a single shared-settings.json and drift detection.
- deploy-hooks --force. Added
--forceflag to overwrite existing hook scripts.
#Fixes
- Health check. Removed xattr-coverage and hook-integrity checks; streamlined hooks-wired to only verify hook-timestamp.
#0.6.1
Consolidate shared data and eliminate ~/.claude-shared/ and ~/.claude-common/
Context
Shared session data (projects, session-env, file-history, tasks, todos, paste-cache) moved from ~/.claude-shared/ to ~/.claudewheel/shared/. Skills, utility scripts, and profile origins moved from ~/.claude-common/ into ~/.claudewheel/. COMMON_DIR constant eliminated. Sentinel files moved to dedicated ~/.claudewheel/shared/sentinels/ subdirectory. Dead code (_strip_xattrs, _clean_origins_file) removed. Origins file dual-location bug fixed.
#Breaking
- Shared data consolidated. Session data, skills, and scripts moved from ~/.claude-shared/ and ~/.claude-common/ into ~/.claudewheel/. Both old directories eliminated.
#Fixes
- Fix. Profile origins log now correctly read from ~/.claudewheel/ instead of stale ~/.claude-common/ path.
#0.6.0
Profile centralization, hook management, worktree isolation, docs website
Context
Profiles moved from ~/.claude-
#Breaking
- Profile directories moved. Profiles now live at ~/.claudewheel/profiles/
/ instead of ~/.claude- /. A startup warning appears if old-style directories are detected.
#Features
- New command.
deploy-hooksauto-creates hook scripts at ~/.claudewheel/scripts/ from built-in templates. - Settings drift detection. Health check compares profiles against a canonical shared-settings.json and reports differences.
- Worktree isolation guard. PreToolUse hook blocks the Agent tool from using worktree isolation, preventing multi-session conflicts.
- Cron tools enabled. CronCreate, CronDelete, CronList, and ScheduleWakeup removed from disallowed tools.
- Documentation website. Live docs site at claudewheel.smmh.dev with auto-generated API reference, CLI reference, and branding.
#0.5.0
Strictcli compatibility fix and config-directory rename to ~/.claudewheel/.
Context
The config directory has been renamed from ~/.claudelauncher/ to ~/.claudewheel/ to match the project name (the rename of the project itself happened a while ago, but the config-dir path was never updated). Existing users must mv ~/.claudelauncher ~/.claudewheel before upgrading or claudewheel will scaffold a fresh empty config directory on next launch.
Strictcli v0.16.0 added a guardrail requiring unique=True or unique=False on every repeatable=True flag. claudewheel's -s/--set flag did not pass it and crashed at startup with ValueError: Flag "set": repeatable requires explicit unique. This release adds unique=False and, more importantly, surfaces the underlying intent the guardrail is meant to enforce: _handle_launch now rejects any duplicate segment override regardless of source. Previously, passing the same key twice (e.g. --profile work -s profile=personal, or -s profile=work -s profile=personal) silently dropped the earlier value. The new diagnostic names the conflicting key, both values, and both sources.
#Breaking
- Config directory renamed from
~/.claudelauncher/to~/.claudewheel/. Runmv ~/.claudelauncher ~/.claudewheelbefore upgrading or claudewheel will scaffold a fresh empty dir on next launch.
#Fixes
- Fix startup crash from strictcli guardrail;
-snow errors on duplicate segment keys (including conflicts between an individual segment flag and-s) instead of silently dropping the earlier value.
#0.4.5
#Fixes
- Fix.
resolve_profile()now runs option discovery before reading metadata, fixing programmatic profile resolution from external callers.
#0.4.4
- No user-facing changes.
#0.4.3
#Fixes
- Fix. Profiles set up before claudewheel (without
.credentials.json) were invisible to health checks and the TUI profile picker. They are now discovered viatokens.json. - Fix. Compatibility with strictcli 0.5.0 (MutexGroup is now always required; session flags moved to a Tag with manual mutual-exclusion check).
#0.4.2
- No user-facing changes.
#0.4.1
#Fixes
- CI fix. Resolved dependency resolution failure by removing local path override for strictcli.
#0.4.0
#Breaking
- Python 3.11 required. Bumped minimum Python version from 3.10 to 3.11 for strictcli compatibility.
#Features
- New API.
resolve_profile(name)returns environment variables (CLAUDE_CONFIG_DIR, CLAUDE_CODE_OAUTH_TOKEN) for a given profile, enabling programmatic consumers like claudestream. - CLI rewrite. Migrated from argparse to strictcli with typed subcommands, mutex groups, and structured flags.
#Fixes
- Print mode hygiene. Print mode (
-p) now skips health checks and state writes, preventing TUI default pollution and stderr noise for programmatic callers.