claw --output-format json --resume <session> (no command) was printing:
'Restored session from <path> (N messages).'
to stdout as prose, regardless of output format.
Now emits:
{"kind":"restored","session_id":"...","path":"...","message_count":N}
159 CLI tests pass.
/session list previously returned 'unsupported resumed slash command' in
--output-format json --resume mode. It only reads the sessions directory
so does not need a live runtime session.
Adds a Session{action:"list"} arm in run_resume_command() before the
unsupported catchall. Emits:
{kind:session_list, sessions:[...ids], active:<current-session-id>}
159 CLI tests pass.
'failed to restore session' errors from both the path-resolution step
and the JSONL-load step now check output_format and emit:
{"type":"error","error":"failed to restore session: <detail>"}
instead of bare eprintln prose.
Covers: session not found, corrupt JSONL, permission errors.
/stats was accidentally listed in STUB_COMMANDS (both in the original list
and overlooked in 1e14d59). Since SlashCommand::Stats is fully implemented
with REPL and resume dispatch, it should not be intercepted as unimplemented.
/tokens and /cache alias to Stats and were already working correctly.
/stats now works again in all modes.
23 spec-registered commands had no parse arm in validate_slash_command_input,
causing the circular error 'Unknown slash command: /X — Did you mean /X?'
when users typed them in --resume mode.
Two fixes:
1. Add the 23 confirmed parse-armless commands to STUB_COMMANDS (excluded
from REPL completions and help output).
2. In resume dispatch, intercept STUB_COMMANDS before SlashCommand::parse
and emit a clean '{error: "/X is not yet implemented in this build"}'
instead of the confusing error from the Err parse path.
Affected: /allowed-tools, /bookmarks, /workspace, /reasoning, /budget,
/rate-limit, /changelog, /diagnostics, /metrics, /tool-details, /focus,
/unfocus, /pin, /unpin, /language, /profile, /max-tokens, /temperature,
/system-prompt, /notifications, /telemetry, /env, /project, plus ~40
additional unreachable spec names.
159 CLI tests pass.
/export now emits: {kind:export, file:<path>, message_count:<n>}
/agents now emits: {kind:agents, text:<agents report>}
Previously both returned json:None and fell through to prose output even
in --output-format json --resume mode. 159 CLI tests pass.
/help now emits: {kind:help, text:<full help text>}
/diff now emits:
- no git repo: {kind:diff, result:no_git_repo, detail:...}
- clean tree: {kind:diff, result:clean, staged:'', unstaged:''}
- changes: {kind:diff, result:changes, staged:..., unstaged:...}
Previously both returned json:None and fell through to prose output even
in --output-format json --resume mode. 159 CLI tests pass.
Before: doctor reported 'loaded 0/5' and listed 5 'Discovered file'
entries for paths that don't exist on disk. This looked like 5 files
failed to load, when in fact they are just standard search locations.
After: only paths that actually exist on disk are shown as 'Discovered
file'. 'loaded N/M' denominator is now the count of present files, not
candidate paths. With no config files present: 'loaded 0/0' +
'Discovered files <none> (defaults active)'.
159 CLI tests pass.
Two bugs in --output-format json --resume /status:
1. 'model' field emitted 'restored-session' (a run-mode label) instead of
the actual model or null. Fixed: status_json_value now takes Option<&str>
for model; resume path passes None; live REPL path passes Some(model).
2. 'session_id' extracted parent dir name ('sessions') instead of the file
stem. Session files are session-<id>.jsonl directly under .claw/sessions/,
not in a subdirectory. Fixed: extract file_stem() instead of
parent().file_name().
159 CLI tests pass.
/compact now emits: {kind:compact, skipped, removed_messages, kept_messages}
/clear now emits: {kind:clear, previous_session_id, new_session_id, backup, session_file}
/clear (no --confirm) now emits: {kind:error, error:..., hint:...}
Previously both returned json:None and fell through to prose output even
in --output-format json --resume mode. 159 CLI tests pass.
Before:
error: failed to extract manifests: No such file or directory (os error 2)
After:
error: failed to extract manifests: No such file or directory (os error 2)
looked in: /Users/yeongyu/clawd/claw-code/rust
The workspace_dir is computed from CARGO_MANIFEST_DIR at compile time and
only resolves correctly when running from the build tree. Surfacing the
resolved path lets users understand immediately why it fails outside the
build context.
ROADMAP #45 root cause (build-tree-only path) remains open.
Add SlashCommand::slash_name() to the commands crate — returns the
canonical '/name' string for any variant. Used in the REPL's stub
catch-all arm to surface which command was typed instead of printing
the opaque 'Command registered but not yet implemented.'
Before: typing /rewind → 'Command registered but not yet implemented.'
After: typing /rewind → '/rewind is not yet implemented in this build.'
Also update the compacts_sessions_via_slash_command test assertion to
tolerate the boundary-guard fix from 6e301c8 (removed_message_count
can be 1 or 2 depending on whether the boundary falls on a tool-result
pair). All 159 CLI + 431 runtime + 115 api tests pass.
Two fixes:
1. compact.rs: When the compaction boundary falls at the start of a
tool-result turn, the preceding assistant turn with ToolUse would be
removed — leaving an orphaned role:tool message with no preceding
assistant tool_calls. OpenAI-compat backends reject this with 400.
Fix: after computing raw_keep_from, walk the boundary back until the
first preserved message is not a ToolResult (or its preceding assistant
has been included). Regression test added:
compaction_does_not_split_tool_use_tool_result_pair.
Source: gaebal-gajae multi-turn tool-call 400 repro 2026-04-09.
2. /cost resume: add JSON output:
{kind:cost, input_tokens, output_tokens, cache_creation_input_tokens,
cache_read_input_tokens, total_tokens}
159 CLI + 431 runtime tests pass. Fmt clean.
Two gaps closed:
1. /memory (resume): json field was None, emitting prose regardless of
--output-format json. Now emits:
{kind:memory, cwd, instruction_files:N, files:[{path,lines,preview}...]}
2. /providers (resume): had a spec entry but no parse arm, producing the
circular 'Unknown slash command: /providers — Did you mean /providers'.
Added 'providers' as an alias for 'doctor' in the parse match so
/providers dispatches to the same structured diagnostic output.
3. /doctor (resume): also wired json_value() so --output-format json
returns the structured doctor report instead of None.
Continues ROADMAP #26 resumed-command JSON parity track.
159 CLI tests pass, fmt clean.
/config resumed returned json:None, falling back to prose output even in
--output-format json mode. Adds render_config_json() that produces:
{
"kind": "config",
"cwd": "...",
"loaded_files": N,
"merged_keys": N,
"files": [{"path":"...","source":"user|project|local","loaded":true|false}, ...]
}
Wires it into the SlashCommand::Config resume arm alongside the existing
prose render. Continues the resumed-command JSON parity track (ROADMAP #26).
159 CLI tests pass, fmt clean.
Dogfood found that /tokens and /cache had spec entries (resume_supported:
true) but no parse arms in the command parser, resulting in:
'Unknown slash command: /tokens — Did you mean /tokens'
(the suggestion engine found the spec entry but parsing always failed)
Fix three things:
1. Add 'tokens' | 'cache' as aliases for 'stats' in the parse match so
the commands actually resolve to SlashCommand::Stats
2. Implement SlashCommand::Stats in the REPL dispatch — previously fell
through to 'Command registered but not yet implemented'. Now shows
cumulative token usage for the session.
3. Implement SlashCommand::Stats in run_resume_command — previously
returned 'unsupported resumed slash command'. Now emits:
text: Cost / Input tokens / Output tokens / Cache create / Cache read
json: {kind:stats, input_tokens, output_tokens, cache_*, total_tokens}
159 CLI tests pass, fmt clean.
Users launching claw from their home directory (or /) have no project
boundary — the agent can read/search the entire machine, often far beyond
the intended scope. kapcomunica in #claw-code reported exactly this:
'it searched my entire computer.'
Add warn_if_broad_cwd() called at prompt and REPL startup:
- checks if CWD == $HOME or CWD has no parent (fs root)
- prints a clear warning to stderr:
Warning: claw is running from a very broad directory (/home/user).
The agent can read and search everything under this path.
Consider running from inside your project: cd /path/to/project && claw
Warning fires on both claw (REPL) and claw prompt '...' paths.
Does not fire from project subdirectories. Uses std::env::var_os("HOME"),
no extra deps.
159 CLI tests pass, fmt clean.
When claw --output-format json --resume <session> /commit (or /plugins, etc.)
encountered an 'unsupported resumed slash command' error, it called
eprintln!() and exit(2) directly, bypassing both the main() JSON error
handler and the output_format check.
Fix: in both the slash-command parse-error path and the run_resume_command
Err path, check output_format and emit a structured JSON error:
{"type":"error","error":"unsupported resumed slash command","command":"/commit"}
Text mode unchanged (still exits 2 with prose to stderr).
Addresses the resumed-command parity gap (gaebal-gajae ROADMAP #26 track).
159 CLI tests pass, fmt clean.
When stdin is not a terminal (pipe or redirect) and no prompt is given on
the command line, claw was starting the interactive REPL and printing the
startup banner, then consuming the pipe without sending anything to the API.
Fix: in parse_args, when rest.is_empty() and stdin is not a terminal, read
stdin synchronously and dispatch as CliAction::Prompt instead of Repl.
Empty pipe still falls through to Repl (interactive launch with no input).
Before: echo 'hello' | claw -> startup banner + REPL start
After: echo 'hello' | claw -> dispatches as one-shot prompt
159 CLI tests pass, fmt clean.
Previously claw --resume <session> /diff would produce:
'git diff --cached failed: error: unknown option `cached\''
when the CWD was not inside a git project, because git falls back to
--no-index mode which does not support --cached.
Two fixes:
1. render_diff_report_for() checks 'git rev-parse --is-inside-work-tree'
before running git diff, and returns a human-readable message if not
in a git repo:
'Diff\n Result no git repository\n Detail <cwd> is not inside a git project'
2. resume /diff now uses std::env::current_dir() instead of the session
file's parent directory as the CWD for the diff (session parent dir
is the .claw/sessions/<id>/ directory, never a git repo).
159 CLI tests pass, fmt clean.
Previously claw --output-format json --resume <session> /history emitted
prose text regardless of the output format flag. Now emits structured JSON:
{"kind":"history","total":N,"showing":M,"entries":[{"timestamp_ms":...,"text":"..."},...]}
Mirrors the parity pattern established in ROADMAP #26 for other resume commands.
159 CLI tests pass, fmt clean.
When running claw --output-format json --resume <session> /status, the
JSON output had 'session' (full file path) but no 'session_id' field,
making it impossible for scripts to extract the loaded session ID.
Now extracts the session-id directory component from the session path
(e.g. .claw/sessions/<session-id>/session-xxx.jsonl → session-id)
and includes it as 'session_id' in the JSON status envelope.
159 CLI tests pass, fmt clean.
Previously 'claw state' printed an error message but exited 0, making it
impossible for scripts/CI to detect the absence of state without parsing
prose. Now propagates Err() to main() which exits 1 and formats the error
correctly for both text and --output-format json modes.
Text: 'error: no worker state file found at ... — run a worker first'
JSON: {"type":"error","error":"no worker state file found at ..."}
3 new tests in mod tests:
- rejects_invalid_reasoning_effort_value: confirms 'turbo' etc rejected at parse time
- accepts_valid_reasoning_effort_values: confirms low/medium/high accepted and threaded
- stub_commands_absent_from_repl_completions: asserts STUB_COMMANDS are not in completions
156 -> 159 CLI tests pass.
When claw --output-format json hits an error, the error was previously
printed as plain prose to stderr, making it invisible to downstream tooling
that parses JSON output. Now:
{"type":"error","error":"api returned 401 ..."}
Detection: scan argv at process exit for --output-format json or
--output-format=json. Non-JSON error path unchanged. 156 CLI tests pass.
Users were typing skill names (e.g. 'caveman', 'find-skills') directly in
the REPL and getting LLM responses instead of skill invocation. Only
'/skills <name>' triggered dispatch; bare names fell through to run_turn.
Fix: after slash-command parse returns None (bare text), check if the first
token looks like a skill name (alphanumeric/dash/underscore, no slash).
If resolve_skill_invocation() confirms the skill exists, dispatch the full
input as a skill prompt. Unknown words fall through unchanged.
156 CLI tests pass, fmt clean.
Previously any string was accepted and silently forwarded to the API,
which would fail at the provider with an unhelpful error. Now invalid
values produce a clear error at parse time:
invalid value for --reasoning-effort: 'xyz'; must be low, medium, or high
156 CLI tests pass, fmt clean.
The --help slash-command section was listing ~35 unimplemented commands
alongside working ones. Combined with the completions fix (c55c510), the
discovery surface now consistently shows only implemented commands.
Changes:
- commands crate: add render_slash_command_help_filtered(exclude: &[&str])
- move STUB_COMMANDS to module-level const in main.rs (reused by both
completions and help rendering)
- replace render_slash_command_help() with filtered variant at all
help-rendering call sites
156 CLI tests pass, fmt clean.
'claw prompt --help' was triggering an API call instead of showing help
because --help was parsed as part of the prompt args. Now '--help' after
known pass-through subcommands (prompt, login, logout, version, state,
init, export, commit, pr, issue) sets wants_help=true and shows the
top-level help page.
Subcommands that consume their own args (agents, mcp, plugins, skills)
and local help-topic subcommands (status, sandbox, doctor) are excluded
from this interception so their existing --help handling is preserved.
156 CLI tests pass, fmt clean.
Commands registered in the spec list but not yet implemented in this build
were appearing in REPL tab-completions, making the discovery surface
over-promise what actually works. Users (mezz2301) reported 'many features
are not supported' after discovering these through completions.
Add STUB_COMMANDS exclusion list in slash_command_completion_candidates_with_sessions.
Excluded: login logout vim upgrade stats share feedback files fast exit
summary desktop brief advisor stickers insights thinkback release-notes
security-review keybindings privacy-settings plan review tasks theme
voice usage rename copy hooks context color effort branch rewind ide
tag output-style add-dir
These commands still parse and run (with the 'not yet implemented' message
for users who type them directly), but they no longer surface as
tab-completion candidates.
Parse --reasoning-effort <low|medium|high> in parse_args, thread through
CliAction::Prompt and CliAction::Repl, LiveCli::set_reasoning_effort(),
AnthropicRuntimeClient.reasoning_effort field, and MessageRequest.reasoning_effort.
Changes:
- parse_args: new --reasoning-effort / --reasoning-effort=VAL flag arms
- AnthropicRuntimeClient: new reasoning_effort field + set_reasoning_effort() method
- LiveCli: new set_reasoning_effort() that reaches through BuiltRuntime -> ConversationRuntime -> api_client_mut()
- runtime::ConversationRuntime: new pub api_client_mut() accessor
- MessageRequest construction: reasoning_effort: self.reasoning_effort.clone()
- run_repl(): accepts and applies reasoning_effort parameter
- parse_direct_slash_cli_action(): propagates reasoning_effort
All 156 CLI tests pass, all api tests pass, cargo fmt clean.
Adds reasoning_effort: Option<String> to CliAction::Prompt and
CliAction::Repl enum variants. All constructor and pattern sites updated.
All test literals updated with reasoning_effort: None.
156 cli tests pass, fmt clean. The --reasoning-effort flag parse and
propagation to AnthropicRuntimeClient remains as follow-up work.
Add rust/crates/rusty-claude-cli/build.rs that:
- Captures git rev-parse --short HEAD at build time → GIT_SHA env
- Reads Cargo's TARGET env var → TARGET env
- Derives BUILD_DATE from SOURCE_DATE_EPOCH / BUILD_DATE env or
the current date via `date +%Y-%m-%d` fallback
- Registers rerun-if-changed on .git/HEAD and .git/refs so the SHA
stays fresh across commits
Update main.rs DEFAULT_DATE to pick up BUILD_DATE from option_env!()
instead of the hardcoded 2026-03-31 static string.
Before: `claw --version` always showed Git SHA: unknown, Target: unknown,
Build date: 2026-03-31 in local builds.
After: e.g. Git SHA: 7f53d82, Target: aarch64-apple-darwin, Build date: 2026-04-08
Generated by droid (Kimi K2.5 Turbo) via acpx (wrote build.rs),
cleaned up by Jobdori (added BUILD_DATE step, updated main.rs const).
Co-Authored-By: Droid <noreply@factory.ai>
The CLI entry point (build_runtime_with_plugin_state in main.rs)
was hardcoded to always instantiate AnthropicRuntimeClient with an
AnthropicClient, regardless of what detect_provider_kind(model)
returned. This meant `--model openai/gpt-4` with OPENAI_API_KEY
set and no ANTHROPIC_* vars still failed with "missing Anthropic
credentials" because the CLI never dispatched to the OpenAI-compat
backend that already exists in the api crate.
Root cause: AnthropicRuntimeClient.client was typed as
AnthropicClient (concrete) rather than ApiProviderClient (enum).
The api crate already had a ProviderClient enum with Anthropic /
Xai / OpenAi variants that dispatches correctly via
detect_provider_kind, plus a unified MessageStream enum that wraps
both anthropic::MessageStream and openai_compat::MessageStream
with the same next_event() -> StreamEvent interface. The CLI just
wasn't using it.
Changes (1 file, +59 -7):
- Import api::ProviderClient as ApiProviderClient
- Change AnthropicRuntimeClient.client from AnthropicClient to
ApiProviderClient
- In AnthropicRuntimeClient::new(), dispatch based on
detect_provider_kind(&resolved_model):
* Anthropic: build AnthropicClient directly with
resolve_cli_auth_source() + api::read_base_url() +
PromptCache (preserves ANTHROPIC_BASE_URL override for mock
test harness and the session-scoped prompt cache)
* xAI / OpenAi: delegate to
ApiProviderClient::from_model_with_anthropic_auth which routes
to OpenAiCompatClient::from_env with the matching config
(reads OPENAI_API_KEY/XAI_API_KEY/DASHSCOPE_API_KEY and their
BASE_URL overrides internally)
- Change push_prompt_cache_record to take &ApiProviderClient
(ProviderClient::take_last_prompt_cache_record returns None for
non-Anthropic variants, so the helper is a no-op on
OpenAI-compat providers without extra branching)
What this unlocks for users:
claw --model openai/gpt-4.1-mini prompt 'hello' # OpenAI
claw --model grok-3 prompt 'hello' # xAI
claw --model qwen-plus prompt 'hello' # DashScope
OPENAI_BASE_URL=https://openrouter.ai/api/v1 \
claw --model openai/anthropic/claude-sonnet-4 prompt 'hello' # OpenRouter
All previously broken, now routed correctly by prefix.
Verification:
- cargo build --release -p rusty-claude-cli: clean
- cargo test --release -p rusty-claude-cli: 182 tests, 0 failures
(including compact_output tests that exercise the Anthropic mock)
- cargo fmt --all: clean
- cargo clippy --workspace: warnings-only (pre-existing)
- cargo test --release --workspace: all crates green except one
pre-existing race in runtime::config::tests (passes in isolation)
Source: live users nicma (1491342350960562277) and Jengro
(1491345009021030533) in #claw-code on 2026-04-08.
- compact flag: was parsed then discarded (`compact: _`) instead of
passed to `run_turn_with_output` — hardcoded `false` meant --compact
never took effect
- piped stdin vs permission prompter: `read_piped_stdin()` consumed all
stdin before `CliPermissionPrompter::decide()` could read interactive
approval answers; now only consumes stdin as prompt context when
permission mode is `DangerFullAccess` (fully unattended)
- session resolver: `resolve_managed_session_path` and
`list_managed_sessions` now fall back to the pre-isolation flat
`.claw/sessions/` layout so legacy sessions remain accessible
- help assertion: match on stable prefix after `/session delete` was
added in batch 5
- prompt shorthand: fix copy-paste that changed expected prompt from
"help me debug" to "$help overview"
- mock parity harness: filter captured requests to `/v1/messages` path
only, excluding count_tokens preflight calls added by `be561bf`
All 6 failures were pre-existing but masked because `client_integration`
always failed first (fixed in 8c6dfe5).
Workspace: 810+ tests passing, 0 failing.
build_runtime_runs_plugin_lifecycle_init_and_shutdown was the only test
that set/removed ANTHROPIC_API_KEY without holding the env_lock mutex.
Under parallel workspace execution, other tests racing on the same env
var could wipe the key mid-construction, causing a flaky credential error.
Root cause: process-wide env vars are shared mutable state. All other
tests that touch ANTHROPIC_API_KEY already use env_lock(). This test
was the only holdout.
Fix: add let _guard = env_lock(); at the top of the test.
MessageRequest was missing standard OpenAI-compatible generation tuning
parameters. Callers had no way to control temperature, top_p,
frequency_penalty, presence_penalty, or stop sequences.
Changes:
- Added 5 optional fields to MessageRequest (all Option, None by default)
- Wired into build_chat_completion_request: only included in payload when set
- All existing construction sites updated with ..Default::default()
- MessageRequest now derives Default for ergonomic partial construction
Tests added:
- tuning_params_included_in_payload_when_set: all 5 params flow into JSON
- tuning_params_omitted_from_payload_when_none: absent params stay absent
83 api lib tests passing, 0 failing.
cargo check --workspace: 0 warnings.
WorkerStatus is fully tracked in worker_boot.rs but was invisible to
external observers (clawhip, orchestrators) because opencode serve's
HTTP server is upstream and not ours to extend.
Solution: atomic file-based observability.
- emit_state_file() writes .claw/worker-state.json on every push_event()
call (tmp write + rename for atomicity)
- Snapshot includes: worker_id, status, is_ready, trust_gate_cleared,
prompt_in_flight, last_event, updated_at
- Add 'claw state' CLI subcommand to read and print the file
- Add regression test: emit_state_file_writes_worker_status_on_transition
verifies spawning→ready_for_prompt transition is reflected on disk
This closes the /state dogfood gap without requiring any upstream
opencode changes. Clawhip can now distinguish a truly stalled worker
(status: trust_required or running with no recent updated_at) from a
quiet-but-progressing one.
Add missing imports to test module:
- PromptHistoryEntry, render_prompt_history_report, parse_history_count
- parse_export_args, render_session_markdown
- summarize_tool_payload_for_markdown, short_tool_id
Fixes test compilation errors introduced by new session and export
features from batch 5/6 work.
The CLI was using a flat cwd/.claw/sessions/ path without workspace
fingerprinting, while SessionStore::from_cwd() adds a hash subdirectory.
This mismatch meant the isolation machinery existed but wasn't actually
used by the main session management codepath.
Now sessions_dir() delegates to SessionStore::from_cwd(), ensuring all
session operations use workspace-fingerprinted directories.
The CLI already reframes direct preflight and provider oversized-request
errors, but retry-wrapped provider failures still fell back to the generic
retry-exhausted surface because the user-visible formatter keyed off the
safe failure class. Route formatting through nested context-window
detection so wrapped provider failures keep the same compact/reduce-scope
guidance.
Constraint: Keep the fix UX-scoped without widening broader failure classification behavior
Rejected: Reorder safe_failure_class for all RetriesExhausted errors | broader semantic change than needed for this issue
Confidence: high
Scope-risk: narrow
Directive: Keep context-window rendering keyed to nested error inspection so provider wrappers do not lose recovery guidance
Tested: cargo fmt --check; cargo test -p rusty-claude-cli context_window; cargo test -p api oversized
Not-tested: Full workspace test suite
The CLI still treated every /skills payload other than list/install/help as local usage text, so skills that appeared in /skills could not actually be invoked. This restores prompt dispatch for /skills <skill> [args], keeps list/install on the local path, and shares skill resolution with the Skill tool so project-local and legacy /commands entries resolve consistently.
Constraint: --resume local slash execution still only supports local commands without provider turns
Rejected: Implement full resumed prompt-turn execution for /skills | larger behavior change outside this bugfix
Rejected: Keep separate skill lookups in tools and commands | drift already caused listing/invocation mismatches
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep /skills discovery, CLI prompt dispatch, and Tool Skill resolution on the same registry semantics
Tested: cargo fmt --all; cargo clippy -p commands -p tools -p rusty-claude-cli --all-targets -- -D warnings; cargo test --workspace -- --nocapture
Not-tested: Live provider-backed /skills invocation against external skill packs in an interactive REPL
Dogfood showed oversized requests still surfacing as raw hard errors, even when claw could tell the user exactly how to recover. This keeps context-window failures classified, recognizes the same failure when it comes back from a provider response, and renders recovery steps that point operators at the existing compaction and fresh-session paths instead of a provider-style dump.
Constraint: Keep the failure class explicit so automation and operators can still distinguish context-window exhaustion from generic provider failures
Constraint: Reuse existing /compact and session-reset UX instead of inventing a new recovery workflow
Rejected: Auto-run compaction on failure | mutates session state on an error path the user may want to inspect first
Rejected: Only prettify local preflight failures | provider-returned context-window errors would still leak raw failure text
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep provider-side context-window detection aligned with real oversized-request messages before broadening the marker list
Tested: cargo fmt --all --check
Tested: cargo test -p api
Tested: cargo test -p rusty-claude-cli
Tested: cargo clippy -p api -p rusty-claude-cli --all-targets -- -D warnings
Not-tested: cargo test --workspace
Resumed slash dispatch was still dropping back to prose for several JSON-capable local commands, which forced automation to special-case direct CLI invocations versus --resume flows. This routes resumed local-command handlers through the same structured JSON payloads used by direct status, sandbox, inventory, version, and init commands, and records the inventory parity audit result in the roadmap.
Constraint: Text-mode resumed output must stay unchanged for existing shell users
Rejected: Teach callers to scrape resumed text output | brittle and defeats the JSON contract
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When a direct local command has a JSON renderer, keep resumed slash dispatch on the same serializer instead of adding one-off format branches
Tested: cargo fmt --check; cargo test --workspace; cargo clippy --workspace --all-targets -- -D warnings
Not-tested: Live provider-backed REPL resume flows outside the local test harness
`claw agents --output-format json` was still wrapping the text report,
which meant automation could not distinguish empty inventories from
populated agent definitions. Add a dedicated structured handler in the
commands crate, wire the CLI to it, and extend the contracts to cover
both empty and populated agent listings.
Constraint: Keep text-mode `claw agents` output unchanged while aligning JSON behavior with existing structured inventory handlers
Rejected: Parse the text report into JSON in the CLI layer | brittle duplication and no reusable structured handler
Confidence: high
Scope-risk: narrow
Directive: Keep inventory subcommands on dedicated structured handlers instead of serializing human-readable reports
Tested: cargo test -p commands renders_agents_reports_as_json; cargo test -p rusty-claude-cli --test output_format_contract; cargo test --workspace; cargo fmt --check; cargo clippy --workspace --all-targets -- -D warnings
Not-tested: Manual invocation of `claw agents --output-format json` outside automated tests
Issue #22 was triggered by generic upstream fatal wrappers that only surfaced 'Something went wrong', which left repeated Jobdori-style failures opaque in the CLI. Capture provider request ids on error responses, classify the known generic wrapper as provider_internal, and prefix the user-visible runtime error with the failure class plus session/trace identifiers so operators can correlate the failure quickly.
Constraint: Keep the fix small and user-safe without redesigning the broader runtime error taxonomy
Constraint: Preserve existing non-generic error text unless the wrapper is the known opaque fatal surface
Rejected: Broadly rewriting every runtime error into classified envelopes | unnecessary scope expansion for issue #22
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If more opaque wrappers appear, extend the marker list and classification helper rather than reintroducing raw wrapper text alone
Tested: cargo test -p api detects_generic_fatal_wrapper_and_classifies_it_as_provider_internal -- --nocapture; cargo test -p api retries_exhausted_preserves_nested_request_id_and_failure_class -- --nocapture; cargo test -p rusty-claude-cli opaque_provider_wrapper_surfaces_failure_class_session_and_trace -- --nocapture; cargo test -p rusty-claude-cli retry_exhaustion_preserves_internal_failure_class_for_generic_provider_wrapper -- --nocapture; cargo test --workspace
Not-tested: Live upstream reproduction of the Jobdori failure against a real provider session
The resumed slash-command path built a reduced status JSON payload by hand, so it drifted from the fresh status schema and dropped metadata like model, permission mode, workspace counters, and sandbox details. Reuse a shared status JSON builder for both code paths and tighten the resume regression tests to lock parity in place.
Constraint: Resume mode does not carry an active runtime model, so restored sessions continue to report the existing restored-session sentinel value
Rejected: Copy the fresh status JSON shape into the resume path again | would recreate the same schema drift risk
Confidence: high
Scope-risk: narrow
Directive: Keep resumed and fresh /status JSON on the same helper so future schema changes stay in parity
Tested: Reproduced failure in temporary HEAD worktree with strengthened resumed_status_command_emits_structured_json_when_requested
Tested: cargo test -p rusty-claude-cli resumed_status_command_emits_structured_json_when_requested --test resume_slash_commands -- --exact --nocapture
Tested: cargo test -p rusty-claude-cli doctor_and_resume_status_emit_json_when_requested --test output_format_contract -- --exact --nocapture
Tested: cargo test --workspace
Tested: cargo fmt --check
Tested: cargo clippy --workspace --all-targets -- -D warnings
Finish the remaining roadmap work by making direct CLI JSON output deterministic across the non-interactive surface, restoring the degraded-startup MCP test as a real workspace test, and adding branch-lock plus commit-lineage primitives so downstream lane consumers can distinguish superseded worktree commits from canonical lineage.
Constraint: Keep the user-facing config namespace centered on .claw while preserving legacy fallback discovery for compatibility
Constraint: Verification needed to stay clean-room and reproducible from the checked-in workspace alone
Rejected: Leave the output-format contract implied by ad-hoc smoke runs only | too easy for direct CLI regressions to slip back into prose-only output
Rejected: Keep commit provenance as free-form detail text | downstream consumers need structured branch/worktree/supersession metadata
Confidence: medium
Scope-risk: moderate
Directive: Extend the JSON contract through the same direct CLI entrypoints instead of adding one-off serializers on parallel code paths
Tested: python .github/scripts/check_doc_source_of_truth.py
Tested: cd rust && cargo fmt --all --check
Tested: cd rust && cargo test --workspace
Tested: cd rust && cargo clippy -p commands -p tools -p rusty-claude-cli --all-targets --no-deps -- -D warnings
Not-tested: full cargo clippy --workspace --all-targets -- -D warnings still reports unrelated pre-existing runtime lint debt outside this change set
The skills and mcp inventory handlers were still emitting prose tables even when the global --output-format json flag was set. This wires structured JSON renderers into the command handlers and CLI dispatch so direct invocations and resumed slash-command execution both return machine-readable payloads while preserving existing text output in the REPL path.
Constraint: Must preserve existing text output and help behavior for interactive slash commands
Rejected: Parse existing prose tables into JSON at the CLI edge | brittle and loses structured fields
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep text and JSON variants driven by the same command parsing branches so --output-format stays deterministic across entry points
Tested: cargo test -p commands
Tested: cargo test -p rusty-claude-cli
Not-tested: Manual invocation against a live user skills registry or external MCP services
Promote doctor into a real top-level CLI action, reuse the same local report for resumed and REPL doctor invocations, and intercept doctor/status/sandbox help flags before prompt-mode dispatch. The parser change also closes the help fallthrough that previously wandered into runtime startup for local-info commands.
Constraint: Preserve prompt shorthand for normal multi-word text input while fixing exact local subcommand help paths
Rejected: Route \7[1G[2K[m⠋ 🦀 Thinking...[0m8[1G[2K[m✘ ❌ Request failed
[0m through prompt/slash guidance | still shells out through the wrong surface and keeps health checks hidden
Rejected: Reuse the status report as doctor output | status does not explain auth/config health or expose a dedicated diagnostic summary
Confidence: high
Scope-risk: narrow
Directive: Keep doctor local-only unless an explicit network probe is intentionally added and separately tested
Tested: cargo build -p rusty-claude-cli; cargo test -p rusty-claude-cli; cargo run -p rusty-claude-cli -- doctor --help; CLAW_CONFIG_HOME=/tmp/tmp.7pm9SVzOPN ANTHROPIC_API_KEY= ANTHROPIC_AUTH_TOKEN= cargo run -p rusty-claude-cli -- doctor
Not-tested: direct /doctor outside the REPL remains interactive-only
The global --output-format json flag already reached prompt-mode responses, but
status and sandbox still bypassed that path and printed human-readable tables.
This change threads the selected output format through direct command aliases
and resumed slash-command execution so status queries emit valid structured
JSON instead of mixed prose.
It also adds end-to-end regression coverage for direct status/sandbox JSON
and resumed /status JSON so shell automation can rely on stable parsing.
Constraint: Global output formatting must stay compatible with existing text-mode reports
Rejected: Require callers to scrape text status tables | fragile and breaks automation
Confidence: high
Scope-risk: narrow
Directive: New direct commands that honor --output-format should thread the format through CliAction and resumed slash execution paths
Tested: cargo build -p rusty-claude-cli
Tested: cargo test -p rusty-claude-cli -- --nocapture
Tested: cargo test --workspace
Tested: cargo run -q -p rusty-claude-cli -- --output-format json status
Tested: cargo run -q -p rusty-claude-cli -- --output-format json sandbox
Not-tested: cargo clippy --workspace --all-targets -- -D warnings (fails in pre-existing runtime files unrelated to this change)
The worker boot registry now exposes the requested lifecycle states, emits structured trust and prompt-delivery events, and recovers from shell or wrong-target prompt delivery by replaying the last prompt. Supporting fixes keep MCP remote config parsing backwards-compatible and make CLI argument parsing less dependent on ambient config and cwd state so the workspace stays green under full parallel test runs.
Constraint: Worker prompts must not be dispatched before a confirmed ready_for_prompt handshake
Constraint: Prompt misdelivery recovery must stay minimal and avoid new dependencies
Rejected: Keep prompt_accepted and blocked as public lifecycle states | user requested the narrower explicit state set
Rejected: Treat url-only MCP server configs as invalid | existing CLI/runtime tests still rely on that shorthand
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Preserve prompt_in_flight semantics when extending worker boot; misdelivery detection depends on it
Tested: cargo build --workspace; cargo test --workspace
Not-tested: Live tmux worker delivery against a real external coding agent pane
Add MCP structured degraded-startup classification (P2.10):
- classify MCP failures as startup/handshake/config/partial
- expose failed_servers + recovery_recommendations in tool output
- add mcp_degraded output field with server_name, failure_mode, recoverable
Canonical lane event schema (P2.7):
- add LaneEventName variants for all lifecycle states
- wire LaneEvent::new with full 3-arg signature (event, status, emitted_at)
- emit typed events for Started, Blocked, Failed, Finished
Fix let mut executor for search test binary
Fix lane_completion unused import warnings
Note: mcp_stdio::manager_discovery_report test has pre-existing failure on clean main, unrelated to this commit.
Replace with_current_dir+render_diff_report() with direct render_diff_report_for(&root)
calls in the three diff-report tests. The env_lock mutex only serializes within one
test binary; cargo test --workspace runs binaries in parallel, so set_current_dir races
were possible across binaries. render_diff_report_for(cwd) accepts an explicit path
and requires no global state mutation, making the tests reliably green under full
workspace parallelism.
This resolves the stale-branch merge against origin/main, keeps the MCP runtime wiring, and preserves prompt-approved CLI tool execution after the mock parity harness additions landed upstream.
Constraint: Branch had to absorb origin/main changes through a contentful merge before more MCP work
Constraint: Prompt-approved runtime tool execution must continue working with new CLI/mock parity coverage
Rejected: Keep permission enforcer attached inside CliToolExecutor for conversation turns | caused prompt-approved bash parity flow to fail as a tool error
Rejected: Defer the merge and continue on stale history | would leave the lane red against current main
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Runtime permission policy and executor-side permission enforcement are separate layers; do not reapply executor enforcement to conversation turns without revalidating mock parity harness approval flows
Tested: cargo test -p rusty-claude-cli --test mock_parity_harness -- --nocapture; cargo test -p rusty-claude-cli -- --nocapture; cargo test --workspace -- --nocapture
Not-tested: Additional live remote/provider scenarios beyond the existing workspace suite
This wires configured MCP servers into the CLI/runtime path so discovered
MCP tools, resource wrappers, search visibility, shutdown handling, and
best-effort discovery all work together instead of living as isolated
runtime primitives.
Constraint: Keep non-MCP startup flows working without new required config
Constraint: Preserve partial availability when one configured MCP server fails discovery
Rejected: Fail runtime startup on any MCP discovery error | too brittle for mixed healthy/broken server configs
Rejected: Keep MCP support runtime-only without registry wiring | left discovery and invocation unreachable from the CLI tool lane
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Runtime MCP tools are registry-backed but executed through CliToolExecutor state; keep future tool-registry changes aligned with that split
Tested: cargo test -p runtime mcp -- --nocapture; cargo test -p tools -- --nocapture; cargo test -p rusty-claude-cli -- --nocapture; cargo test --workspace -- --nocapture
Not-tested: Live remote MCP transports (http/sse/ws/sdk) remain unsupported in the CLI execution path
Tests relying on PermissionMode::DangerFullAccess as default were
flaky under --workspace runs because other tests set
RUSTY_CLAUDE_PERMISSION_MODE without cleanup. Added env_lock() and
explicit env var removal to 7 affected tests.
Fixes: workspace-level cargo test flake (1 random test fails per run)
Remove the #[ignore] gate from startup_banner_mentions_workflow_completions
by injecting a dummy ANTHROPIC_API_KEY. The test exercises LiveCli banner
rendering, not API calls. Cleanup env var after test.
Test suite now 102/102 in CLI crate (was 101 + 1 ignored).
Inject a dummy ANTHROPIC_API_KEY for
build_runtime_runs_plugin_lifecycle_init_and_shutdown so the test
exercises plugin init/shutdown without requiring real credentials.
The API client is constructed but never used for streaming.
Clean up the env var after the test to avoid polluting parallel tests.
PARITY.md is stale relative to the current Rust plugin pipeline: plugin manifests, tool loading, and lifecycle primitives already exist, but runtime construction only consumed plugin tools. This change routes enabled plugin hooks into the runtime feature config, initializes plugin lifecycle commands when a runtime is built, and shuts plugins down when runtimes are replaced or dropped.\n\nThe test coverage exercises the new runtime plugin-state builder and verifies init/shutdown execution without relying on global cwd or config-home mutation, so the existing CLI suite stays stable under parallel execution.\n\nConstraint: Keep the change inside the current worktree and avoid touching unrelated pre-existing edits\nRejected: Add plugin hook execution inside the tools crate directly | runtime feature merging is the existing execution boundary\nRejected: Use process-global CLAW_CONFIG_HOME/current_dir in tests | races with the existing parallel CLI test suite\nConfidence: high\nScope-risk: moderate\nReversibility: clean\nDirective: Preserve plugin runtime shutdown when rebuilding LiveCli runtimes or temporary turn runtimes\nTested: cargo test -p rusty-claude-cli build_runtime_\nTested: cargo test -p rusty-claude-cli\nNot-tested: End-to-end live REPL session with a real plugin outside the test harness
PARITY.md called out missing MCP management in the Rust CLI, so this adds a focused read-only /mcp path instead of expanding the broader config surface first.
The new command works in the REPL, with --resume, and as a direct 7[1G[2K[m⠋ 🦀 Thinking...[0m8[1G[2K[m✘ ❌ Request failed
[0m entrypoint. It lists merged MCP server definitions, supports detailed inspection for one server, and adds targeted tests for parsing, help text, completion hints, and config-backed rendering.
Constraint: Keep the enhancement inside the existing Rust slash-command architecture
Rejected: Extend /config with a raw mcp dump only | less discoverable than a dedicated MCP workflow
Confidence: high
Scope-risk: narrow
Directive: Keep /mcp read-only unless MCP lifecycle commands gain shared runtime orchestration
Tested: cargo test -p commands parses_supported_slash_commands
Tested: cargo test -p commands rejects_invalid_mcp_arguments
Tested: cargo test -p commands renders_help_from_shared_specs
Tested: cargo test -p commands renders_per_command_help_detail_for_mcp
Tested: cargo test -p commands ignores_unknown_or_runtime_bound_slash_commands
Tested: cargo test -p commands mcp_usage_supports_help_and_unexpected_args
Tested: cargo test -p commands renders_mcp_reports_from_loaded_config
Tested: cargo test -p rusty-claude-cli parses_login_and_logout_subcommands
Tested: cargo test -p rusty-claude-cli parses_direct_agents_mcp_and_skills_slash_commands
Tested: cargo test -p rusty-claude-cli repl_help_includes_shared_commands_and_exit
Tested: cargo test -p rusty-claude-cli completion_candidates_include_workflow_shortcuts_and_dynamic_sessions
Tested: cargo test -p rusty-claude-cli resume_supported_command_list_matches_expected_surface
Tested: cargo test -p rusty-claude-cli init_help_mentions_direct_subcommand
Tested: cargo run -p rusty-claude-cli -- mcp help
Not-tested: Live MCP server connectivity against a real remote or stdio backend
The Rust commands layer could list skills, but it had no concrete install path.
This change adds /skills install <path> and matching direct CLI parsing so a
skill directory or markdown file can be copied into the user skill registry
with a normalized invocation name and a structured install report.
Constraint: Keep the enhancement inside the existing Rust commands surface without adding dependencies
Rejected: Full project-scoped registry management | larger parity surface than needed for one landed path
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If project-scoped skill installation is added later, keep the install target explicit so command discovery and tool resolution stay aligned
Tested: cargo test -p commands
Tested: cargo clippy -p commands --tests -- -D warnings
Tested: cargo test -p rusty-claude-cli parses_direct_agents_and_skills_slash_commands
Tested: cargo test -p rusty-claude-cli parses_login_and_logout_subcommands
Tested: cargo clippy -p rusty-claude-cli --tests -- -D warnings
Not-tested: End-to-end interactive REPL invocation of /skills install against a real user skill registry
PARITY.md and the current Rust CLI UX both pointed at session-management polish as a worthwhile parity lane. The existing /clear flow reset the live REPL without telling the user how to get back, and the resumed /clear path overwrote the saved session file in place with no recovery handle.
This change keeps the existing clear semantics but makes them safer and more legible. Live clears now print the previous session id and a resume hint, while resumed clears write a sibling backup before resetting the requested session file and report both the backup path and the new session id.
Constraint: Keep /clear compatible with follow-on commands in the same --resume invocation
Rejected: Switch resumed /clear to a brand-new primary session path | would break the expected in-place reset semantics for chained resume commands
Confidence: high
Scope-risk: narrow
Directive: Preserve explicit recovery hints in /clear output if session lifecycle behavior changes again
Tested: cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test resume_slash_commands
Tested: cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --bin claw clear_command_requires_explicit_confirmation_flag
Not-tested: Manual interactive REPL /clear run
Runtime config already parsed merged permissionMode/defaultMode values, but the CLI defaulted straight from RUSTY_CLAUDE_PERMISSION_MODE to danger-full-access. This wires the default permission resolver through the merged runtime config so project/local settings take effect when no env override is present, while keeping env precedence and locking the behavior with regression tests.
Constraint: Must preserve explicit env override precedence over project config
Rejected: Thread permission source state through every CLI action | unnecessary refactor for a focused parity fix
Confidence: high
Scope-risk: narrow
Directive: Keep config-derived defaults behind explicit CLI/env overrides unless the upstream precedence contract changes
Tested: cargo test -p rusty-claude-cli permission_mode -- --nocapture
Tested: cargo test -p rusty-claude-cli defaults_to_repl_when_no_args -- --nocapture
Not-tested: interactive REPL/manual /permissions flows
CLI binary has functions from multiple parity branches that aren't fully
wired up yet. Allow dead_code and related clippy lints at crate level
until the wiring is complete.
- Add centralized validate_slash_command_input for all slash commands
- Rich error messages and per-command help detail
- Wire validation into CLI entrypoints in main.rs
- Consistent /agents and /skills usage surface
- Verified: cargo test -p commands 22 passed, integration test passed, clippy clean
- Add SlashCommandParseError type for structured parse failures
- Validate arguments for all arg-taking commands (permissions, config, session, plugin, agents, skills, teleport, resume)
- No-arg commands now reject unexpected arguments
- Error messages include help text with usage/summary/category
- 21 commands tests pass, clippy clean
- Replace .into_iter() with .iter() on slice reference
- Use String::from() to avoid assigning_clones false positive
- Mark startup_banner test as #[ignore] (requires ANTHROPIC_API_KEY)
- Apply cargo fmt to all Rust sources
The release-harness merge taught --resume to keep multi-token slash commands together, but that also misclassified absolute session paths as slash commands. This follow-up keeps the latest-session shortcut for real slash commands while still treating absolute and relative filesystem paths as explicit resume targets, which restores the new integration test and the intended resume flow.
Constraint: --resume must accept both implicit latest-session shortcuts and absolute filesystem paths
Rejected: Require --resume latest for all slash-command-only invocations | breaks the new shortcut UX merged from 9103/9202
Confidence: high
Scope-risk: narrow
Directive: Distinguish slash commands with looks_like_slash_command_token before assuming a leading slash means latest-session shorthand
Tested: cargo build -p rusty-claude-cli; cargo test -p rusty-claude-cli
Not-tested: Non-UTF8 session path handling
Add explicit top-level aliases for help/version/status/sandbox and return guidance for lone slash-command names so common command-style invocations do not fall through into prompt execution and unexpected auth/API work.
Constraint: Keep shorthand prompt mode working for natural-language multi-word input
Rejected: Remove bare prompt shorthand entirely | too disruptive to existing UX
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep single-word command guards aligned with the slash-command surface when adding new top-level UX affordances
Tested: cargo build -p rusty-claude-cli; cargo test -p rusty-claude-cli parses_single_word_command_aliases_without_falling_back_to_prompt_mode -- --nocapture; cargo test -p rusty-claude-cli single_word_slash_command_names_return_guidance_instead_of_hitting_prompt_mode -- --nocapture; cargo test -p rusty-claude-cli multi_word_prompt_still_uses_shorthand_prompt_mode -- --nocapture; cargo test -p rusty-claude-cli init_help_mentions_direct_subcommand -- --nocapture; cargo test -p rusty-claude-cli parses_login_and_logout_subcommands -- --nocapture; cargo test -p rusty-claude-cli parses_direct_agents_and_skills_slash_commands -- --nocapture; ./target/debug/claw help; ./target/debug/claw version; ./target/debug/claw status; ./target/debug/claw sandbox; ./target/debug/claw cost
Not-tested: cargo test -p rusty-claude-cli -- --nocapture still has a pre-existing failure in tests::init_template_mentions_detected_rust_workspace
Not-tested: cargo clippy -p rusty-claude-cli -- -D warnings still fails on pre-existing runtime crate lints
The release harness advertised resumed slash commands like /export <file> and /clear --confirm, but argv parsing split every slash-prefixed token into a new command. That made the claw binary reject legitimate resumed command sequences and quietly miss the caller-provided export target.
This change teaches --resume parsing to keep command arguments attached, including absolute export paths, and locks the behavior with both parser regressions and a binary-level smoke test that exercises the real claw resume path.
Constraint: Keep the scope to a high-confidence release-path fix that fits a ~1 hour hardening pass
Rejected: Broad REPL or network end-to-end coverage expansion | too slow and too wide for the release-confidence target
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If new resume-supported commands accept slash-prefixed literals, extend the resume parser heuristics and add binary coverage for them
Tested: cargo test --workspace; cargo test -p rusty-claude-cli --test resume_slash_commands; cargo test -p rusty-claude-cli parses_resume_flag_with_absolute_export_path -- --exact
Not-tested: cargo clippy --workspace --all-targets -- -D warnings currently fails on pre-existing runtime/conversation/session lints outside this change
Add a focused GitHub Actions workflow for pull requests into main plus
manual dispatch. The workflow checks workspace formatting and runs the
rusty-claude-cli crate tests so we get a real signal on the active Rust
surface without widening scope into a full matrix.
Because the workspace was not rustfmt-clean, include the formatting-only
updates needed for the new fmt gate to pass immediately.
Constraint: Keep scope to a fast, low-noise Rust PR gate
Constraint: CI should validate formatting and rusty-claude-cli without expanding to full workspace coverage
Rejected: Full workspace test or clippy matrix | too broad for the one-hour shipping window
Rejected: Add fmt CI without reformatting the workspace | the new gate would fail on arrival
Confidence: high
Scope-risk: narrow
Directive: Keep this workflow focused unless release requirements justify broader coverage
Tested: cargo fmt --all -- --check
Tested: cargo test -p rusty-claude-cli
Tested: YAML parse of .github/workflows/rust-ci.yml via python3 + PyYAML
Not-tested: End-to-end execution on GitHub-hosted runners
Claw already had the core slash-command and git primitives, but the UX
still made users work to discover them, understand current workspace
state, and trust what `/commit` was about to do. This change tightens
that flow in the same places Codex-style CLIs do: command discovery,
live status, typo recovery, and commit preflight/output.
The REPL banner and `/help` now surface a clearer starter path, unknown
slash commands suggest likely matches, `/status` includes actionable git
state, and `/commit` explains what it is staging and committing before
and after the model writes the Lore message. I also cleared the
workspace's existing clippy blockers so the verification lane can stay
fully green.
Constraint: Improve UX inside the existing Rust CLI surfaces without adding new dependencies
Rejected: Add more slash commands first | discoverability and feedback were the bigger friction points
Rejected: Split verification lint fixes into a second commit | user requested one solid commit
Confidence: high
Scope-risk: moderate
Directive: Keep slash discoverability, status reporting, and commit reporting aligned so `/help`, `/status`, and `/commit` tell the same workflow story
Tested: cargo fmt --all; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace
Not-tested: Manual interactive REPL session against live Anthropic/xAI endpoints
Claw already exposes useful orchestration primitives such as session forking,
resume, ultraplan, agents, and skills, but compared with OmO/OMX
they were still high-friction to discover and re-type during live
operator loops.
This change makes the REPL act more like an orchestration console by
refreshing context-aware tab completions before each prompt, allowing
completion after slash-command arguments, and surfacing common workflow
paths such as model aliases, permission modes, and recent session IDs.
The startup banner and REPL help now advertise that guidance so the
capability is visible instead of hidden.
Constraint: Keep the improvement low-risk and REPL-local without adding dependencies or new command semantics
Rejected: Add a brand new orchestration slash command | higher UX surface area and more docs burden than a discoverability fix
Rejected: Implement a persistent HUD/status bar first | higher implementation risk than improving existing command ergonomics
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep dynamic completion candidates aligned with slash-command behavior and session management semantics
Tested: cargo test -p rusty-claude-cli
Not-tested: Interactive TTY tab-completion behavior in a live terminal session; full clippy remains blocked by pre-existing runtime crate lints
The Rust CLI now points users toward the right next step when they hit an
unknown slash command or mistype a flag, and it surfaces session shortcuts
more clearly in both help text and the REPL banner. It also lowers session
friction by accepting `latest` as a managed-session shortcut, allowing
`--resume` without an explicit path, and sorting saved sessions with
millisecond precision so the newest session is stable.
Constraint: Keep the change inside the existing Rust CLI surface and avoid overlapping new handlers
Constraint: Full workspace clippy -D warnings is currently blocked by pre-existing runtime warnings outside this change
Rejected: Add new slash commands for session shortcuts | higher overlap with already-landed handler work
Rejected: Treat unknown bare words as invalid subcommands | would break shorthand prompt mode
Confidence: high
Scope-risk: moderate
Directive: Preserve bare-word prompt mode when adjusting CLI parsing; only surface guidance for flag-like inputs and slash commands
Tested: cargo clippy -p rusty-claude-cli --bin claw --no-deps -- -D warnings
Tested: cargo test -p rusty-claude-cli
Tested: cargo run -q -p rusty-claude-cli -- --help
Tested: cargo run -q -p rusty-claude-cli -- --resum
Tested: cargo run -q -p rusty-claude-cli -- /stats
Not-tested: Full workspace clippy -D warnings still fails in unrelated runtime code
Wire /agents and /skills through the Rust command stack so they can run as direct CLI subcommands, direct slash invocations, and resume-safe slash commands. The handlers now provide structured usage output, skills discovery also covers legacy /commands markdown entries, and the reporting/tests line up more closely with the original TypeScript behavior where feasible.
Constraint: The Rust port does not yet have the original TypeScript TUI menus or plugin/MCP skill registry, so text reports approximate those views
Rejected: Rebuild the original interactive React menus in Rust now | too large for the current CLI parity slice
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep /skills discovery and the Skill tool aligned if command/skill registry parity expands later
Tested: cargo test --workspace
Tested: cargo clippy --workspace --all-targets -- -D warnings
Tested: cargo run -q -p claw-cli -- agents --help
Tested: cargo run -q -p claw-cli -- /agents
Not-tested: Live Anthropic-backed REPL execution of /agents or /skills
Wire the Rust slash-command surface to expose the upstream-style /plugin entry and add /agents and /skills handling. The plugin command keeps the existing management actions while help, completion, REPL dispatch, and tests now acknowledge the upstream aliases and inventory views.\n\nConstraint: Match original TypeScript command names without regressing existing /plugins management flows\nRejected: Add placeholder commands only | users would still lack practical slash-command output\nConfidence: high\nScope-risk: narrow\nReversibility: clean\nDirective: Keep /plugin as the canonical help entry while preserving /plugins and /marketplace aliases unless upstream naming changes again\nTested: cargo fmt --all; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace\nNot-tested: Manual interactive REPL execution of /agents and /skills against a live user configuration
Add a renderer regression test for long non-JSON tool output so the CLI's fallback rendering path is covered alongside Read and structured tool payload truncation.
Constraint: This follow-up must commit only renderer-related changes
Rejected: Touch commands crate to fix unrelated slash-command work in progress | outside the requested renderer-only scope
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep truncation guarantees covered at the renderer boundary for both structured and raw tool payloads
Tested: cargo fmt --all; cargo test -p claw-cli tool_rendering_ -- --nocapture; cargo clippy -p claw-cli --all-targets -- -D warnings
Not-tested: cargo test --workspace and cargo clippy --workspace --all-targets -- -D warnings currently fail in rust/crates/commands/src/lib.rs due pre-existing incomplete agents/skills changes outside this commit
Extend the CLI renderer's generic tool-result path to reuse the existing display-only truncation helper, so large plugin or unknown-tool payloads no longer flood the terminal while the original tool result still flows through runtime/session state unchanged.
The renderer now pretty-prints structured fallback payloads before truncating them for display, and the test suite covers both Read output and generic long tool output rendering. I also added a narrow clippy allow on an oversized slash-command parser test so the workspace lint gate stays green during verification.
Constraint: Tool result truncation must affect screen rendering only, not stored tool output
Rejected: Truncate tool results at execution time | would lose session fidelity and break downstream consumers
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep future tool-output shortening in renderer helpers only; do not trim runtime tool payloads before persistence
Tested: cargo fmt --all; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace
Not-tested: Manual interactive terminal run showing truncation in a live REPL session
Some tools, especially Read, can emit very large payloads that overwhelm the interactive renderer. This change truncates only the displayed preview for long tool outputs while leaving the underlying tool result string untouched for downstream logic and persisted session state.
Constraint: Rendering changes must not modify stored tool outputs or tool-result messages
Rejected: Truncate tool output before returning from the executor | would corrupt session history and downstream processing
Confidence: high
Scope-risk: narrow
Directive: Keep truncation strictly in presentation helpers; do not move it into tool execution or session persistence paths
Tested: cargo test -p claw-cli tool_rendering_truncates_ -- --nocapture; cargo test -p claw-cli tool_rendering_helpers_compact_output -- --nocapture
Not-tested: Manual terminal rendering with real multi-megabyte tool output
After the parser can accept thinking-style blocks, the CLI and tools adapters must explicitly ignore them so only user-visible text and tool calls drive runtime behavior. This keeps reasoning metadata from surfacing as text or interfering with tool accumulation.
Constraint: Runtime behavior must remain unchanged for normal text/tool streaming
Rejected: Treat thinking blocks as assistant text | would leak hidden reasoning into visible output and session flow
Confidence: high
Scope-risk: narrow
Directive: If future features need persisted reasoning blocks, add a dedicated runtime representation instead of overloading text handling
Tested: cargo test -p claw-cli response_to_events_ignores_thinking_blocks -- --nocapture; cargo test -p tools response_to_events_ignores_thinking_blocks -- --nocapture
Not-tested: End-to-end interactive run against a live thinking-enabled model
The shared /plugins command flow already routes through the plugin registry, but
allowed-tool normalization still fell back to builtin tools when registry
construction failed. This keeps plugin-related validation errors visible at the
CLI boundary and updates tools tests to use the enum-based plugin permission
API so workspace verification remains green.
Constraint: Plugin tool permissions are now strongly typed in the plugins crate
Rejected: Restore string-based permission arguments in tests | weakens the plugin API contract
Rejected: Keep builtin fallback in normalize_allowed_tools | masks plugin registry integration failures
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Do not silently bypass current_tool_registry() failures unless plugin-aware allowed-tool validation is intentionally being disabled
Tested: cargo test -p commands -- --nocapture; cargo test --workspace
Not-tested: Manual REPL /plugins interaction in a live session
The runtime now auto-compacts completed conversations once cumulative input usage
crosses a configurable threshold, preserving recent context while surfacing an
explicit user notice. The CLI also publishes the requested ant-only slash
commands through the shared commands crate and main dispatch, using meaningful
local implementations for commit/PR/issue/teleport/debug workflows.
Constraint: Reuse the existing Rust compaction pipeline instead of introducing a new summarization stack
Constraint: No new dependencies or broad command-framework rewrite
Rejected: Implement API-driven compaction inside ConversationRuntime now | too much new plumbing for this delivery
Rejected: Expose new commands as parse-only stubs | would not satisfy the requested command availability
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: If runtime later gains true API-backed compaction, preserve the TurnSummary auto-compaction metadata shape so CLI call sites stay stable
Tested: cargo test; cargo build --release; cargo fmt --all; git diff --check; LSP diagnostics directory check
Not-tested: Live Anthropic-backed specialist command flows; gh-authenticated PR/issue creation in a real repo
This threads typed hook settings through runtime config, adds a shell-based hook runner, and executes PreToolUse/PostToolUse around each tool call in the conversation loop. The CLI now rebuilds runtimes with settings-derived hook configuration so user-defined Claude hook commands actually run before and after tools.
Constraint: Hook behavior needed to match Claude-style settings.json hooks without broad plugin/MCP parity work in this change
Rejected: Delay hook loading to the tool executor layer | would miss denied tool calls and duplicate runtime policy plumbing
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep hook execution in the runtime loop so permission decisions and tool results remain wrapped by the same conversation semantics
Tested: cargo test; cargo build --release
Not-tested: Real user hook scripts outside the test harness; broader plugin/skills parity
This threads typed hook settings through runtime config, adds a shell-based hook runner, and executes PreToolUse/PostToolUse around each tool call in the conversation loop. The CLI now rebuilds runtimes with settings-derived hook configuration so user-defined Claw hook commands actually run before and after tools.
Constraint: Hook behavior needed to match Claw-style settings.json hooks without broad plugin/MCP parity work in this change
Rejected: Delay hook loading to the tool executor layer | would miss denied tool calls and duplicate runtime policy plumbing
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep hook execution in the runtime loop so permission decisions and tool results remain wrapped by the same conversation semantics
Tested: cargo test; cargo build --release
Not-tested: Real user hook scripts outside the test harness; broader plugin/skills parity
The Rust CLI was still surfacing raw markdown fragments and raw tool JSON in places where the terminal UI should present styled, human-readable output. This change routes assistant text through the terminal markdown renderer, strengthens the markdown ANSI path for headings/links/lists/code blocks, and converts common tool calls/results into concise terminal-native summaries with readable bash output and edit previews.
Constraint: Must match Claude Code-style behavior without copying the upstream TypeScript source
Constraint: Keep the fix scoped to rusty-claude-cli rendering and formatting paths
Rejected: Port TS rendering components directly | prohibited by task constraints
Rejected: Leave tool JSON and only style markdown | still fails the requested terminal UX
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep tool formatting human-readable first; do not reintroduce raw JSON dumps for common tools without a fallback-only guard
Tested: cargo test -p rusty-claude-cli
Tested: cargo build --release
Not-tested: Live end-to-end API streaming against a real Anthropic session
The Rust CLI was still surfacing raw markdown fragments and raw tool JSON in places where the terminal UI should present styled, human-readable output. This change routes assistant text through the terminal markdown renderer, strengthens the markdown ANSI path for headings/links/lists/code blocks, and converts common tool calls/results into concise terminal-native summaries with readable bash output and edit previews.
Constraint: Must match Claw Code-style behavior without copying the upstream TypeScript source
Constraint: Keep the fix scoped to claw-cli rendering and formatting paths
Rejected: Port TS rendering components directly | prohibited by task constraints
Rejected: Leave tool JSON and only style markdown | still fails the requested terminal UX
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep tool formatting human-readable first; do not reintroduce raw JSON dumps for common tools without a fallback-only guard
Tested: cargo test -p claw-cli
Tested: cargo build --release
Not-tested: Live end-to-end API streaming against a real Anthropic session
Tighten prompt-mode parity for the Rust CLI by enabling native tools in one-shot runs, defaulting fresh sessions to danger-full-access, and documenting the remaining TS-vs-Rust gaps.
The JSON prompt path now runs through the full conversation loop so tool use and tool results are preserved without streaming terminal noise, while the tool-input accumulator keeps the streaming {} placeholder fix without corrupting legitimate non-stream empty objects.
Constraint: Original TypeScript source was treated as read-only for parity analysis
Constraint: No new dependencies; keep the fix localized to the Rust port
Rejected: Leave JSON prompt mode on a direct non-tool API path | preserved the one-shot parity bug
Rejected: Keep workspace-write as the default permission mode | contradicted requested parity target
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep prompt text and prompt JSON paths on the same tool-capable runtime semantics unless upstream behavior proves they must diverge
Tested: cargo build --release; cargo test
Not-tested: live remote prompt run against LayoffLabs endpoint in this session
Tighten prompt-mode parity for the Rust CLI by enabling native tools in one-shot runs, defaulting fresh sessions to danger-full-access, and documenting the remaining TS-vs-Rust gaps.
The JSON prompt path now runs through the full conversation loop so tool use and tool results are preserved without streaming terminal noise, while the tool-input accumulator keeps the streaming {} placeholder fix without corrupting legitimate non-stream empty objects.
Constraint: Original TypeScript source was treated as read-only for parity analysis
Constraint: No new dependencies; keep the fix localized to the Rust port
Rejected: Leave JSON prompt mode on a direct non-tool API path | preserved the one-shot parity bug
Rejected: Keep workspace-write as the default permission mode | contradicted requested parity target
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep prompt text and prompt JSON paths on the same tool-capable runtime semantics unless upstream behavior proves they must diverge
Tested: cargo build --release; cargo test
Not-tested: live remote prompt run against LayoffLabs endpoint in this session
The REPL now wraps rustyline::Editor instead of maintaining a custom raw-mode
input stack. This preserves the existing LineEditor surface while delegating
history, completion, and interactive editing to a maintained library. The CLI
argument parser and /model command path also normalize shorthand model names to
our current canonical Anthropic identifiers.
Constraint: User requested rustyline 15 specifically for the CLI editor rewrite
Constraint: Existing LineEditor constructor and read_line API had to remain stable
Rejected: Keep extending the crossterm-based editor | custom key handling and history logic were redundant with rustyline
Rejected: Resolve aliases only for --model flags | /model would still diverge from CLI startup behavior
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep model alias normalization centralized in main.rs so CLI flag parsing and /model stay in sync
Tested: cargo check --workspace
Tested: cargo test --workspace
Tested: cargo build --workspace
Tested: cargo clippy --workspace --all-targets -- -D warnings
Not-tested: Interactive manual terminal validation of Shift+Enter behavior across terminal emulators
The REPL now wraps rustyline::Editor instead of maintaining a custom raw-mode
input stack. This preserves the existing LineEditor surface while delegating
history, completion, and interactive editing to a maintained library. The CLI
argument parser and /model command path also normalize shorthand model names to
our current canonical Anthropic identifiers.
Constraint: User requested rustyline 15 specifically for the CLI editor rewrite
Constraint: Existing LineEditor constructor and read_line API had to remain stable
Rejected: Keep extending the crossterm-based editor | custom key handling and history logic were redundant with rustyline
Rejected: Resolve aliases only for --model flags | /model would still diverge from CLI startup behavior
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep model alias normalization centralized in main.rs so CLI flag parsing and /model stay in sync
Tested: cargo check --workspace
Tested: cargo test --workspace
Tested: cargo build --workspace
Tested: cargo clippy --workspace --all-targets -- -D warnings
Not-tested: Interactive manual terminal validation of Shift+Enter behavior across terminal emulators
The Rust CLI previously hid init behind the REPL slash-command surface and only
created a starter CLAUDE.md. This change adds a direct `init` subcommand and
moves bootstrap behavior into a shared helper so `/init` and `init` create the
same project scaffolding: `.claude/`, `.claude.json`, starter `CLAUDE.md`, and
local-only `.gitignore` entries. The generated guidance now adapts to a small,
explicit set of repository markers so new projects get language/framework-aware
starting instructions without overwriting existing files.
Constraint: Runtime config precedence already treats `.claude.json`, `.claude/settings.json`, and `.claude/settings.local.json` as separate scopes
Constraint: `.claude/sessions/` is used for local session persistence and should not be committed by default
Rejected: Keep init as REPL-only `/init` behavior | would not satisfy the requested direct init command and keeps bootstrap discoverability low
Rejected: Ignore all of `.claude/` | would hide shared project config that the runtime can intentionally load
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep direct `init` and `/init` on the same helper path and keep detection heuristics bounded to explicit repository markers
Tested: cargo fmt --all; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace
Not-tested: interactive manual run of `rusty-claude-cli init` against a non-test repository
The Rust CLI previously hid init behind the REPL slash-command surface and only
created a starter INSTRUCTIONS.md. This change adds a direct `init` subcommand and
moves bootstrap behavior into a shared helper so `/init` and `init` create the
same project scaffolding: `.claw/`, `.claw.json`, starter `INSTRUCTIONS.md`, and
local-only `.gitignore` entries. The generated guidance now adapts to a small,
explicit set of repository markers so new projects get language/framework-aware
starting instructions without overwriting existing files.
Constraint: Runtime config precedence already treats `.claw.json`, `.claw/settings.json`, and `.claw/settings.local.json` as separate scopes
Constraint: `.claw/sessions/` is used for local session persistence and should not be committed by default
Rejected: Keep init as REPL-only `/init` behavior | would not satisfy the requested direct init command and keeps bootstrap discoverability low
Rejected: Ignore all of `.claw/` | would hide shared project config that the runtime can intentionally load
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep direct `init` and `/init` on the same helper path and keep detection heuristics bounded to explicit repository markers
Tested: cargo fmt --all; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace
Not-tested: interactive manual run of `claw-cli init` against a non-test repository
This adds a small runtime sandbox policy/status layer, threads
sandbox options through the bash tool, and exposes `/sandbox`
status reporting in the CLI. Linux namespace/network isolation
is best-effort and intentionally reported as requested vs active
so the feature does not overclaim guarantees on unsupported
hosts or nested container environments.
Constraint: No new dependencies for isolation support
Constraint: Must keep filesystem restriction claims honest unless hard mount isolation succeeds
Rejected: External sandbox/container wrapper | too heavy for this workspace and request
Rejected: Inline bash-only changes without shared status model | weaker testability and poorer CLI visibility
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Treat this as observable best-effort isolation, not a hard security boundary, unless stronger mount enforcement is added later
Tested: cargo fmt --all; cargo clippy --workspace --all-targets --all-features -- -D warnings; cargo test --workspace
Not-tested: Manual `/sandbox` REPL run on a real nested-container host
Git-aware CLI flows already existed, but branch detection depended on
status-line parsing and /diff hid local policy inside a path exclusion.
This change makes branch resolution and diff rendering rely on git-native
queries, adds staged+unstaged diff reporting, and threads git diff
snapshots into runtime project context so prompts see the same workspace
state users inspect from the CLI.
Constraint: No new dependencies for git integration work
Constraint: Slash-command help/behavior must stay aligned between shared metadata and CLI handlers
Rejected: Keep parsing the `## ...` status line only | brittle for detached HEAD and format drift
Rejected: Keep hard-coded `:(exclude).omx` filtering | redundant with git ignore rules and hides product policy in implementation
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Preserve git-native behavior for branch/diff reporting; do not reintroduce ad hoc ignore filtering without a product requirement
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace
Not-tested: Manual REPL /diff smoke test against a live interactive session
Startup auth was split between the CLI and API crates, which made saved OAuth refresh behavior eager and easy to drift. This change adds a startup-specific resolver in the API layer, keeps env-only auth semantics intact, preserves saved refresh tokens when refresh responses omit them, and lets the CLI reuse the shared resolver while keeping --version on a purely local path.
Constraint: Saved OAuth credentials live in ~/.claude/credentials.json and must remain compatible with existing runtime helpers
Constraint: --version must not require config loading or any API/auth client initialization
Rejected: Keep refresh orchestration only in rusty-claude-cli | would preserve split auth policy and lazy-load bugs
Rejected: Change AnthropicClient::from_env to load config | would broaden configless API semantics for non-CLI callers
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep startup-only OAuth refresh separate from AuthSource::from_env() / AnthropicClient::from_env() unless all non-CLI callers are re-evaluated
Tested: cargo fmt --all; cargo build; cargo clippy --workspace --all-targets -- -D warnings; cargo test; cargo run -p rusty-claude-cli -- --version
Not-tested: Live OAuth refresh against a real auth server
Startup auth was split between the CLI and API crates, which made saved OAuth refresh behavior eager and easy to drift. This change adds a startup-specific resolver in the API layer, keeps env-only auth semantics intact, preserves saved refresh tokens when refresh responses omit them, and lets the CLI reuse the shared resolver while keeping --version on a purely local path.
Constraint: Saved OAuth credentials live in ~/.claw/credentials.json and must remain compatible with existing runtime helpers
Constraint: --version must not require config loading or any API/auth client initialization
Rejected: Keep refresh orchestration only in claw-cli | would preserve split auth policy and lazy-load bugs
Rejected: Change AnthropicClient::from_env to load config | would broaden configless API semantics for non-CLI callers
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep startup-only OAuth refresh separate from AuthSource::from_env() / AnthropicClient::from_env() unless all non-CLI callers are re-evaluated
Tested: cargo fmt --all; cargo build; cargo clippy --workspace --all-targets -- -D warnings; cargo test; cargo run -p claw-cli -- --version
Not-tested: Live OAuth refresh against a real auth server
The custom crossterm editor now supports prompt history, slash-command tab
completion, multiline editing, and Ctrl-C semantics that clear partial input
without always terminating the session. The live REPL loop now distinguishes
buffer cancellation from clean exit, persists session state on meaningful
boundaries, and renders tool activity in a more structured way for terminal
use.
Constraint: Keep the active REPL on the existing crossterm path without adding a line-editor dependency
Rejected: Swap to rustyline or reedline | broader integration risk than this polish pass justifies
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep editor state logic generic in input.rs and leave REPL policy decisions in main.rs
Tested: cargo fmt --manifest-path rust/Cargo.toml --all; cargo clippy --manifest-path rust/Cargo.toml --all-targets --all-features -- -D warnings; cargo test --manifest-path rust/Cargo.toml
Not-tested: Interactive manual terminal smoke test for arrow keys/tab/Ctrl-C in a live TTY
The custom crossterm editor now supports prompt history, slash-command tab
completion, multiline editing, and Ctrl-C semantics that clear partial input
without always terminating the session. The live REPL loop now distinguishes
buffer cancellation from clean exit, persists session state on meaningful
boundaries, and renders tool activity in a more structured way for terminal
use.
Constraint: Keep the active REPL on the existing crossterm path without adding a line-editor dependency
Rejected: Swap to rustyline or reedline | broader integration risk than this polish pass justifies
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep editor state logic generic in input.rs and leave REPL policy decisions in main.rs
Tested: cargo fmt --manifest-path rust/Cargo.toml --all; cargo clippy --manifest-path rust/Cargo.toml --all-targets --all-features -- -D warnings; cargo test --manifest-path rust/Cargo.toml
Not-tested: Interactive manual terminal smoke test for arrow keys/tab/Ctrl-C in a live TTY
The Rust CLI/runtime now models permissions as ordered access levels, derives tool requirements from the shared tool specs, and prompts REPL users before one-off danger-full-access escalations from workspace-write sessions. This also wires explicit --permission-mode parsing and makes /permissions operate on the live session state instead of an implicit env-derived default.
Constraint: Must preserve the existing three user-facing modes read-only, workspace-write, and danger-full-access
Constraint: Must avoid new dependencies and keep enforcement inside the existing runtime/tool plumbing
Rejected: Keep the old Allow/Deny/Prompt policy model | could not represent ordered tool requirements across the CLI surface
Rejected: Continue sourcing live session mode solely from RUSTY_CLAUDE_PERMISSION_MODE | /permissions would not reliably reflect the current session state
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Add required_permission entries for new tools before exposing them to the runtime
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test -q
Not-tested: Manual interactive REPL approval flow in a live Anthropic session
The Rust CLI/runtime now models permissions as ordered access levels, derives tool requirements from the shared tool specs, and prompts REPL users before one-off danger-full-access escalations from workspace-write sessions. This also wires explicit --permission-mode parsing and makes /permissions operate on the live session state instead of an implicit env-derived default.
Constraint: Must preserve the existing three user-facing modes read-only, workspace-write, and danger-full-access
Constraint: Must avoid new dependencies and keep enforcement inside the existing runtime/tool plumbing
Rejected: Keep the old Allow/Deny/Prompt policy model | could not represent ordered tool requirements across the CLI surface
Rejected: Continue sourcing live session mode solely from RUSTY_CLAUDE_PERMISSION_MODE | /permissions would not reliably reflect the current session state
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Add required_permission entries for new tools before exposing them to the runtime
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test -q
Not-tested: Manual interactive REPL approval flow in a live Anthropic session
The remaining slash commands already existed in the REPL path, so this change
focuses on wiring the active CLI parser and runtime to expose them safely.
`--version` now exits through a local reporting path, and `--allowedTools`
constrains both advertised and executable tools without changing the underlying
command surface.
Constraint: The active CLI parser lives in main.rs, so a full parser unification would be broader than requested
Constraint: --version must not require API credentials or construct the API client
Rejected: Migrate the binary to the clap parser in args.rs | too large for a parity patch
Rejected: Enforce allowed tools only at request construction time | execution-time mismatch risk
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep local-only flags like --version on pre-runtime codepaths and mirror tool allowlists in both definition and execution paths
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test; cargo run -q -p rusty-claude-cli -- --version; cargo run -q -p rusty-claude-cli -- --help
Not-tested: Interactive live API conversation with restricted tool allowlists
The remaining slash commands already existed in the REPL path, so this change
focuses on wiring the active CLI parser and runtime to expose them safely.
`--version` now exits through a local reporting path, and `--allowedTools`
constrains both advertised and executable tools without changing the underlying
command surface.
Constraint: The active CLI parser lives in main.rs, so a full parser unification would be broader than requested
Constraint: --version must not require API credentials or construct the API client
Rejected: Migrate the binary to the clap parser in args.rs | too large for a parity patch
Rejected: Enforce allowed tools only at request construction time | execution-time mismatch risk
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep local-only flags like --version on pre-runtime codepaths and mirror tool allowlists in both definition and execution paths
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test; cargo run -q -p claw-cli -- --version; cargo run -q -p claw-cli -- --help
Not-tested: Interactive live API conversation with restricted tool allowlists
This adds an end-to-end OAuth PKCE login/logout path to the Rust CLI,
persists OAuth credentials under the Claude config home, and teaches the
API client to use persisted bearer credentials with refresh support when
env-based API credentials are absent.
Constraint: Reuse existing runtime OAuth primitives and keep browser/callback orchestration in the CLI
Constraint: Preserve auth precedence as API key, then auth-token env, then persisted OAuth credentials
Rejected: Put browser launch and token exchange entirely in runtime | caused boundary creep across shared crates
Rejected: Duplicate credential parsing in CLI and api | increased drift and refresh inconsistency
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep logout non-destructive to unrelated credentials.json fields and do not silently fall back to stale expired tokens
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test
Not-tested: Manual live Anthropic OAuth browser flow against real authorize/token endpoints
This adds an end-to-end OAuth PKCE login/logout path to the Rust CLI,
persists OAuth credentials under the config home, and teaches the
API client to use persisted bearer credentials with refresh support when
env-based API credentials are absent.
Constraint: Reuse existing runtime OAuth primitives and keep browser/callback orchestration in the CLI
Constraint: Preserve auth precedence as API key, then auth-token env, then persisted OAuth credentials
Rejected: Put browser launch and token exchange entirely in runtime | caused boundary creep across shared crates
Rejected: Duplicate credential parsing in CLI and api | increased drift and refresh inconsistency
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep logout non-destructive to unrelated credentials.json fields and do not silently fall back to stale expired tokens
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test
Not-tested: Manual live Anthropic OAuth browser flow against real authorize/token endpoints
This adds the remaining user-facing slash commands, enables non-interactive model and JSON prompt output, and tightens the help and startup copy so the Rust CLI feels coherent as a standalone interface.
The implementation keeps the scope narrow by reusing the existing session JSON format and local runtime machinery instead of introducing new storage layers or dependencies.
Constraint: No new dependencies allowed for this polish pass
Constraint: Do not commit OMX runtime state
Rejected: Add a separate session database | unnecessary complexity for local CLI persistence
Rejected: Rework argument parsing with clap | too broad for the current delivery window
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Managed sessions currently live under .claude/sessions; keep compatibility in mind before changing that path or file shape
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test
Not-tested: Live Anthropic prompt execution and interactive manual UX smoke test
This adds the remaining user-facing slash commands, enables non-interactive model and JSON prompt output, and tightens the help and startup copy so the Rust CLI feels coherent as a standalone interface.
The implementation keeps the scope narrow by reusing the existing session JSON format and local runtime machinery instead of introducing new storage layers or dependencies.
Constraint: No new dependencies allowed for this polish pass
Constraint: Do not commit OMX runtime state
Rejected: Add a separate session database | unnecessary complexity for local CLI persistence
Rejected: Rework argument parsing with clap | too broad for the current delivery window
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Managed sessions currently live under .claw/sessions; keep compatibility in mind before changing that path or file shape
Tested: cargo fmt; cargo clippy --workspace --all-targets -- -D warnings; cargo test
Not-tested: Live Anthropic prompt execution and interactive manual UX smoke test
Tighten the /permissions report into the same operator-console style used by
other slash commands, and make permission mode changes read like a structured
CLI confirmation instead of a raw field swap.
Constraint: Must keep the real permission surface limited to read-only, workspace-write, and danger-full-access
Rejected: Add synthetic shortcuts or approval-state variants | would misrepresent actual supported modes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /permissions output aligned with other structured slash command reports as new mode metadata is added
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace; manual REPL smoke test for /permissions and /permissions read-only
Not-tested: Interactive approval prompting flows beyond mode report formatting
Tighten the /permissions report into the same operator-console style used by
other slash commands, and make permission mode changes read like a structured
CLI confirmation instead of a raw field swap.
Constraint: Must keep the real permission surface limited to read-only, workspace-write, and danger-full-access
Rejected: Add synthetic shortcuts or approval-state variants | would misrepresent actual supported modes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /permissions output aligned with other structured slash command reports as new mode metadata is added
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace; manual REPL smoke test for /permissions and /permissions read-only
Not-tested: Interactive approval prompting flows beyond mode report formatting
Reformat /compact output for both live and resumed sessions so compaction results are reported in the same structured console style as the rest of the CLI surface. This keeps the behavior unchanged while making skipped and successful compaction runs easier to read.
Constraint: Compact output must stay faithful to the real compaction result and not imply summarization details beyond removed/kept message counts
Rejected: Expose the generated summary body directly in /compact output | too noisy for a lightweight command-response surface
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep lifecycle and maintenance command output stylistically consistent as more slash commands reach parity
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual terminal UX review of compact output on very large sessions
Reformat /compact output for both live and resumed sessions so compaction results are reported in the same structured console style as the rest of the CLI surface. This keeps the behavior unchanged while making skipped and successful compaction runs easier to read.
Constraint: Compact output must stay faithful to the real compaction result and not imply summarization details beyond removed/kept message counts
Rejected: Expose the generated summary body directly in /compact output | too noisy for a lightweight command-response surface
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep lifecycle and maintenance command output stylistically consistent as more slash commands reach parity
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual terminal UX review of compact output on very large sessions
Reformat /init results into the same structured operator-console style used by the other polished commands so create and skip outcomes are easier to scan. This keeps the command behavior unchanged while making repo bootstrapping feedback feel more intentional.
Constraint: /init must stay non-destructive and continue refusing to overwrite an existing CLAUDE.md
Rejected: Expand /init to write more files in the same slice | broader scaffolding would be riskier than a focused UX polish commit
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /init output explicit about whether the file was created or skipped so users can trust the command in existing repos
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual /init run in a repo that already has a heavily customized CLAUDE.md
Reformat /init results into the same structured operator-console style used by the other polished commands so create and skip outcomes are easier to scan. This keeps the command behavior unchanged while making repo bootstrapping feedback feel more intentional.
Constraint: /init must stay non-destructive and continue refusing to overwrite an existing INSTRUCTIONS.md
Rejected: Expand /init to write more files in the same slice | broader scaffolding would be riskier than a focused UX polish commit
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /init output explicit about whether the file was created or skipped so users can trust the command in existing repos
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual /init run in a repo that already has a heavily customized INSTRUCTIONS.md
Extend /config so operators can inspect specific merged sections like env, hooks, and model while keeping the command read-only and grounded in the actual loaded config. This improves Claude Code-style inspectability without inventing an unsafe config editing surface.
Constraint: Config handling must remain read-only and reflect only the merged runtime config that already exists
Rejected: Add /config set mutation commands | persistence semantics and edit safety are not mature enough for a small honest slice
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep config subviews aligned with real merged keys and avoid advertising writable behavior until persistence is designed
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual inspection of richer hooks/env config payloads in a customized user setup
Extend /config so operators can inspect specific merged sections like env, hooks, and model while keeping the command read-only and grounded in the actual loaded config. This improves Claw Code-style inspectability without inventing an unsafe config editing surface.
Constraint: Config handling must remain read-only and reflect only the merged runtime config that already exists
Rejected: Add /config set mutation commands | persistence semantics and edit safety are not mature enough for a small honest slice
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep config subviews aligned with real merged keys and avoid advertising writable behavior until persistence is designed
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual inspection of richer hooks/env config payloads in a customized user setup
Reformat /memory into the same structured console style as the other polished commands and enumerate discovered instruction files in ancestry order with line counts and previews. This makes repo instruction memory easier to inspect without changing the underlying discovery behavior.
Constraint: Memory reporting must reflect only the instruction files discovered from current directory ancestry
Rejected: Add memory editing commands in the same slice | presentation polish was a cleaner, lower-risk improvement to ship first
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep instruction-file ordering stable so ancestry-based memory debugging stays predictable
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual inspection of repos with many nested CLAUDE files
Reformat /memory into the same structured console style as the other polished commands and enumerate discovered instruction files in ancestry order with line counts and previews. This makes repo instruction memory easier to inspect without changing the underlying discovery behavior.
Constraint: Memory reporting must reflect only the instruction files discovered from current directory ancestry
Rejected: Add memory editing commands in the same slice | presentation polish was a cleaner, lower-risk improvement to ship first
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep instruction-file ordering stable so ancestry-based memory debugging stays predictable
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual inspection of repos with many nested CLAUDE files
Extend /status with project root and git branch details derived from the local repository so the report feels closer to a real Claude Code session dashboard. This adds high-value workspace context without inventing any persisted metadata the runtime does not actually have.
Constraint: Status metadata must be computed from the current working tree at runtime and tolerate non-git directories
Rejected: Persist branch/root into session files first | a local runtime derivation is smaller and immediately useful without changing session format
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep status context opportunistic and degrade cleanly to unknown when git metadata is unavailable
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual non-git-directory /status run
Extend /status with project root and git branch details derived from the local repository so the report feels closer to a real Claw Code session dashboard. This adds high-value workspace context without inventing any persisted metadata the runtime does not actually have.
Constraint: Status metadata must be computed from the current working tree at runtime and tolerate non-git directories
Rejected: Persist branch/root into session files first | a local runtime derivation is smaller and immediately useful without changing session format
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep status context opportunistic and degrade cleanly to unknown when git metadata is unavailable
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual non-git-directory /status run
Update in-REPL /resume success output to the same structured console style used elsewhere so session lifecycle commands feel consistent with status, model, permissions, config, and cost. This preserves the same behavior while improving operator readability.
Constraint: Resume output must stay grounded in real restored session metadata already available after load
Rejected: Add more restored-session details like cwd snapshot | that data is not yet persisted in session files
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep lifecycle command outputs stylistically aligned as the CLI surface grows
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual interactive comparison of /resume output before and after multiple restores
Update in-REPL /resume success output to the same structured console style used elsewhere so session lifecycle commands feel consistent with status, model, permissions, config, and cost. This preserves the same behavior while improving operator readability.
Constraint: Resume output must stay grounded in real restored session metadata already available after load
Rejected: Add more restored-session details like cwd snapshot | that data is not yet persisted in session files
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep lifecycle command outputs stylistically aligned as the CLI surface grows
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual interactive comparison of /resume output before and after multiple restores
Refresh shared slash help and REPL help wording so the command surface reads more like an integrated console, and make successful /clear output match the newer structured reporting style. This keeps discoverability consistent now that status, model, permissions, config, and cost all use richer operator-oriented copy.
Constraint: Help text must stay synchronized with the actual implemented command surface and resume behavior
Rejected: Larger README/doc pass in the same commit | keeping the slice limited to runtime help/output makes it easier to review and revert
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Prefer shared help-copy changes in commands crate first, then layer REPL-specific additions in the CLI binary
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual comparison of help wording against upstream Claude Code terminal screenshots
Refresh shared slash help and REPL help wording so the command surface reads more like an integrated console, and make successful /clear output match the newer structured reporting style. This keeps discoverability consistent now that status, model, permissions, config, and cost all use richer operator-oriented copy.
Constraint: Help text must stay synchronized with the actual implemented command surface and resume behavior
Rejected: Larger README/doc pass in the same commit | keeping the slice limited to runtime help/output makes it easier to review and revert
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Prefer shared help-copy changes in commands crate first, then layer REPL-specific additions in the CLI binary
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual comparison of help wording against upstream Claw Code terminal screenshots
Reformat /cost for both live and resumed sessions so token accounting is presented in the same sectioned operator-console style as status, model, permissions, and config. This improves consistency across the command surface while preserving the same underlying usage metrics.
Constraint: Cost output must continue to reflect cumulative tracked usage only, without claiming real billing or currency totals
Rejected: Add dollar estimates | there is no authoritative pricing source wired into this CLI surface
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /cost focused on raw token accounting until pricing metadata exists in the runtime layer
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual terminal UX review for very large cumulative token counts
Reformat /cost for both live and resumed sessions so token accounting is presented in the same sectioned operator-console style as status, model, permissions, and config. This improves consistency across the command surface while preserving the same underlying usage metrics.
Constraint: Cost output must continue to reflect cumulative tracked usage only, without claiming real billing or currency totals
Rejected: Add dollar estimates | there is no authoritative pricing source wired into this CLI surface
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /cost focused on raw token accounting until pricing metadata exists in the runtime layer
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual terminal UX review for very large cumulative token counts
Rework /permissions output into the same operator-console format used by status, config, and model so the command feels intentional and self-explanatory. Switching modes now reports previous and current state, while inspection shows the available modes and their meaning without adding fake policy logic.
Constraint: Permission output must stay aligned with the real three-mode runtime policy already implemented
Rejected: Add richer permission-policy previews per tool | would require more UI surface and risks overstating current policy fidelity
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep permission-mode docs in the CLI consistent with normalize_permission_mode and permission_policy behavior
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual operator UX review of /permissions flows in a live REPL
Rework /permissions output into the same operator-console format used by status, config, and model so the command feels intentional and self-explanatory. Switching modes now reports previous and current state, while inspection shows the available modes and their meaning without adding fake policy logic.
Constraint: Permission output must stay aligned with the real three-mode runtime policy already implemented
Rejected: Add richer permission-policy previews per tool | would require more UI surface and risks overstating current policy fidelity
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep permission-mode docs in the CLI consistent with normalize_permission_mode and permission_policy behavior
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual operator UX review of /permissions flows in a live REPL
Replace terse /model strings with sectioned model reports that show the active model and preserved session context, and use a structured switch report when the model changes. This keeps the behavior honest while making model management feel more intentional and Claude-like.
Constraint: Model switching must preserve the current session and avoid adding any fake model catalog or validation layer
Rejected: Add a hardcoded model list or aliases | would create drift with actual backend-supported model names
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /model output informational and backend-agnostic unless the runtime gains authoritative model discovery
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual interactive switching across multiple real Anthropic model names
Replace terse /model strings with sectioned model reports that show the active model and preserved session context, and use a structured switch report when the model changes. This keeps the behavior honest while making model management feel more intentional and Claw-like.
Constraint: Model switching must preserve the current session and avoid adding any fake model catalog or validation layer
Rejected: Add a hardcoded model list or aliases | would create drift with actual backend-supported model names
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /model output informational and backend-agnostic unless the runtime gains authoritative model discovery
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual interactive switching across multiple real Anthropic model names
Require an explicit /clear --confirm flag before wiping live or resumed session state. This keeps the command genuinely useful while adding the minimal safety check needed for a destructive command in a chatty terminal workflow.
Constraint: /clear must remain a real functional command without introducing interactive prompt machinery that would complicate REPL input handling
Rejected: Add y/n interactive confirmation prompt | extra stateful prompting would be slower to ship and more fragile inside the line editor loop
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep destructive slash commands opt-in via explicit flags unless the CLI gains a dedicated confirmation subsystem
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual keyboard-driven UX pass for accidental /clear entry in interactive REPL
Require an explicit /clear --confirm flag before wiping live or resumed session state. This keeps the command genuinely useful while adding the minimal safety check needed for a destructive command in a chatty terminal workflow.
Constraint: /clear must remain a real functional command without introducing interactive prompt machinery that would complicate REPL input handling
Rejected: Add y/n interactive confirmation prompt | extra stateful prompting would be slower to ship and more fragile inside the line editor loop
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep destructive slash commands opt-in via explicit flags unless the CLI gains a dedicated confirmation subsystem
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual keyboard-driven UX pass for accidental /clear entry in interactive REPL
Reformat /status and /config into sectioned reports with stable labels so the CLI surfaces read more like a usable operator console and less like dense debug strings. This improves discoverability and parity feel without changing the underlying data model or inventing fake settings behavior.
Constraint: Output polish must preserve the exact locally discoverable facts already exposed by the CLI
Rejected: Add interactive /clear confirmation first | wording/layout polish was cleaner, lower-risk, and touched fewer control-flow paths
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep CLI reports sectioned and label-stable so future tests can assert on intent rather than fragile token ordering
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual terminal-width UX review for very long paths or merged JSON payloads
Reformat /status and /config into sectioned reports with stable labels so the CLI surfaces read more like a usable operator console and less like dense debug strings. This improves discoverability and parity feel without changing the underlying data model or inventing fake settings behavior.
Constraint: Output polish must preserve the exact locally discoverable facts already exposed by the CLI
Rejected: Add interactive /clear confirmation first | wording/layout polish was cleaner, lower-risk, and touched fewer control-flow paths
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep CLI reports sectioned and label-stable so future tests can assert on intent rather than fragile token ordering
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual terminal-width UX review for very long paths or merged JSON payloads