Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

About

Claude Code Rust is a native Rust terminal interface for Claude Code. It replaces the stock Node.js and React Ink terminal UI with a Ratatui-based binary while keeping Claude Code functionality routed through Anthropic’s Agent SDK.

The goal is a faster, lower-memory terminal experience with reliable scrollback, direct terminal rendering, native input handling, and a project-local configuration surface.

Project Status

The project is pre-1.0. The crate version in the root Cargo.toml and the Changelog are the source of truth for the current release.

The project is useful today, but the runtime still depends on the upstream Claude Agent SDK bridge. Startup readiness, authentication behavior, billing, model availability, and service limits are controlled by Anthropic.

Claude CLI Dependencies

Core conversations, tools, file edits, permissions, and session history run through the bundled Agent SDK. The separately installed claude command is used for the following operations and must be available on PATH when you use them:

OperationCLI commandWhen it is needed
/login and /logoutclaude auth login and claude auth logoutAccount sign-in and sign-out from the Rust TUI. An already authenticated SDK session does not invoke these commands for each turn.
Plugin inventory and managementclaude plugin ...Listing installed and available plugins; installing, enabling, disabling, updating, and uninstalling plugins; and managing marketplaces. Installed plugins execute through the SDK, and runtime reload uses the SDK.
Remove a persisted MCP serverclaude mcp remove --scope <scope> <server>Removing user-, project-, or local-scope server configuration. Dynamic session servers are removed through the SDK.
Usage data from the CLIclaude /usage --allowed-tools ""When the CLI usage source is selected, or an eligible fallback reaches it. The default source first tries the connected SDK session, then OAuth; only eligible OAuth failures fall back to the CLI.

This list was audited against Agent SDK 0.3.286 on October 2, 2026, by checking the application’s CLI process launches and usage-source selection. Installing claude provides these operations; it does not add the stock terminal interface’s other screens or controls to the Rust TUI.

Feature Overview

The Rust TUI implements its own interface and uses the SDK’s session capabilities. It does not reproduce every stock Claude Code interface feature.

FeatureAvailabilityDetails
Conversations, tools, file edits, and permissionsRust TUI and SDKCore interactive workflow.
Model, effort, permission mode, and agent selectionRust TUI and SDKAvailable through startup flags and session controls.
Resume, continue, compaction, and rewindRust TUI and SDKSession startup and history controls; see Usage and Slash Commands.
Subagents and background tasks within a sessionRust TUI and SDKSDK task activity and results are displayed in the conversation. This is distinct from detaching the entire session.
Skills and SDK-advertised slash commandsSDK, when advertisedUse /docs commands for the current session’s merged list.
MCP status, authorization, and dynamic serversRust TUI and SDKPersisted server removal additionally needs the CLI, as listed above.
Inline edit diffsRust TUITool output displays file changes.
Shell completions and man pagesNative CLIGenerated from the CLI definitions; see Usage.
Account login and logoutInstalled Claude CLIInvoked from /login and /logout.
Plugin inventory and persistent managementInstalled Claude CLIInvoked from the plugin management interface.
Session-only local plugin foldersRust TUI and SDKLoad local folder in /plugins; no persistent installation.
Usage informationSDK, OAuth, or installed Claude CLIThe CLI is conditional; see the dependency table above.
Whole-session background detach/attach and stock agent viewUnavailable in the Rust TUISDK background tasks are supported, but the stock /background and claude agents interface is not provided.
Remote Control and stock IDE integrationsUnavailable in the Rust TUINo equivalent to the stock /remote-control or /ide integration. Running in an IDE terminal still works.
Vim input modeUnavailable in the Rust TUIThe settings surface does not offer an editor-mode preference; see unavailable settings.
Dedicated /diff review panelUnavailable in the Rust TUIInline edit diffs remain available.
Stock /tui renderer switchUnavailable in the Rust TUIRendering and fullscreen settings screens are owned by the Rust application.
Mouse interaction with app controlsUnavailable in the Rust TUIUse keyboard controls. Terminal text selection and native scrollback depend on your terminal.

The comparison was checked against the official Claude Code command reference, the app-owned command definitions, and a metadata-only supportedCommands() query using SDK 0.3.286. The SDK list varies with account, platform, configuration, and installed skills; it is not the stock CLI’s complete /help menu. A missing SDK command alone is not evidence that a capability is unavailable. The interface gaps above were also checked against the Rust and bridge implementations. For the upstream integrations, see Remote Control and VS Code.

Relationship To Anthropic

This project is not affiliated with, endorsed by, or supported by Anthropic. It is a third-party terminal UI that talks to the official Agent SDK through a local TypeScript bridge. It is not a fork, copy, or port of Anthropic’s Claude Code source.

For official Claude documentation, use the Claude documentation:

Billing Note

Because Claude Code Rust uses the Agent SDK, usage should be treated as Agent SDK usage. Anthropic has paused the previously announced Agent SDK credit change. For now, Agent SDK usage, including claude -p and third-party apps like this one, still draws from normal Claude subscription limits.

Check Anthropic’s current support article before relying on billing assumptions:

Installation

User Prerequisite

Install the Claude Code CLI and keep claude on PATH for the account and management operations listed in Claude CLI dependencies. Core sessions use the bundled Agent SDK; the CLI is also an optional usage-data source or fallback. See anthropics/claude-code for how to install it.

The recommended script install includes the application and its runtime dependencies. It does not require a Rust toolchain, Node.js, npm, or a separate Bun installation.

Install Script

Install scripts are available in GitHub Releases starting with v0.14.0 and are the recommended install path. They install a self-contained release without requiring npm, Node.js, or Bun on the user’s machine.

The scripts download a complete release archive from GitHub, verify the release archive integrity, install the native binary with the bundled private Bun runtime, Agent SDK bridge, and production node_modules, then run a quiet claude-rs --version check. Download diagnostics and strict runtime diagnostics are available with the opt-in verify flag.

Interactive terminals display a fixed-width 20-cell progress bar while downloading the release archive and a spinner for other longer installation steps. Transferred size and total size are shown when they fit; the verify flag adds average speed and ETA, followed by the final transfer size, elapsed time, average speed, and HTTP status. Details that would wrap are omitted from the live line. Redirected output and CI remain plain and log-friendly, and NO_COLOR disables colored status output.

On supported interactive terminals, confirmation prompts show y Yes / N No and accept either answer key immediately, without Enter. Other keys are ignored. Terminals without single-key input use a line prompt instead, where Enter selects No.

macOS/Linux:

curl -fsSL https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.sh | sh

Windows PowerShell:

powershell -NoProfile -ExecutionPolicy Bypass -Command "irm 'https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.ps1' | iex"

The default Unix install layout is:

${XDG_DATA_HOME:-$HOME/.local/share}/claude-rs/
$HOME/.local/bin/claude-rs
$HOME/.local/share/man/man1/claude-rs*.1

The app directory contains claude-rs, claude-rs-bridge-bun, agent-sdk/, and node_modules/. The file in $HOME/.local/bin is a launcher script that executes the app binary. Unix archives also contain manuals under share/man/man1/; the installer links them into the sibling share/man/man1/ directory beside bin. Uninstall removes its own manual links and preserves manuals from other installations. See Usage for viewing manuals and generating them with npm or source installations.

The default Windows install layout is:

%LOCALAPPDATA%\Programs\claude-rs\

The Windows app directory is added to the user Path unless path modification is disabled.

Install From npm

npm remains supported for users who prefer package-manager ownership of the global command:

npm install -g claude-code-rust
claude-rs --version
claude-rs

The npm option requires Node.js 24 and npm to install and run its JavaScript launcher. The package owns the claude-rs command, selects the matching platform payload with npm optional dependencies, and includes the private Bun runtime used by the Agent SDK bridge. A Rust toolchain and separate Bun installation are not required. No install-time binary download or postinstall script is used.

Supported npm platforms are Linux x64/arm64 with glibc, Windows x64/arm64, and macOS x64/arm64.

Pinning a Release

Use CLAUDE_RS_RELEASE to install a specific release:

curl -fsSL https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.sh | CLAUDE_RS_RELEASE=v0.14.0 sh
$env:CLAUDE_RS_RELEASE = "v0.14.0"
powershell -NoProfile -ExecutionPolicy Bypass -Command "irm 'https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.ps1' | iex"

The version can include or omit the v prefix.

Reinstalling the Same Version

Before downloading release checksums or an archive, the installer compares the selected release with the version recorded in an existing script-owned install at the configured install directory. It does not compare with an npm install or another claude-rs found on PATH, because those may represent a different installation method or location.

When the selected version is already installed, an interactive installation asks whether to reinstall it and defaults to no. Declining is a successful no-op and leaves the existing files unchanged. In CI or another non-interactive environment, the same-version check also exits successfully without reinstalling.

Use --yes or -Yes to approve an intentional same-version reinstall, for example to repair an installation:

curl -fsSL https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.sh | sh -s -- --release v0.14.0 --yes
.\install.ps1 -Release v0.14.0 -Yes

Update mode always treats an already-installed selected version as a successful no-op, even though update mode otherwise runs non-interactively. With the default latest selection, the installer must first request GitHub Release metadata to resolve the release tag; the same-version guard still runs before downloading SHA256SUMS or the release archive.

Custom Install Locations

Choosing a custom install directory creates or updates the installation at that location; it does not move or automatically uninstall a copy in the default directory. A temporary test installation can therefore coexist with your normal installation. Decline its optional cleanup prompt to keep the normal copy.

On macOS/Linux, pass installer flags after sh -s --:

curl -fsSL https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.sh | sh -s -- --install-dir "$HOME/.local/share/claude-rs" --bin-dir "$HOME/.local/bin"

For non-interactive Unix installs:

curl -fsSL https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.sh | sh -s -- --yes

The Unix installer also accepts:

  • --release <version>
  • --install-dir <dir>
  • --bin-dir <dir>
  • --yes or -y
  • --non-interactive
  • --no-modify-path
  • --verify
  • --run
  • --remove-npm
  • --keep-npm
  • --uninstall
  • --update

When using the PowerShell one-liner, configure the installer with environment variables because arguments cannot be passed through iex:

$env:CLAUDE_RS_INSTALL_DIR = "$env:LOCALAPPDATA\Programs\claude-rs"
$env:CLAUDE_RS_NO_MODIFY_PATH = "1"
powershell -NoProfile -ExecutionPolicy Bypass -Command "irm 'https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.ps1' | iex"

If you download the script first, PowerShell flags are also available:

.\install.ps1 -Release v0.14.0 -InstallDir "$env:LOCALAPPDATA\Programs\claude-rs" -NoModifyPath

Other PowerShell flags available when the script is downloaded first:

  • -Yes
  • -Verify
  • -Run
  • -RemoveNpm
  • -KeepNpm
  • -Uninstall
  • -Update

With the PowerShell one-liner, use the matching environment variables:

  • CLAUDE_RS_VERIFY=1
  • CLAUDE_RS_RUN=1
  • CLAUDE_RS_REMOVE_NPM=1
  • CLAUDE_RS_KEEP_NPM=1
  • CLAUDE_RS_UNINSTALL=1

After a successful install, an interactive run asks whether to start claude-rs immediately. This runs the installed binary directly, so it works even before a new shell picks up PATH changes. Use --run, -Run, or CLAUDE_RS_RUN=1 to start it automatically after install.

When the startup update screen offers Install update, it detects whether the running executable is owned by a script or npm install and uses the same method. Script updates replace the existing app directory while preserving its launcher and PATH configuration. If the executable is not in a recognized install layout, the screen offers separate script and npm choices instead of guessing from PATH order.

The /config setting Automatic updates defaults to Off, retaining that manual update screen. Turning it On skips the screen and installs an available newer version in the background after a normal exit. Update checks continue in either mode. Automatic installation uses only a recognized script or npm layout and selects the checked release version; an unrecognized source build is left untouched. See Settings.

Supported Script Platforms

Install archives are published for Linux x64/arm64 with glibc, Windows x64/arm64, and macOS x64/arm64.

Linux musl distributions are not supported by the install archives yet. Use npm if your platform has a matching package, or build from source.

The scripts do not require user-installed Node.js or Bun. If npm is available and a global claude-code-rust install is present, the installer identifies its location and offers to uninstall it through npm after the new script installation has passed verification. If the selected release does not contain install archives, the installer exits with:

install script is currently not available for this release

Switching Install Methods

claude-rs is resolved by normal PATH order. npm and script installs use different app layouts, and one method does not automatically own files created by the other. If both are installed, whichever claude-rs appears first on PATH runs.

After verifying a new installation, the installer reports recognized other script installations on PATH and offers to uninstall each one with y Yes / N No. The question names the exact app directory; another copy is not necessarily older. Confirming removes that copy and its owned launcher, manual links, and managed PATH configuration where applicable. Unknown copies receive manual guidance, and installations whose directories overlap the current app or launcher are kept. Different PATH spellings, symlinks, and junctions pointing to the current installation do not produce a duplicate-install prompt.

Declining keeps the other installation. --yes / -Yes and non-interactive runs skip optional cleanup and preserve other script copies. They also keep a detected npm installation unless you explicitly request npm removal with --remove-npm, -RemoveNpm, or CLAUDE_RS_REMOVE_NPM=1. Update mode preserves other installations and does not offer cleanup. Cleanup failures are reported without failing the completed new installation.

To see every visible claude-rs on macOS/Linux:

command -v claude-rs
which -a claude-rs

To see every visible claude-rs on Windows:

Get-Command claude-rs -All

To switch from npm to the install script, either let the installer prompt you or pass the explicit removal flag:

curl -fsSL https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.sh | sh -s -- --remove-npm
$env:CLAUDE_RS_REMOVE_NPM = "1"
powershell -NoProfile -ExecutionPolicy Bypass -Command "irm 'https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.ps1' | iex"
Remove-Item Env:\CLAUDE_RS_REMOVE_NPM

To switch from the install script back to npm, uninstall the script layout first, then install from npm:

npm install -g claude-code-rust

The installers do not silently remove the other install method because that would delete files outside their ownership and can be surprising in managed environments. For non-interactive installs, use --remove-npm / CLAUDE_RS_REMOVE_NPM=1 when you want the script installer to remove the npm install, or --keep-npm / CLAUDE_RS_KEEP_NPM=1 when you want it kept without prompting.

If the wrong claude-rs runs after switching methods, see Troubleshooting.

Uninstall

Remove a script install on macOS/Linux with --uninstall:

curl -fsSL https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.sh | sh -s -- --uninstall

On Windows, PowerShell supports -Uninstall when the script is downloaded first:

.\install.ps1 -Uninstall

With the PowerShell one-liner, arguments cannot be passed through iex, so use CLAUDE_RS_UNINSTALL:

$env:CLAUDE_RS_UNINSTALL = "1"
powershell -NoProfile -ExecutionPolicy Bypass -Command "irm 'https://raw.githubusercontent.com/srothgan/claude-code-rust/main/scripts/install/install.ps1' | iex"
Remove-Item Env:\CLAUDE_RS_UNINSTALL

The script uninstall path removes the script install directory, removes the Unix launcher when it points at that directory, and removes installer-managed PATH entries where supported. It refuses to delete an app directory that does not look like a claude-code-rust script install.

An npm install is owned by npm and is removed with npm:

npm uninstall -g claude-code-rust

Reporting Install Problems

Include:

  • install method
  • OS and architecture
  • terminal
  • npm --version, for npm installs
  • npm config get omit, for npm installs
  • claude-rs --version
  • claude-rs doctor --json
  • the command you ran
  • the exact error output

Usage

Start a new session in the current directory:

claude-rs

While the session connects, the crab beside the welcome overview scuttles and looks around; on the first connect of the process it waves once, then stays still. The prefersReducedMotion setting keeps it still throughout, once claude-rs has read that setting from the connected session.

Start with an initial prompt:

claude-rs "Explain this project"

The prompt is sent automatically after project trust, startup dialogs, and session selection are complete. The TUI stays open for follow-up messages.

Start in a specific working directory:

claude-rs -C path/to/project

Resume a previous session:

claude-rs resume

Resume by session id:

claude-rs resume <session_id>

The Claude-style flags use the same resume workflow:

claude-rs --resume
claude-rs -r <session_id> "Continue reviewing the changes"
claude-rs --continue
claude-rs -c "Finish the review"

--resume without an ID opens the session picker. --continue selects the most recently modified SDK-visible session for the working directory, including its git worktrees; this includes sessions created by claude-rs. If no session exists, it starts a new one. Resume accepts session IDs; name and transcript-path lookup are not supported. Use --resume=<session_id> to make the ID boundary explicit, or --resume -- "prompt" to open the picker with an initial prompt. --resume, --continue, and the resume subcommand cannot be combined.

Choose how the initial session starts:

claude-rs --model opus --effort high --permission-mode plan "Review this project"
claude-rs --agent reviewer "Review the current changes"
claude-rs resume <session_id> --model sonnet --effort medium

--model, --effort, --permission-mode, and --agent apply to the initial new or resumed session before its first prompt. They do not write saved preferences. Later sessions started inside the TUI use saved settings. Model aliases, full model IDs, agent names, and model-specific effort availability are resolved by the SDK. Effort values are low, medium, high, xhigh, and max; max is a session-only override. Permission modes are default, auto, acceptEdits, plan, dontAsk, and bypassPermissions.

Name the session as you start it, or branch from an existing one:

claude-rs -n "Release prep"
claude-rs --continue --name "Release prep, day two"
claude-rs --continue --fork-session --name "Experiment"

-n, --name names a new session or renames the session being resumed or continued. A new or forked session takes the name as its title, and the SDK reports a new session’s title after its first turn. A resumed session is renamed once it has connected, through the same SDK rename as the Status tab, so a resume that fails to start, or that asks you to sign in, leaves its saved title unchanged; a rename that fails is shown as an error and the resumed session stays open. Control characters are removed and a name with no visible characters is rejected. --fork-session resumes under a new session ID and leaves the original conversation and its title unchanged; it requires --resume, --continue or the resume subcommand. With --continue and no earlier session in the directory, --fork-session has nothing to fork and a plain new session starts. The resume hint after exit shows the new session ID. Both apply to the initial session only.

Add directories, settings, MCP servers and system prompt text for a run:

claude-rs --add-dir ../shared --settings ./settings.json --mcp-config ./mcp.json
claude-rs --settings '{"cleanupPeriodDays": 7}' --strict-mcp-config --mcp-config ./mcp.json
claude-rs --system-prompt-file ./release-bot.md --append-system-prompt "Answer in German."
  • --add-dir <PATH> gives Claude access to a directory beyond the working directory; repeat it for more.
  • --settings <JSON_OR_FILE> takes a JSON object inline (a value starting with {) or the path of a JSON file. It becomes the SDK’s flag-settings layer, which outranks the user, project and local settings files; managed policy still outranks it. The layer reaches SDK behaviour only: claude-rs’s own interface preferences (tips, notifications, time format, auto-scroll) are read from the saved settings files, so putting them in --settings does nothing. Explicit launch options such as --model are applied as SDK options of their own. claude-rs lays two host restrictions over this layer: feedbackDrafts is always off, and crossSessionInbound is refuse unless the value in effect, from this layer or else the saved settings, is accept or refuse. Draft review and held peer-message review need surfaces claude-rs does not have.
  • --mcp-config <JSON_OR_FILE> takes the same inline-or-file form, with an object that contains mcpServers, and can be repeated. Servers are merged in command-line order, and a later server replaces an earlier one of the same name. The SDK validates each server definition. --strict-mcp-config restricts the session to the servers supplied this way, ignoring project .mcp.json, user settings, plugins and agent definitions; without any --mcp-config it starts the session with no MCP servers.
  • --system-prompt <TEXT> or --system-prompt-file <PATH> replaces the default system prompt, and --append-system-prompt <TEXT> or --append-system-prompt-file <PATH> appends instructions to it. The text and file spellings of each option cannot be combined, and an empty prompt, inline or in a file, is rejected. claude-rs keeps one instruction of its own in every system prompt, which tells Claude not to stop the bridge runtime process: appended text follows it, and a replacement prompt is followed by it.

Relative paths resolve against --dir, or the current directory without it. Everything is read and checked before logging, the bridge or the terminal starts: a missing directory, an unreadable or empty file, invalid JSON or an MCP config without mcpServers stops the launch with an error that names the flag, and nothing is renamed, written or started. Files are read once at startup, so later edits do not reach a running session. None of these flags write saved preferences, and the Config window shows the saved settings files, not the --settings layer.

Lifetime: --name and --fork-session apply to the initial session. The other flags stay in effect for every session the process starts, including /new-session, sessions opened with /resume and a new session after login. The SDK records a conversation’s system prompt on its first request where recording is enabled; a resumed or continued session then keeps the recorded prompt and ignores a different one, until compaction or a new session. Launch flags apply to interactive launches and cannot be combined with support commands.

An initial prompt whose text matches a subcommand name can be passed after --, for example claude-rs -- "doctor". Startup arguments cannot be combined with support commands such as doctor, logs, config, or completions.

--dir and --bridge-script are checked before the terminal, trust prompt, or bridge start. A missing path, a file where a directory is expected, a directory where the script is expected, a path behind a directory that cannot be searched, a directory without read or search (execute) permission, or a script that cannot be read prints an error naming the flag and exits with status 2. Nothing is saved. Support commands do not refuse them: claude-rs --bridge-script <PATH> doctor reports the same bridge script problem as a failed check instead.

A relative --dir is resolved against the current directory to its absolute path, with . and .. resolved (following symlinks on Unix, lexically on Windows), before it is used for the session, shown as Loc:, or read by config and doctor. An absolute --dir is used as given. claude-rs --dir . shows and uses the current directory’s path, not ..

After the TUI exits, the app prints a resume hint whenever a session was established, using the active or most recently established session id.

Support And Diagnostics

Use support commands when you need a repeatable snapshot of the local environment or diagnostic logs.

CommandPurpose
claude-rs doctorRun installation, runtime, config path, log path, npm metadata, and credential checks.
claude-rs doctor --jsonEmit the diagnostics report as JSON.
claude-rs logsShow diagnostics log locations and useful follow-up commands.
claude-rs logs --tail <LINES>Print redacted lines from the latest discovered log.
claude-rs logs --bundle --yesWrite a redacted ZIP debug bundle.
claude-rs configShow resolved config paths and file states.
claude-rs config showShow a concise redacted config summary.
claude-rs config export --output <PATH>Write a redacted config export without overwriting existing files.

Every run writes a default log of warnings and errors, including failures reported by the bridge and the SDK, without any flag. claude-rs logs --latest prints its path, and --enable-logs adds the detailed records.

A hook that fails shows one warning in the transcript with its exit code and the start of its output, and the failure is also in the default log. Exit code 2 depends on the hook event, as in the hook reference. Where it is the hook’s decision, such as blocking a tool call or a prompt, keeping Claude working, or handing the output to Claude after PostToolUse, it is not a failure and is recorded only in the detailed log; when nothing else shows that decision, as after PostToolUse, PostToolUseFailure or PostToolBatch, the transcript shows one line saying the hook returned a blocking error. Where Claude Code only shows the output to the user, ignores the exit code, or fails the operation on any non-zero exit (as WorktreeCreate does), and on events the reference does not list, it is reported as a failure. A hook cancelled by an interrupted turn is not reported at all.

See Diagnostics for full options, logging presets, bundle contents, and sharing guidance.

CLI Options

The installed claude-rs --help command exposes these options:

OptionPurpose
-r, --resume [ID]Resume by session ID, or open the picker without an ID.
-c, --continueContinue the latest session for the working directory and its git worktrees; start new if none exists.
--model <MODEL>Set the initial session model without changing saved preferences.
--effort <LEVEL>Set the initial session effort; availability depends on the model.
--permission-mode <MODE>Set the initial session permission mode without changing saved preferences.
--agent <NAME>Select the main-thread agent for the initial session.
-n, --name <TEXT>Name a new session, or rename the session being resumed.
--fork-sessionResume under a new session ID, leaving the original unchanged.
--add-dir <PATH>Add a directory Claude may access; repeatable.
--settings <JSON_OR_FILE>Apply temporary settings as inline JSON or a JSON file.
--mcp-config <JSON_OR_FILE>Add MCP servers from inline JSON or a file with an mcpServers object; repeatable.
--strict-mcp-configUse only the MCP servers from --mcp-config.
--system-prompt <TEXT>Replace the default system prompt for new sessions.
--system-prompt-file <PATH>Read the replacement system prompt from a file.
--append-system-prompt <TEXT>Append instructions to the system prompt for new sessions.
--append-system-prompt-file <PATH>Read the appended system prompt instructions from a file.
--no-update-checkDisable startup update checks.
-C, --dir <DIR>Run in a specific working directory, which must exist and be readable and searchable.
--bridge-script <PATH>Use a specific Agent SDK bridge script, which must be a readable file.
--enable-logsAdd detailed info-level diagnostics to the always-on warning and error log.
`–diagnostics-preset <runtimesession
--log-file <PATH>Write tracing diagnostics to a specific file.
--log-filter <FILTER>Use explicit tracing filter directives.
--log-appendAppend to the active log file instead of resetting it on startup.

See Diagnostics before enabling verbose logs.

Shell Completions

claude-rs completions <shell> prints a completion script for bash, zsh, fish, powershell, or elvish. It works with script, npm, archive, and source installations and does not start the bridge or require credentials. All five scripts suggest CLI commands and flags. Bash, Zsh, and Fish also suggest fixed choices such as effort levels; the generated PowerShell and Elvish scripts currently complete command and option names. They do not query live session IDs, model catalogs, or agents. The TUI’s slash-command completion is separate.

For PowerShell, enable completions in the current session:

claude-rs completions powershell | Out-String | Invoke-Expression

Put that same line in your PowerShell $PROFILE to enable completions in future sessions. For Bash, run the following and add it to ~/.bashrc for future shells:

source <(claude-rs completions bash)

For Zsh, generate the script:

mkdir -p ~/.zfunc
claude-rs completions zsh > ~/.zfunc/_claude-rs

Add fpath=(~/.zfunc $fpath) to ~/.zshrc before its completion initialization. If completion is not already initialized, add autoload -Uz compinit followed by compinit after the fpath line.

For Fish:

mkdir -p ~/.config/fish/completions
claude-rs completions fish > ~/.config/fish/completions/claude-rs.fish

Regenerate scripts saved to disk after upgrading claude-rs. The PowerShell and Bash startup lines above generate completions from the currently installed binary each time the shell starts.

Man Pages

A man page is a local command reference opened in a terminal with the Unix man viewer.

Unix release archives include generated manuals under share/man/man1/, including a root page and pages for visible subcommands. The Unix installer links them into share/man/man1/ beside the installation’s bin directory, normally ~/.local/share/man/man1/. Open the manual with:

man claude-rs
man claude-rs-config-show

If your man viewer does not search that directory, use MANPATH="$HOME/.local/share/man:" man claude-rs; the trailing colon preserves its default search paths. Custom --bin-dir installations use the corresponding sibling share/man directory. Uninstall removes only manual links pointing into the script installation.

For npm, source, or manually extracted installations, generate the pages locally with the packaging command:

claude-rs man ./man-pages
man ./man-pages/claude-rs.1

The man generator is hidden from normal command help because it is primarily a packaging utility. It works on Windows too, although viewing the output requires a Unix-compatible man viewer. Help, completion scripts, and manual pages all derive from the same CLI definitions.

Core UI

The main screen is a terminal-owned chat view. The app renders messages, tool calls, diffs, permissions, questions, autocomplete, and status directly through Crossterm and Ratatui.

Common surfaces:

  • Chat input for prompts and multiline text.
  • File, slash-command, and subagent autocomplete.
  • Inline permission prompts for tool decisions.
  • Inline questions for agent-requested choices or text.
  • Fullscreen settings, status, usage, MCP, plugins, and help tabs.
  • Session picker when running claude-rs resume without a session id.

Use /help for the fullscreen help tab, /config for settings, and /docs <topic> for live in-chat help generated from the running app state.

MCP input requests

MCP tools can request input in an editable dialog. Fill the fields, select Accept, Decline or Cancel, and use Esc to cancel. Invalid answers stay available for correction; a failed send keeps the draft for retry. Concurrent requests queue behind the active dialog. See the MCP controls.

Scheduled jobs and notification reads

CronCreate and CronList tool cards show Next run beside the corresponding schedule ID when the SDK supplies it. This is the scheduler’s timestamp, including its scheduling offset; the app does not calculate another time from the cron expression. Dates and clock times use your time format and time zone. Preset formats include the calendar date; custom strftime formats are used as written. Older saved results without a next-run timestamp leave it unknown.

ReadNotifications cards show the queue’s Remaining count and optional Read at timestamp for that drain. Each item keeps its notification ID, origin and literal content, with Queued at for the backend queue timestamp and optional Arrived at for arrival in the local queue. These times describe separate stages; they do not indicate PushNotification delivery. Missing or invalid timestamps are omitted.

Saved conversations preserve these fields when the SDK saved them. Replaying a queue result displays its saved data without sending another desktop notification. These cards retain the normal tool preview limit and hidden-line indicator, keeping the leading IDs and timestamps visible when results are clipped. Full saved content remains available in transcript exports.

More Usage Topics

Slash Commands

Claude Code Rust has app-owned slash commands and can also show slash commands advertised by the active Agent SDK session. App-owned commands are available from the Rust TUI itself; SDK-advertised commands depend on the current session and what the bridge reports.

Use /docs commands in the app to render the live merged command list into chat. That is the source to use when you want to know exactly which app-owned and SDK-advertised commands are available in the current session.

App-Owned Commands

CommandUsagePurpose
/btw/btw <question>Ask a contextual side question without adding it to the main conversation.
/cancel/cancelCancel the active assistant turn.
/compact/compactAsk the active session to compact conversation context.
/config/configOpen fullscreen settings.
/memory/memoryOpen the Memory settings pane.
/permissions/permissionsOpen saved permission defaults, rules and directories.
/sandbox/sandboxOpen sandbox settings without toggling sandboxing.
/hooks/hooksInspect and edit saved hook configuration without executing hooks.
/copy/copyCopy the last completed response, or choose a code block from it.
/diff/diffReview Git changes and full file contents without changing files or the index.
/docs/docs <mode|models|shortcuts|commands|agents>Render command, shortcut, model, mode, or subagent help into chat.
/agent/agent <name|reset>Change the main-thread agent for the active session. Applies on the next turn.
/effort/effort <low|medium|high|xhigh|max|reset>Change thinking effort for the active session.
/thinking/thinking <on|off|reset>Set the thinking preference for the active session or restore its inherited preference.
/ultracode/ultracode <on|off|status>Enable, disable, or inspect Ultracode for the active session.
/fast/fast [on|off]Toggle fast mode or explicitly enable/disable it for the active session.
/help/helpOpen the fullscreen Help tab.
/mcp/mcpOpen MCP status and authorization.
/plugins/pluginsManage installed plugins, marketplaces and session-only local folders.
/status/statusOpen session and account status.
/usage/usageOpen quota and usage information.
/agents/agentsOpen this session’s subagents with their live status and saved transcripts.
/login/loginRun Claude CLI authentication and reconnect the session.
/logout/logoutRun Claude CLI logout and clear the active authenticated session.
/mode/mode <id>Switch to a mode advertised by the active session.
/model/model <id>Switch to a model advertised by the active session.
/new-session/new-sessionStart a fresh bridge session in the current folder.
/resume/resumeSearch and select a session in the fullscreen picker.
/rewind/rewind <user_message_uuid> <both|conversation|code>Restore conversation, code, or both to a previous user message.
/reload/reloadRe-read skills and output styles from disk for the active session.
/export/export [path]Save the complete conversation as a Markdown file.

Enter completes the selected slash command or argument and submits it when ready. Tab completes without submitting. Exact command names appear ahead of substring matches; arrow keys can select a different match. App commands that still need required arguments stay in the composer; commands with argument choices show those choices, while /btw continues as ordinary question text. An empty suggestion menu allows Enter to submit the typed input for normal validation.

Editing the draft cancels a pending submission. Editing, completion, and submission keys cannot change or send the draft while pasted text is awaiting insertion, including when suggestions are open or keys are remapped. Suggestions refresh after the pasted text is inserted.

Completing the name of a command with no arguments or optional arguments closes the popup and returns focus to the draft. For commands accepting arguments, pressing Tab again requests argument completion explicitly. When the SDK provides only an argument hint, Tab displays that hint without changing or sending the draft; Enter sends the typed command for SDK validation. SDK hints are descriptive text, so their brackets never determine whether the app allows submission. Empty hints and none or [none] do not produce argument help.

Space inserts a literal separator without accepting the highlighted suggestion. It ends command-name completion and continues argument assistance only when the app requires arguments, or when you explicitly requested argument help. There is no special Space dismissal state. Escape dismisses the current menu; argument edits, cursor movement within arguments, and metadata refreshes keep it closed. Tab requests completion again, and editing the command name starts a new completion interaction. A command is recognized only at the start of the draft, allowing leading whitespace; slashes on later lines remain literal prompt or argument text.

The command menu includes the full merged inventory and scrolls as you move through it. SDK commands remain available after /clear changes the session identifier. In SDK sessions that advertise /clear [name], /new and /reset are aliases; the optional name labels the conversation you are leaving. /new-session is the separate app command that starts a fresh bridge session. App command definitions take precedence when the SDK advertises the same name.

Resuming sessions

/resume opens the same fullscreen session picker used by claude-rs resume at startup. Type to filter by session name, session ID, or branch name; search matches partial text without case sensitivity, and pasted text also searches. Up/Down selects a matching session, Enter resumes it, and Escape closes the picker without switching sessions. Backspace edits the search. The scrollable list shows the SDK-provided title, last activity, branch when available, session ID, and a marker for the current session. All available sessions for the project directory are searchable.

Refreshing session metadata keeps the selected session by ID when it still matches. If it disappears or stops matching, the next result at that position is selected, or the previous result at the end. An empty result list stays open and cannot resume an unrelated session; edit the search or press Escape. Right activates the fork action and opens the message picker; Left/Escape returns to the filtered session list. Message previews wrap to the terminal width, preserve paragraph breaks, and show up to four text lines with a more indicator for longer messages. Up/Down selects a message, and Enter forks before it. Right opens the selected message for full-text reading with Up/Down scrolling; Left/Escape returns to the message list.

Session selection happens inside the picker; /resume has no inline session suggestions or chat arguments. Ordinary command-name completion still completes /resu to /resume. For direct resume by ID from the terminal, use claude-rs resume <session_id>.

Resumed history displays saved Claude command records as readable commands, such as /rename review-444, and command output as notices. Internal command context, compaction summaries, and background-task notifications are excluded from the fork list. Ordinary conversation XML remains literal, and saved session content is unchanged.

Exporting the conversation

/export [path] writes the session’s saved history to a Markdown file. The history comes from the Agent SDK’s saved transcript, translated by the same code a resume uses, not from the chat on screen, so it includes messages the app no longer keeps in memory and history from before a compaction.

Without a path the file is export-<session-id>-<YYYYMMDDTHHMMSSZ>.md in the session directory, using the full session ID and the export time in UTC, for example export-11d785e2-d277-406c-9f99-31d840a3705b-20261013T123045Z.md. With a path, a relative path is relative to the session directory, a leading ~/ is your home directory, and everything after the command is the path, so spaces need no quoting: /export ./session notes.md. On Windows, drive-letter and UNC paths (C:\Users\me\notes.md, \\server\share\notes.md) are used as given and ~\ also means your home directory. A drive-relative path such as C:notes.md is refused, because it points at that drive’s current directory and not at the session directory.

The file starts with the session title, ID, directory, model, export time and a Not included line naming what is never exported: thinking blocks, images inside tool results, background task state, and timing and other session metadata. Your messages and the assistant’s text are written as they were, except that a code fence or HTML comment a message leaves open is closed at the end of that message, and a line that would read as one of the export’s own User, Assistant or Tool: headings gets its first # escaped, so message text cannot change the file’s structure. Saved command output, notices and notifications appear as quoted notes. Each tool call is a heading with the tool name and a short summary of its input, followed by its result in a fenced block and, for edits and new files, a diff block. Results over 60 lines or 4,000 characters and diffs over 200 lines are cut with a note saying how much is shown, and terminal colour codes are removed. A session too large to send at once keeps its beginning, and the file ends with a note saying how many later entries were left out. History entries the app cannot show, such as an image of an unsupported type, are counted in a closing note, and an image in a tool result is named where it occurred. Rendering and writing happen on the app’s event loop, so the terminal pauses until a very large export is written.

/export never overwrites a file and creates no directories. If the default name is taken, it uses -2, -3 and so on before .md. If an explicit destination exists (a directory is reported as a directory), or its directory does not, the command reports the error and writes nothing. When it finishes it shows the absolute path it wrote, or the failure.

Reviewing Git changes

/diff opens a fullscreen, read-only Git viewer for the repository containing the current directory. The left pane shows changed files in an expanded tree; folders are not selectable. Each file shows its status and line counts, with additions in green and removals in red; zero counts are hidden. Totals appear above the tree. The right pane previews the selected file. Binary files, submodules, unavailable files, clean repositories, and Git read failures are shown explicitly. Repositories without a first commit are supported.

Press s to choose a comparison with Up/Down and Enter; Escape cancels. HEAD compares the last commit with current files, Staged compares the last commit with the Git index, and Unstaged compares the index with current files. HEAD and Unstaged also include untracked files that Git does not ignore. This view shows repository changes, not session or turn history.

Refresh keeps the current pane focused and retains the selected change when it remains available. If that change disappears, the next remaining file takes its place, or the previous file when the selection was at the end. If no changes remain, the viewer clears the old preview and stays open with an empty-state message.

KeyAction
Up/DownSelect files in the left pane or scroll content in the right pane.
Enter or RightFocus the content pane.
Left or Escape in the content paneReturn focus to the file tree.
Tab / Shift+TabSelect the next/previous file without changing the focused pane.
vToggle the diff and full file contents. Staged shows the indexed version; deleted files show their contents before deletion.
[Jump to the previous diff hunk (changed block).
]Jump to the next diff hunk (changed block).
rRefresh, retaining the selected file when it remains in the comparison.
Escape in the file treeReturn to the conversation.
Ctrl+CClose the viewer and return to the conversation.
Ctrl+QQuit the app.

Copying responses

/copy copies the last completed assistant response as its original Markdown, without thinking or tool output. Responses loaded from session history can be copied too. If the response contains code blocks, choose Full response or a code block with Up/Down, then Enter; Escape cancels. Enable Skip the /copy picker in /config to copy the complete Markdown response directly. Responses without code blocks copy directly. If the clipboard is unavailable, the picker stays open so you can retry. The command can copy an earlier completed response while a new response is still running; it does not submit a model request.

Reloading skills and output styles

/reload asks the active session to re-read skills and output styles from disk, so a skill or style you just edited applies without restarting. The input is blocked until the SDK has answered both reloads, output styles first, then a single notice reports how many skills and output styles it found. The two halves are reported separately: one that fails shows its error next to the count for the other, and one that does not answer within 10 seconds is reported as unanswered (it may still apply) instead of as a failure. Before it runs, /reload waits for earlier requests for the same session to finish. If they take longer than 10 seconds from when /reload reached the bridge, whether stalled or just slow, /reload is skipped, nothing is reloaded, and a notice says so; it does not run later when the earlier request finishes. Once started, each half is given 10 seconds, so the input can stay blocked for up to 30 seconds in all; either way it is released. The slash command list picks up new or changed skills through the SDK’s own command-list update. /reload does not reload plugins; use the Plugins tab for that.

Side Questions

/btw treats the complete non-empty text after the command as one question, including internal spaces and line breaks. Side questions are shown in a separate status field while pending and produce a bordered Claude · BTW transcript card only when answered. During an active turn, the card is inserted at the current point in the agent’s output, with subsequent output below it; when idle, it is a standalone transcript entry with the same design. You can continue using the normal composer while up to ten side questions are unresolved; Rust queues and dispatches them one at a time in submission order. Each question sees main-conversation context at SDK dispatch time, not a snapshot from submission. Failures free capacity immediately and remain visible briefly as error rows.

SDK-Advertised Commands

The active SDK session can advertise additional slash commands. These are not documented as a fixed table here because they can change with SDK behavior, session capabilities, account state, and future upstream changes.

Use:

/docs commands

to inspect the current session’s full command list. The output includes app-owned commands and SDK-advertised commands, with descriptions when the SDK provides them.

Session Name

The Status tab shows the session name. Its rename draft (r) starts from that name, and title generation (g) uses it as the description when there is one.

Renaming goes through the Agent SDK, which records the new name in the session’s saved transcript. Claude Code saves a session once it runs a command or a message, so until then the rename dialog stays open and editable but cannot be confirmed, and says so beneath the field. claude-rs looks for the transcript, <session id>.jsonl in the session’s project folder under the Claude configuration directory (CLAUDE_CONFIG_DIR, ~/.claude by default), when the Status tab opens, when the dialog opens, after each turn while Status is open, and when the session changes. If it cannot look, the dialog shows that error instead. The rename’s success or failure is reported in Status, not in the chat; a failed rename keeps its draft in the dialog.

The name is whatever the Agent SDK’s session API reports as the session’s title; claude-rs keeps no title of its own. It is read when a session connects or resumes, when the session is replaced, when the conversation resets, after each turn, and after a Status-tab rename or title generation. A /rename typed in the composer therefore shows once its turn completes. For a session nobody named, the API reports a generated title instead, so such a session shows that title after its first turn. Until the API reports a title, Status shows (unnamed session); it does not fall back to the session’s summary or first prompt, which after /clear are the command itself.

Commands that Claude Code runs locally, such as /rename, /color or /context, reply in the chat under the command as they do in Claude Code. /color runs in Claude Code and its reply shows, but Claude Rust does not draw a session colour.

Session Commands

/ultracode on enables session-scoped dynamic-workflow orchestration while retaining the current thinking effort; /ultracode off disables it. Both require an idle turn. /ultracode status can be used during a turn and reports the latest verified SDK snapshot: on, available and off, requested but unavailable, unavailable and off, or unknown. Availability depends on SDK session capabilities and model support. The footer shows Ultracode only when it is verified as effective. Changing effort preserves active Ultracode, and changing models refreshes its state. This command does not persist a preference or control the one-turn ultracode keyword trigger.

If the SDK accepts /ultracode on but reports Ultracode unavailable, the command shows an error explaining that the request was saved but Ultracode remains inactive. The verified requested-but-unavailable state remains visible through /ultracode status, which reports it as information.

/model, /mode, /effort, /thinking, /agent, /fast, and /ultracode change the current session; /config edits saved defaults for new sessions. Choices are checked against SDK capabilities and acknowledged only after the SDK accepts them. Model, effort, fast mode, and Ultracode show reported runtime results, including caps or fallbacks, rather than echoing requests. The starting permission mode comes from SDK initialization, before the first prompt. Saved permission defaults remain inherited by the native session. Both /mode and the mode-cycle shortcut keep the confirmed mode visible while awaiting SDK acceptance; a rejected change leaves it unchanged.

/effort reset uses the current model’s native session default; it does not reload the saved per-model effort. max is session-only. /thinking reset removes the temporary override and restores the inherited thinking preference. Thinking is a preference, and the model may still require or restrict thinking. /agent reset clears the active main-thread agent rather than restoring its saved default.

/fast changes fast mode only for the active session. It does not rewrite the persisted Fast mode setting. Use the settings surface to choose the fast-mode preference applied when future sessions start. If an accepted change cannot be verified, the footer shows FAST:?; retry explicitly with /fast on or /fast off.

/agents lists the active session’s subagents in lifecycle order and keeps selection by task identity across execution runs. Details show the subagent type, known parent, current run ID, model source, transcript availability, current activity or lifecycle result, recent tool calls and prompt. Observed models take precedence over requested or agent-default models. Forks inherit their parent’s model; ignored model and effort overrides are not shown as applied. Unknown or finished parents do not prevent reading or stopping a child. Ambient housekeeping tasks are excluded. The configurable footer counts running subagents once per task; see Footer.

A completed row can show a Saved response preview. This is the last reply in the SDK’s saved conversation, including reports sent through SubagentHandback; persistence may still contain an older run’s report. The lifecycle result is the authoritative outcome of the current run. Enter opens the whole saved conversation, with Markdown replies, tool calls and labeled SDK reminders. User-authored tags remain literal. A run change invalidates the preview; an open older transcript remains a labeled saved snapshot at its current scroll position until r refreshes it. The SDK provides no run-specific transcript selector.

A transcript becomes available only when the SDK lists it; r checks again and retries failed reads. s requests a stop for the selected running execution. Stopping state and acknowledgements are correlated to that request and run; only the lifecycle establishes the stopped outcome. A resumed session retains recorded outcomes and labels unfinished historical work as interrupted, without counting it as running or offering a stop. Keys are listed in Keyboard Shortcuts.

Opening or refreshing /agents also restores saved agents at every nesting depth, including children launched inside another agent. They join the same inventory as live agents, with their saved ancestry and supported outcomes. Missing completion evidence is shown as interrupted. This discovery does not add nested conversations to the main chat transcript.

Keyboard Shortcuts

Keyboard shortcuts are context-sensitive. Use /docs shortcuts in the app to show the live shortcuts for the current state.

Global

ShortcutAction
Ctrl+QQuit.
Ctrl+LRedraw.
Ctrl+Z on UnixSuspend the process.

In a fullscreen view, Ctrl+C closes the view and returns to chat. After shutdown begins, pressing Ctrl+C again forces any remaining cleanup to stop.

Chat Reading

ShortcutAction
Page UpPause following and read earlier output.
Page DownRead later output.
Ctrl+EndJump to the latest output. Following resumes when Auto-scroll is On.

See Presentation and scrolling for the Auto-scroll setting.

Settings Surface

The fullscreen settings surface has its own keys for tabs, panes, search and editors. See Opening and navigating, Editing a value and Lists and structured settings.

Plugins

Open /plugins. Left and Right switch between Installed, Plugins, Marketplace and Session; Up and Down select an entry. Outside search, l opens Load local folder. In Session, Enter opens the selected folder for reloading, or the new-folder input; r reloads the runtime inventory. In the folder input, Enter requests loading and Esc returns. A held reload defaults to declining; select Apply explicitly to add the same folders and invalidate the prompt cache. Esc declines and keeps the folder draft.

Subagents View

/agents, or Left in an empty input, opens the current session’s subagents.

ShortcutAction
Up, DownSelect a subagent.
EnterOpen the selected subagent’s saved transcript.
sAsk the selected running subagent to stop.
rCheck again which subagents have a saved transcript, and read the selected subagent’s response again.
Page Up, Page DownScroll the selected subagent’s details.
EscReturn to chat with the draft unchanged.

In a transcript, Up and Down scroll, Page Up and Page Down scroll by a page, r reads the whole saved conversation again at the same position (also after a failed read), and Esc or Left returns to the list. If the agent starts another run, the open transcript stays labeled as a saved snapshot until r; returning to the list refreshes the current run’s saved-response preview.

Chat Input

ShortcutAction
EnterSubmit.
Shift+Enter, Ctrl+EnterInsert newline.
EscCancel the active assistant turn.
Ctrl+CClear the local draft, or quit when the draft is empty.
TabFocus prompts or accept suggestions.
Shift+Tab, Shift+RightSwitch to the next permission mode, wrapping after the last.
Shift+LeftSwitch to the previous permission mode, wrapping before the first.
Shift+Up, Shift+DownRaise or lower effort to the next level the current model supports, stopping at the highest and lowest level.
UpMove up through text, or recall the latest user message when the input is empty.
LeftMove left through text, or open /agents when the input is empty.
Down, RightMove through text.
Home, EndMove to line start or line end.
Ctrl+Left, Ctrl+RightMove by word.
Alt+Left, Alt+RightMove by word.
Ctrl+Backspace, Ctrl+DeleteDelete by word.
Alt+Backspace, Alt+DeleteDelete by word.

Shift with an arrow key changes the permission mode or effort; it does not select text. Mode and effort shortcuts act only while the composer has focus and no turn or command is running. They change the current session only and keep the draft. The footer updates once Claude confirms the change.

Readline-style bindings are also supported:

ShortcutAction
Ctrl+A, Ctrl+EMove to line start or line end.
Ctrl+B, Ctrl+FMove one character.
Ctrl+DDelete after cursor.
Ctrl+HDelete before cursor.
Ctrl+KKill to line end.
Ctrl+UKill to line start.
Ctrl+WDelete previous word.
Ctrl+YYank.
Alt+B, Alt+FMove by word.
Alt+DDelete next word.

Undo And Redo

PlatformUndoRedo
macOSCmd+ZCmd+Shift+Z, Cmd+Y
WindowsCtrl+ZCtrl+Shift+Z
Unix except macOSCtrl+_, Ctrl+/Ctrl+Shift+Z

On Unix except macOS, Ctrl+Z is reserved for process suspend.

Autocomplete

ShortcutAction
Up, DownMove through candidates.
Enter, TabAccept the selected candidate.
EscCancel autocomplete.

Inline Permissions

ShortcutAction
Left, UpMove to the previous option.
Right, DownMove to the next option.
EnterConfirm the focused option.
EscCancel.
TabMove focus.

Letter shortcuts such as Ctrl+A, Ctrl+Y, or Ctrl+N are not permission shortcuts.

Inline Questions

ShortcutAction
Left, UpMove to the previous option.
Right, DownMove to the next option.
Home, EndMove to first or last option.
SpaceToggle/select where applicable.
EnterSubmit.
EscCancel.
TabToggle notes or move focus.
Shift+TabMove focus backward.

MCP input forms

ShortcutAction
Tab, DownNext field or action.
Shift+Tab, UpPrevious field or action.
Left, RightMove the text cursor or change the highlighted choice.
SpaceToggle a boolean or multi-choice option; insert a space in text.
Ctrl+OInclude or omit the focused optional field.
EnterAdvance from a field or activate the selected action.
Ctrl+EnterValidate and accept, if distinguished by the terminal.
EscCancel the active request.

Type or paste into text and numeric fields. Home, End, Backspace and Delete edit the focused text. While a response awaits SDK confirmation, editing and repeated submission are disabled. Queued requests retain their own drafts and activate in arrival order.

Settings

Claude Code Rust has a fullscreen settings surface with multiple tabs. These slash commands open that surface directly:

CommandTabPurpose
/configSettings → GeneralEdit saved defaults and everyday preferences.
/memorySettings → MemoryConfigure context, checkpoints, automatic memory and plans.
/permissionsSettings → PermissionsConfigure saved permission defaults, rules and working directories.
/sandboxSettings → SandboxConfigure sandbox execution, filesystem, network and credentials.
/hooksSettings → HooksInspect and edit saved hook handlers without executing them.
/mcpMCPInspect live MCP server status and complete MCP authorization flows.
/pluginsPluginsManage installed plugins, marketplace plugins, and marketplaces.
/statusStatusInspect session, account, authentication, and runtime status.
/usageUsageInspect quota and usage information reported by the active session.
/helpHelpOpen fullscreen in-app help.

The settings surface is session-aware. Settings load when the app’s session starts, and some tabs need an active session before they can show live data.

Opening and navigating

Every command in the table above opens the same fullscreen surface on a different starting tab. The tab order is:

Settings -> Plugins -> Status -> Usage -> MCP -> Help

Tab moves to the next tab and Shift+Tab to the previous one. Esc closes the surface. Enter closes it as well wherever the selected item has no action of its own. The hint line at the bottom of the surface shows what Enter and Esc do at the current position. Each tab also has its own keys: the Plugins tab navigates plugin lists, the MCP tab opens server actions and authorization flows, the Status tab renames the session with r or generates a title with g, and the Usage tab refreshes with r.

Settings panes

The Settings tab has a second row with six panes: General, Memory, Permissions, Sandbox, Hooks, and Workflows & Worktrees. Each pane is one alphabetical list. Focus moves between three areas stacked from top to bottom: the pane row, the search field, and the list.

FocusKeyAction
ListUp on the first itemMove to the search field.
Search fieldUpMove to the pane row.
Search fieldDown, EnterMove to the list.
Pane rowLeft, RightSwitch pane.
Pane rowDownMove to the search field.
Pane rowEnterMove to the list.

Each pane remembers its own selection. Switching to another top-level tab and back keeps the pane, selection and search.

Below 30 columns or 12 rows the surface asks you to resize the window instead of drawing an unusable layout.

Press / to search the current pane. A setting matches when its label, description or setting ID contains every word you typed, ignoring case. Search covers only the current pane and never looks inside saved values such as hook commands, credential entries or environment values.

KeyAction
Enter in the search fieldMove to the results.
Enter on a resultClear the query and keep that setting selected in the full list.
EscClear the query and return to the previous position. Without a query, Esc closes the surface.

Switching panes clears the search.

Help

Use /help when you want fullscreen help inside the same tabbed surface. The Help tab has three sections:

SectionShows
ShortcutsKeyboard shortcuts for the current app state and focused UI context.
CommandsApp-owned slash commands plus slash commands advertised by the active SDK session.
SubagentsSubagents advertised by the active SDK session, including model labels when provided.

Use Left and Right inside the Help tab to switch sections. Use Up and Down to move through rows in the active section.

The Help tab is live UI, not a static manual page. Its Shortcuts section changes with focus and state, and its Commands and Subagents sections depend on what the active SDK session advertises.

Where settings are saved

Each save goes to one scope. Press s in the list to cycle the save scope through User, Project and Local.

ScopeFileUse
User~/.claude/settings.jsonPersonal defaults for every project.
Project./.claude/settings.jsonDefaults shared with the repository.
Local./.claude/settings.local.jsonPrivate defaults for this project.
ManagedOrganization policyShown for information. Settings restricted by policy are read-only.
App preferencesclaude-code-rust/settings.json in the OS config directory, or <CLAUDE_RS_CONFIG_DIR>/settings.json when overriddenThis app’s own preferences: footer layout, tab-title activity, the /copy picker, notification categories and automatic updates. Always saved for the user.

Not every setting can be saved at every scope. A setting that the selected scope cannot hold is read-only until you switch scope; Settings by pane lists the restrictions.

Workspace trust is recorded separately in ~/.claude.json. It is not a settings scope and is never used as a fallback for a setting.

Set CLAUDE_CONFIG_DIR before startup to use an isolated Claude profile. User settings then live in <directory>/settings.json, workspace trust in <directory>/.claude.json, and file credentials in <directory>/.credentials.json. Sessions, plugins and authentication use the same directory. Project and Local settings stay in the project, and app preferences and diagnostics keep their normal OS locations.

Set CLAUDE_RS_CONFIG_DIR to select a separate directory for this app’s preferences. They are read from and saved to <directory>/settings.json, including the footer layout, presentation preferences, notification categories and update preferences. An empty or unset value uses the normal OS config location. This override is independent of CLAUDE_CONFIG_DIR; diagnostics retain their normal location.

The Settings tab shows saved values. A running session can differ, because workspace trust, managed policy, model capabilities, startup arguments and session commands also apply. The Status tab and the chat footer show what the session is running with.

Reading the list

Each row shows a setting and its value, and a counter such as 1/27 shows the position in the pane. Below the list, Description: explains the selected setting and a context line states where its value comes from at the selected scope:

Context lineMeaning
Saved in UserThe value is saved at the selected scope.
User value: … · Overridden by ProjectA value is saved at the selected scope, but another scope takes precedence.
From Project · Not set in UserThe value comes from another scope.
Using DefaultNo scope sets a value.
Not set in UserA list or structured setting has no entries at the selected scope.
Saved in User · Not loadedThe file contains the value, but Claude did not load it.
· Also supplied by ProjectAnother scope contributes as well, as with merged lists.
· Applies immediately, · Applies to new sessionsWhen a saved change takes effect.

Default means that no scope sets a value. It does not say whether the built-in behavior is On or Off; where the built-in behavior is known, the description states it, for example Default: On.

Read-only restrictions and settings-file errors appear as warnings below the description.

Claude decides which settings files it loads: some invalid entries are ignored individually, while other schema errors exclude the whole file. Not loaded reports that outcome without naming the cause. Saving and resetting still work on any readable file, and correcting the offending value restores loading.

Editing a value

KeyAction
Up, DownSelect the previous or next setting.
Home, EndSelect the first or last setting.
Page Up, Page DownMove one page.
Left, RightStep through the choices of an On/Off or fixed-choice setting. The change is saved immediately.
SpaceSame as Right for fixed choices. Opens the editor for text, number, list and structured settings.
EnterOn a list or structured setting, opens the editor, or opens it for inspection when the scope is read-only. On any other setting, closes the surface.
DeleteReset the setting at the selected scope.
sCycle the save scope.
rReload settings from disk.

Changes made with Left, Right or Space are saved as you make them, so closing with Enter or Esc discards nothing.

The text editor used for settings such as Language takes Enter to save, Ctrl+R to reset and Esc to cancel.

Reset removes the value saved at the selected scope. The row then shows the value from another scope, or Default. Reset does not write a replacement value and does not restore an earlier edit.

While a save is in progress the row keeps showing the last confirmed value. A successful save shows Saved.

Saving a default never changes the running session. Use /model, /mode, /effort, /thinking, /agent, /fast or /ultracode for the current session; see Session Commands.

Lists and structured settings

Permission rules, directory and domain lists, hook definitions and the structured sandbox settings open an editor instead of changing in place. The row in the main list shows how many entries are saved at the selected scope.

The editor loads only the entries saved at the selected scope, not a merged view of all scopes, and keeps that scope until it closes.

KeyAction
Up, Down, Home, EndMove through entries or fields.
aAdd an entry.
Enter, SpaceEdit the selected entry, open a nested group, or toggle an On/Off field.
DeleteRemove the selected entry or optional field.
Ctrl+SSave the draft.
Ctrl+RReset the whole setting at this scope.
EscGo up one level. At the top level, discard the draft and close the editor.
Ctrl+JSwitch to a JSON view of the same draft.
Ctrl+FReturn from JSON to the form. The JSON must be valid.

While typing in a field:

KeyAction
EnterAccept the field into the draft.
EscCancel the field.
Ctrl+UClear the field.
Ctrl+JInsert a line break.
Up, Down, Left, RightChoose a value when the field offers fixed choices.

Rules for these structured editors:

  • Edits stay in a draft until Ctrl+S. Accepting a field does not write the file.
  • Many lists merge across scopes. Removing the last entry saves an explicit empty list, and entries from other scopes still apply. Reset removes the setting from this scope instead.
  • Invalid JSON or a value that Claude rejects keeps the draft open for correction. Nothing is written.
  • If the file changed on disk while the editor was open, the editor loads the latest version and keeps your draft. Save again to confirm.
  • If the session moves to another project while an editor is open, saving is blocked. Close the editor and open it again.
  • A scope that cannot be edited can still be opened for inspection.
  • Opening, browsing and validating never run hooks or credential helpers, and never read secret files or environment values. Header values and command arguments are redacted in summaries.
  • Fields that the form does not know are preserved when you save.

Editing permission rules

In the Permissions pane, open Allow rules, Ask rules, Deny rules or Additional directories. Add one tool rule per entry, for example Bash(npm test *) or Read(./src/**). A deny rule wins over an allow rule from any scope.

Editing hooks

Hooks → Definitions shows a flat list with each hook’s event, matcher and action.

  • a starts guided creation: choose an event, enter an optional matcher, choose an action, fill its required fields, then review. Enter on the review step adds the hook to the draft and opens its optional fields. Esc goes back one step and cancels at the first step.
  • Enter edits the selected hook.
  • m edits the matcher of the hook’s group. Every hook in that group shares the matcher.
  • Delete removes only the selected hook.

Hook actions are command, prompt, agent, HTTP and MCP tool. Event names come from the installed SDK. The JSON view shows the same definitions in the settings-file format:

{
  "PreToolUse": [
    {
      "matcher": "Bash",
      "hooks": [
        { "type": "command", "command": "echo Check shell operation", "timeout": 10 }
      ]
    }
  ]
}

Saving replaces the hooks object at the selected scope. Hooks from other scopes keep merging in. Disable all is a separate On/Off setting.

Command and HTTP actions offer Failure policy (onFailure): continue reports a failed hook and lets the guarded action proceed; block treats the failure as exit code 2. Failures include startup errors, timeouts, exit codes other than 0 or 2, and invalid JSON or JSON that does not match the hook schema. Unset uses continue. Select the field and press Delete to remove only that handler’s override, then Ctrl+S to save.

The SDK ignores this policy for asynchronous hooks and the Stop, SubagentStop, TaskCompleted and TeammateIdle events. It decides whether an event can block an action. Editing or validating the policy never executes a hook.

Editing sandbox settings

Path, domain and command lists use the list editor. Credential protection, TLS termination, Ignored violations and Ripgrep command open forms:

  • Required fields are marked with *.
  • Fixed choices open a picker.
  • Credential entries take file paths and variable names, never secret values.
  • TLS termination takes both a CA certificate path and a CA key path, or neither.
  • Proxy ports accept whole numbers from 1 to 65535.

Settings by pane

Every row has a description in the app. This section covers behavior that needs more explanation. Unless noted, a setting can be saved at User, Project or Local scope and applies to new sessions.

General

SettingKeyChoicesNotes
Default modelmodelModels offered by the sessionA model ID cannot be typed. A value written by another tool is kept until you change or reset it.
Default effortmodelSettings.<model>.effortLevelEffort levels of the default model, without maxSee below.
Default agentagentAgents offered by the session
ThinkingalwaysThinkingEnabledOn / OffA preference. The model may still require or restrict thinking.
Fast modefastModeOn / OffAccount and model eligibility still apply.
Output styleoutputStyleTextA built-in or custom style name.
LanguagelanguageTextPreferred response language. Does not translate the app.
Question timeoutaskUserQuestionTimeoutNever / 60 seconds / 5 minutes / 10 minutesUser only. See below.
Dialog expirydialogExpiry60 seconds / 5 minutes / 10 minutes / NeverUser only. See below.
Respect .gitignorerespectGitignoreOn / OffHides ignored files from the file picker. Applies immediately.
Reduce motionprefersReducedMotionOn / OffShows a static ◆ in place of animated spinners and keeps the welcome crab still. Applies immediately.

General also holds the settings described under Presentation and scrolling, Notifications and Automatic updates.

Default effort belongs to the saved Default model and is saved per model, so changing Default model switches the effort row to the new model. max is available only through /effort in a session. The row is read-only when the default model is unknown or offers no effort levels. Environment settings, workspace trust and organization caps can still change the effort a session runs with; the chat footer shows the applied level.

Question timeout submits a waiting question after the chosen idle time. Only answers you explicitly selected are sent, together with any notes; untouched questions are skipped. Keyboard, paste and mouse activity restart the interval, and the timer pauses while another screen has focus. Never waits for confirmation.

Dialog expiry cancels forwarded remote dialogs and held cross-session messages after the chosen time. Local permission prompts get no deadline. Reset restores 5 minutes. The CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS environment variable takes precedence.

Memory

SettingKeyNotes
Auto compactautoCompactEnabledCompacts context automatically.
Idle compactionidleCompactionOff stops compaction while idle. On or Default does not enable the feature. User, Project and Local scopes; saved for the next session.
File checkpointsfileCheckpointingEnabledRecords file snapshots for code rewind.
Automatic memoryautoMemoryEnabledReads and writes automatic memory for the project.
DirectoryautoMemoryDirectoryUser and Local only; shared Project settings cannot redirect memory. Supports ~/.
Excluded instructionsclaudeMdExcludesOne glob or absolute path per entry. Managed instructions cannot be excluded.
Plans directoryplansDirectoryRelative paths are relative to the project root.

Idle compaction follows the SDK’s settings cascade. Reset removes the preference at the selected scope and exposes the remaining scope or Default. Its saved On/Off value is a preference, not evidence that idle compaction is available or running; availability remains under SDK control.

Permissions

SettingKeyNotes
Default permission modepermissions.defaultModeUser only. default, plan, acceptEdits, auto, dontAsk or bypassPermissions, subject to workspace trust and account restrictions.
Auto mode during planninguseAutoModeDuringPlanUser and Local only.
Disable bypasspermissions.disableBypassPermissionsModeRemoves the bypass permission mode. Reset removes this scope’s restriction.
Block outside readspermissions.blockReadsOutsideWorkingDirectoriesBlocks Read, Grep, Glob and LSP outside working directories. On in any scope wins.
Allow rules, Ask rules, Deny rulespermissions.allow, permissions.ask, permissions.denySee Editing permission rules.
Additional directoriespermissions.additionalDirectoriesOne directory per entry.

Sandbox

The Sandbox pane covers sandbox execution, filesystem paths, network domains, proxy ports and credential protection under the sandbox. key. Descriptions name the settings that apply to one platform only. Workspace trust, platform support and organization restrictions decide which saved values take effect, and can make rules and allowlists read-only.

These settings are User only: Disable filesystem isolation, Strict domain allowlist, TLS termination, Credential protection, Allow Apple Events and Ripgrep command.

Hooks

SettingKeyNotes
DefinitionshooksSee Editing hooks.
Disable alldisableAllHooksDisables settings and plugin hooks, including status-line execution.
Allowed HTTP URLsallowedHttpHookUrlsOne URL pattern per entry; * is a wildcard. An empty list blocks all HTTP hooks.
Allowed environment variableshttpHookAllowedEnvVarsVariable names that HTTP hook headers may interpolate.

Workflows & Worktrees

SettingKeyNotes
Dynamic workflowsenableWorkflowsAvailability depends on the account.
Workflow keyword triggerworkflowKeywordTriggerEnabledAllows keyword-triggered workflows.
Workflow sizeworkflowSizeGuidelineAn advisory agent count: Small aims below 5, Medium below 10, Large below 50. Unrestricted gives no guideline.
Worktree base refworktree.baseReffresh or head.
Symlink directoriesworktree.symlinkDirectoriesRepository directories shared with new worktrees, for example node_modules.
Sparse pathsworktree.sparsePathsDirectories included through Git sparse-checkout.
Background isolationworktree.bgIsolationworktree makes background jobs enter a worktree before editing; none allows edits in the main checkout.

Unavailable settings

Continue at usage limit and Messages from other sessions are listed in General but are read-only in this version. Themes and Vim editor mode are not offered.

Presentation and scrolling

These General settings apply immediately, including to the conversation already on screen.

SettingKeyChoicesBehavior
Auto-scrollautoScrollEnabledOn / OffFollow new output when On; hold the reading position when Off.
Show tipsspinnerTipsEnabledOn / OffShow tips during active turns. Off hides only the tip text. Default: On.
Show message timestampsshowMessageTimestampsOn / OffShow the message time beside its role label. Default: Off.
Show turn durationshowTurnDurationOn / OffShow one total elapsed time per completed response. Default: Off.
Time formattimeFormatAuto / 12-hour / 24-hour / 24-hour UTCFormat clock times. Elapsed durations are unaffected.
Show activity in tab titlepresentation.showStatusInTerminalTabOn / OffShow a busy/idle icon beside the folder name in the terminal tab title.
Skip the /copy pickerpresentation.copyFullResponseOn / OffCopy the complete response directly. See Copying responses.

The first five are Claude settings and can be saved at User, Project or Local scope. The last two are app preferences and are always saved for the user.

Timestamps and durations. When Claude supplies no timestamp, a live message shows the locally observed time marked (observed); resumed messages without a timestamp stay unstamped. With both settings On, the duration row also shows the completion time (Done). When the SDK reports no turn timing, a live response shows an Observed duration. Tool progress time is a lower bound, shown with ≥, and task time is labelled separately; neither is added to the turn total. Resumed responses show a duration only when the session history contains one.

Time format. Auto follows the system locale. 12-hour shows AM/PM and 24-hour UTC adds a Z suffix. A custom strftime pattern written into a settings file is used and preserved; the picker offers only the four presets. A timeZone entry in a settings file, such as Europe/Berlin, sets the zone for local presets and custom patterns. An unknown zone name falls back to the system zone.

Scrolling. Page Up pauses following and reads earlier output; Page Down reads later output. Ctrl+End jumps to the latest output and resumes following when Auto-scroll is On. With Auto-scroll Off it jumps once and then holds that position. The reading position survives new output and window resizing. The mouse wheel belongs to the terminal’s own scrollback unless the terminal forwards mouse events to the app.

Open /config → General → Footer with Enter or Space. The chat footer uses one row with independently ordered left- and right-aligned groups. Changes save automatically, and the running footer changes after each successful save. Layout and colors load before the first frame and remain available while connecting or authenticating. You can edit the footer when authentication is required, before an agent session exists. The field-position counter appears in the dialog’s top-right corner. The settings row shows Default layout until a layout is saved, then Custom layout.

KeyAction
Up, DownSelect a field.
SpaceToggle visibility, preserving the field’s side and position.
Left, RightSwitch between Left and Right; append the field to the destination group.
Ctrl+Up, Ctrl+DownMove the field within its group; selection follows it.
CExpand or collapse the inline color palette for an eligible field.
Ctrl+RRemove the saved layout and restore defaults.
EscClose after any pending changes finish saving.

You can keep editing while a save is in progress. Later edits are saved next, using the confirmed file revision. A failed save or conflict keeps your edits in the dialog and shows an error; Enter retries the save, and Esc discards the unsaved edits and closes. Session changes leave the active footer, editor draft, and local saves intact.

Model, effort, working directory, Git branch, and context remaining support optional colors. Press C to expand a palette directly below the selected field. Arrow keys move between color boxes; the selected color name appears underneath. Enter applies and autosaves the choice, while Esc or C collapses the palette without applying it. Choose Current (Home) to restore the field’s existing appearance. Permission mode, Fast mode, and Ultracode retain their fixed colors. Narrow windows show fewer boxes per row and keep the focused box visible.

Permission mode, model, effort, Ultracode, fast mode, running subagents, working directory, Git branch and context remaining are independent fields. Hiding the model does not hide effort or Ultracode; hiding the directory does not hide the branch. Fields appear only when their session data applies: effort requires a model that supports it, Ultracode requires verified effective state, running subagents requires at least one non-ambient subagent of the current session still running (one count per task across resumes, including stopping requests; see /agents), and branch requires a Git branch.

Permission and startup MCP-authentication notices remain at the far right and take priority over configured fields. On narrow terminals, paths and branches shorten first, then later fields are omitted, with the left group preceding the right group for overflow priority. The footer never wraps.

The layout is a user-level app preference saved as the presentation.footer array in the app-preferences file described under Where settings are saved. Each entry has an id, a visible boolean, a side of left or right, and an optional color; array order determines reading order within each group. The field IDs are permissionMode, model, effort, ultracode, fastMode, runningSubagents, directory, gitBranch and contextRemaining. Omitted fields remain available in the dialog but are hidden. An empty array hides all optional fields. Removing the setting restores the built-in layout.

For example, { "id": "model", "visible": true, "side": "left", "color": "cyan" } sets the model color. Omitting color keeps its existing appearance. The palette IDs are red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose, white, gray, and slate.

Notifications

Notifications alert only while the terminal reports that it is unfocused. A terminal without focus reporting stays silent. These General settings apply immediately:

SettingKeyChoicesBehavior
Notification methodpreferredNotifChannelAuto, iTerm2, Terminal bell, iTerm2 with bell, Kitty, Ghostty, Disabled. Default: AutoHow alerts are delivered. Disabled silences every category.
Notify when input is needednotifications.actionsRequiredOn / Off. Default: OnAlert for a waiting permission, question or dialog. A request that is already waiting does not alert twice.
Notify when Claude requests itnotifications.modelDirectedOn / Off. Default: OnAllow alerts that Claude sends through the PushNotification tool, when the account offers that tool.
Notify when a turn finishesnotifications.turnCompleteOn / Off. Default: OnAlert when an active turn completes. Cancelled turns, errors and resumed history do not alert.

Notification method is a Claude setting saved for the user. The three category toggles are app preferences. They do not change the mobile-push settings inputNeededNotifEnabled and agentPushNotifEnabled.

Auto uses the terminal’s own notification protocol on iTerm2, Ghostty and Kitty, and otherwise sends a desktop notification with a terminal bell. A terminal-specific method uses its protocol on that terminal and falls back to a desktop notification elsewhere. iTerm2 with bell adds the bell, and Terminal bell sends only the bell. Desktop notifications can be unavailable over SSH. Protocol references: iTerm2, Ghostty, and Kitty.

Two limits apply to every method:

  • Ordinary notices from Claude, including high-priority ones, appear in the transcript and do not raise an alert.
  • An alert is sent when its event happens or not at all. Resuming a session, regaining focus or changing a setting never delivers earlier alerts.

If Claude already delivered a requested alert on this machine, the app does not send a second one. A mobile push alone does not suppress the local alert.

To investigate a missing alert, see Notification diagnostics.

Automatic updates

Automatic updates is an app preference saved as updates.autoInstall. It defaults to Off.

ValueBehavior
OffA newer version opens the update window at startup, with manual installation choices.
OnThe window is skipped. A newer version is installed in the background after a normal exit, using the installation method of the running app (script or npm).

Update checks run in both modes and are cached for 24 hours. --no-update-check and CLAUDE_RUST_NO_UPDATE_CHECK disable checking and therefore automatic installation.

Automatic installation is skipped for source builds and unrecognized installations, after a forced shutdown, and after an application error. The setting is read again at exit, so switching it Off during a session cancels the pending installation.

The installation runs detached from the terminal and asks no questions. On exit the app prints one line naming the version and returns to the shell; closing the terminal does not stop the installation. Only one background installation runs at a time, and one that takes longer than 10 minutes is stopped.

Installer output is written to claude-rs-update.log in the parent of the runtime log directory, replacing the log of the previous installation. A failed installation is shown as a warning at the next start and retried after the next normal exit.

The setting updates only claude-rs. It does not update a separately installed Claude CLI.

How files are changed

  • A save changes only the key of the edited setting. Other keys, unknown keys and values the app does not understand are left as they are.
  • Reset removes the key and any parent object that becomes empty. It never writes a substitute default.
  • A missing settings file is created on the first save.
  • A file that contains invalid JSON, is not a JSON object, cannot be read, or is a symlink is blocked from editing. The app does not repair, replace or back up such a file.
  • Saving at Local scope inside a Git repository adds .claude/settings.local.json to the repository’s private .git/info/exclude when needed. A Local settings file that Git already tracks is rejected.
  • Only the edited setting is validated. An unrelated invalid value elsewhere in the file does not block the save, but it can still prevent Claude from loading the file; see Not loaded under Reading the list.
  • A change made to the same setting by another program is detected before writing. The app reloads and keeps your draft. An editor that writes at the same instant without honoring the app’s lock file can still overwrite a save.

Offline inspection

These read-only commands inspect redacted settings files without starting the TUI:

claude-rs config
claude-rs config show --which project-settings
claude-rs config export --output claude-rs-config.json

The output covers User, Project and Local settings and the preferences file. Malformed files are reported, not rewritten. The commands read the files as they are on disk: they do not combine scopes and do not include managed policy. See Config Inspection.

MCP

The MCP tab shows live session-backed MCP state. Use /mcp to inspect servers, refresh status, complete authorization, reconnect servers, and handle SDK-provided MCP prompts when available.

If no session is active, the tab asks you to open or resume a session first. If the active session reports no MCP servers, the tab shows an empty state rather than editing raw config files.

MCP input requests open a dialog over this tab. Supported forms edit strings, numbers, whole numbers, booleans, single choices, and arrays of string choices, including titled choices and defaults. Required fields and supported length, numeric range, choice-count and date/email/URI/date-time constraints are validated before Accept. false and 0 are answers. Optional fields start omitted unless the server supplies a default; Ctrl+O includes or omits the focused optional field, so an included empty string differs from omission. Unsupported schemas show a reason and allow Decline or Cancel without offering Accept.

Use Tab/Shift+Tab or Up/Down to move between fields and actions. Type or paste into text and numeric fields, use Left/Right for choices, and Space to toggle a boolean or the highlighted multi-choice option. Enter advances from a field or activates the selected action. Ctrl+Enter accepts when the terminal distinguishes it; navigating to Accept works in every terminal. Esc cancels. A validation or send error retains the draft for correction or retry.

Overlapping requests wait in arrival order; the dialog shows the waiting count. A new request does not replace the form being edited. Only the active URL request opens a browser. SDK cancellation removes its matching request, including one still queued. A submitted dialog stays pending until its SDK callback settles, and prevents duplicate submission. Drafts remain in memory for the active session and are discarded on settlement or session teardown; form answers are not written as settings or diagnostic fields.

Plugins

The Plugins tab is available through /plugins. It shows installed plugins, marketplace plugins, configured marketplaces, and Session attachments.

Supported actions include enabling, disabling, updating, uninstalling, and installing plugins into user, project, or local scopes when those actions are available for the selected plugin.

After plugin changes, the app requests a session runtime plugin reload when an active session is available.

In the Session list, choose Load local folder or press l outside search. Enter the plugin directory, using an absolute path or a path relative to the session’s working directory. The SDK loads it into the current session without installing it into a persistent scope or changing marketplaces. Confirmed folders show Source: Session, their folder, and the SDK’s source and version when supplied. Select an existing folder and press Enter to load it again after editing its files; r reloads the current inventory.

A reload that would invalidate the prompt cache opens an Apply/Decline confirmation. Until Apply, no requested folder is added. Apply submits the same folders; declining keeps the draft and the session’s existing plugins. A rejected request keeps the draft for retry. A reload can apply with component errors: the app shows the SDK’s error count and reconciles the confirmed plugins, commands, agents and MCP servers. A host reconciliation failure is reported separately and does not imply that the attachment was rolled back.

Confirmed attachments are retained when the bridge replaces or resumes the same active session, including rewind. They are not persisted by the host: after restarting the app or switching away and returning, load the folders again. A fresh session does not inherit them. Before the first prompt after a replacement, press r in Session to obtain a new SDK inventory if it is not yet listed. Managed policy, remote environments or an already-running sandbox can reject local folder loading; the SDK’s refusal is shown without a persistent-install fallback.

Diagnostics

Interactive TUI runs write a small local diagnostics baseline by default. The baseline records warnings and errors from the app, the bridge, and the SDK, plus minimal application lifecycle metadata, using a restricted field set. Detailed diagnostics (timings, routine activity, every protocol and SDK event) remain opt-in because verbose logs can grow quickly and may contain private context. claude-rs logs prints where the current log is; see Finding Logs.

Doctor

Run deterministic environment diagnostics:

claude-rs doctor

For machine-readable output:

claude-rs doctor --json

For CI or support scripts that should fail on hard runtime prerequisites:

claude-rs doctor --strict

Use -C, --dir with doctor to inspect project-local settings for a specific folder:

claude-rs -C path/to/project doctor

Config Inspection

Inspect resolved config paths without starting the TUI:

claude-rs config
claude-rs config path

claude-rs config prints the same path summary as config path, including user settings, project-local settings, user preferences, and whether each file is present and valid. Use -C, --dir to inspect project-local config for a specific folder.

For script-friendly path output:

claude-rs config path --which settings
claude-rs config path --which local-settings
claude-rs config path --which preferences

Show a concise redacted config summary:

claude-rs config show
claude-rs config show --json

Export a support-safe config snapshot:

claude-rs config export --output claude-rs-config.json

Config output redacts obvious credentials by default. Export refuses to overwrite existing files, and inspection does not repair, back up, normalize, or rewrite config files. Malformed existing config files are reported as invalid and cause show or export to return a non-zero exit code.

Logging

Expand the baseline with a named diagnostics preset:

claude-rs --enable-logs --diagnostics-preset session
claude-rs --enable-logs --diagnostics-preset render

Available presets:

PresetUse when
runtimeDebugging general app, bridge, session, tool, permission, network, and update flow.
sessionDebugging session startup, permission, and command flow.
renderDebugging rendering, cache, input, and paste behavior.
bridgeDebugging Agent SDK bridge lifecycle, protocol, SDK, permission, and MCP behavior.
fullCapturing the broadest diagnostic trace.

The render preset includes Read preview timings. read_preview_started records the source path, starting line, size, width and initialization time. read_preview_prepared reports cumulative parse_us, hidden_scope_us, visible_style_us, line counts and max_line_us across preparation polls. Parsing includes lazy regex compilation and scope-operation generation; visible styling includes rebuilding style state and constructing spans. These phase totals exclude source normalization, wrapping, scheduling delays and terminal drawing. syntax_highlight_slow_line reports the same phases for calls taking at least 50 ms, with visibility and a one-based line number within the returned source. Canceled preparations do not emit a completion summary.

Use an explicit log path when you want the file somewhere predictable:

claude-rs --enable-logs --diagnostics-preset bridge --log-file claude-rs.log

Use an explicit tracing filter for targeted debugging:

claude-rs --log-filter "info,app.render=trace,bridge.protocol=debug"

--log-filter overrides --diagnostics-preset. Every interactive run writes to a timestamped default diagnostics file when --log-file is omitted. With no logging options, the filter is warn,app.lifecycle=info and versioned claude-rs-baseline/v1 records keep stable event metadata (event name, message, outcome, error classification, duration, counts, logging policy) plus the failure detail needed to act on a warning or error: the error message or startup failure reason and, for bridge and SDK records, only a fixed set of failure fields (reason, hook name and event, exit code, output excerpt, plugin name and category). Text fields are redacted for common credential shapes (bearer, basic and token authorization values, API keys and tokens in name=value pairs, headers and query strings, and URL user information) and cut to a fixed length. Session, request and tool-call identifiers, working directories, project keys, commands, and conversation or file content are omitted from the baseline format. Redaction is pattern-based and best-effort. It also replaces your home directory with ~ in text, so /Users/alice/.claude/settings.json is logged as ~/.claude/settings.json; a path outside the home directory (/opt/tools/x, /tmp/build, another drive) is kept as written. A free-text error message, a hook output excerpt, and the preview of an unstructured line the bridge printed to stderr (a stack trace, for example) are kept as written once redacted, so they can still hold such paths, file names and fragments of command output. Review a log before sharing it.

Baseline logging is best-effort: if the default log cannot be initialized, the app continues without disrupting the TUI. Explicitly requested detailed logging still reports initialization failures as startup errors.

The default diagnostics directory is under the platform local data directory:

  • Windows: %LOCALAPPDATA%\claude-code-rust\logs\runtime\
  • Linux: usually $XDG_DATA_HOME/claude-code-rust/logs/runtime/ or ~/.local/share/claude-code-rust/logs/runtime/
  • macOS: the platform data directory reported by the dirs crate, under claude-code-rust/logs/runtime/

Default runtime log files include the UTC start timestamp, process id, and a short run id, for example:

claude-rs-20260614T075924Z-p12345-r8f3a2c1.log

Logs rotate at 10 MB and keep up to five rotated files per run. Default runtime logs are retained up to 256 MB, 30 days, or 100 managed files, while always preserving at least 10 newest files. Retention only applies to app-managed timestamped files in the default runtime log directory; explicit --log-file paths are never cleaned up by the app.

--log-append appends to an explicit --log-file. When used without --log-file, it appends to the legacy shared default file claude-rs.log for compatibility; prefer the normal timestamped defaults for new diagnostics.

Finding Logs

Use the logs command to find diagnostics paths without starting the TUI:

claude-rs logs
claude-rs logs --path
claude-rs logs --latest

claude-rs logs prints the runtime log directory, legacy log path, latest discovered log, and common follow-up commands. --path prints only the default runtime log directory for scripts. --latest prints only the latest runtime log path, falling back to the legacy shared log when no timestamped runtime log exists.

To inspect recent log output safely:

claude-rs logs --tail 200

Tail output is redacted for obvious credentials such as API keys, bearer tokens, OAuth tokens, passwords, and authorization headers before it is printed.

Debug Bundles

Create a redacted support bundle with:

claude-rs logs --bundle --yes

Without --yes, an interactive terminal is prompted before the bundle is written. Use --output <PATH> to choose the ZIP path.

The manifest uses schema claude-rs-debug-bundle/v2. Diagnostics paths describe the runtime log directory and legacy log path.

The bundle includes:

  • manifest.json
  • doctor.json, equivalent to claude-rs doctor --json
  • selected recent runtime logs
  • the legacy log if present
  • bridge diagnostics extracted from structured log records
  • last-crash.json when the previous run crashed
  • diagnostics paths

The bundle excludes full config files, Claude credentials, environment dumps, and arbitrary project files. Redaction removes obvious credentials, and baseline logs omit common sensitive diagnostic fields. Detailed logs can still contain private conversation text, local file paths, command output, session identifiers, or project-specific context. Review a bundle before sharing it publicly.

Failure Reports

Top-level failures print a short issue-friendly report to stderr with a category, exit code, version, platform, latest discovered log path, and one next-step command. Bridge failures are categorized as spawn, initialization, stdout close, SDK/protocol failure, or timeout so support output points at the likely failing boundary.

Unexpected Rust panics install a local panic hook. The hook writes a redacted last-crash.json file in the diagnostics root and prints the same safe-to-paste metadata to stderr. No crash report is uploaded automatically.

Bridge Diagnostics

The bridge always writes its warnings and errors to stderr, and the app records them in the baseline log. Only the failure fields listed above are kept from each record; any other field the bridge sends, such as a working directory or a transcript key, is dropped. This includes SDK warnings and errors, and a hook that fails (its event, name, exit code, and the start of its stderr). A hook that exits with code 2 on an event where that is its decision (it blocks the action, keeps Claude working, or hands its output to Claude) is recorded only in the detailed log; on an event where Claude Code only shows the output to the user or ignores the exit code, such as SessionStart or Notification, or fails the operation on any non-zero exit, as WorktreeCreate does, and on an event the reference does not list, it is a failure like any other exit code. The hook reference lists what exit code 2 does on each event. An ordinary user cancellation is not a warning either and is recorded only in the detailed log. A bridge process that prints something that is not a structured record is logged as an unstructured line with a bounded preview. A command the bridge cannot decode is logged with its size and a content-free error; the start of the text is kept only in detailed logs.

When detailed diagnostics are requested through --enable-logs, a preset, --log-file, --log-filter, --log-append, or RUST_LOG, the bridge also writes its info, debug, and trace records, with their full fields, into the structured log. That is where timings, hook start and progress, and other routine activity appear.

The bridge script can be overridden with:

claude-rs --bridge-script /path/to/agent-sdk/dist/bridge.js

or:

CLAUDE_RS_AGENT_BRIDGE=/path/to/agent-sdk/dist/bridge.js

Debug builds can override the bridge runtime with:

CLAUDE_RS_AGENT_BRIDGE_RUNTIME=/path/to/bun

Release npm installs use the root package launcher to start the native platform binary and point it at the bundled bridge script. The native binary resolves the private claude-rs-bridge-bun executable from the installed platform package. In doctor --json, the runtime checks are reported as bridge_runtime, bridge_runtime_version, and bridge_script.

Notification Diagnostics

To investigate a missing or unexpected alert, run with a preset that includes notification records, or add the target to a custom filter:

claude-rs --enable-logs --diagnostics-preset session
claude-rs --log-filter "info,app.notify=debug"

The runtime, session and full presets include app.notify. Its records show the observed terminal focus, the origin and delivery report supplied by the SDK, duplicate and replay handling, the category and method decision, and the outcome of the terminal or desktop transport. Question and notification text are omitted.

A successful terminal write or an accepted OS request confirms that the alert was handed to the transport. It does not prove that the terminal or operating system displayed or sounded it. See Notifications for the delivery rules.

Useful Issue Reports

Include:

  • claude-rs --version
  • OS and terminal.
  • Install method: npm package, source build, fork build, or manual binary.
  • The exact command used to launch the app.
  • Whether a custom bridge script or debug bridge runtime override was used.
  • A short reproduction.
  • A claude-rs logs --bundle --yes bundle or relevant redacted log snippets, not full secrets or private conversation content.

Troubleshooting

Start with claude-rs doctor. It runs installation, runtime, config path, log path, npm metadata, and credential checks, and it names the failing boundary for most of the problems below.

claude-rs doctor
claude-rs doctor --json

When you need the underlying detail, enable diagnostics and read the log. See Diagnostics for presets, log locations, and debug bundles.

claude-rs logs
claude-rs logs --tail 200

The App Will Not Start Or The Bridge Will Not Spawn

The TUI depends on the Agent SDK bridge, which runs as a child process under a private Bun runtime. If the bridge cannot start, the app reports the failing boundary as spawn, initialization, stdout close, SDK or protocol failure, or timeout.

Check what the app actually resolved:

claude-rs doctor --json

The bridge_runtime, bridge_runtime_version, and bridge_script checks show which runtime and bridge script the binary picked. A missing or unexpected path there is the usual cause: a source build without the bridge built, a partially extracted install, or a stale CLAUDE_RS_AGENT_BRIDGE override left in the environment.

For a source build, the bridge has to be built before the app can spawn it. See Development.

To capture the bridge’s own startup output, run with bridge logging enabled and inspect the log:

claude-rs --enable-logs --diagnostics-preset bridge
claude-rs logs --latest

Login And Authentication Failures

If startup reports that required organization configuration is temporarily unavailable, check connectivity and retry. If access to organization configuration was refused, sign in with an allowed account or contact your organization administrator.

Authentication is owned by the Claude Code CLI, not by this project. claude-rs reuses the credentials the CLI already holds.

Sign in from inside the app with /login, or from a shell:

claude auth login

If login appears to succeed but sessions still fail, confirm that the CLI itself works, then re-check the credential state:

claude-rs doctor

Billing, model availability, and service limits are controlled by Anthropic and surface here as session errors rather than install problems.

Extra usage being enabled and extra usage being available are separate conditions. A warning offers continued use only when the SDK confirms both; an unavailable allowance is not a promise that work will continue. A refresh failure reported as an invalid request, such as a full disk, remains a request failure and does not trigger login from its error text.

For the authentication and permission flow in the log, use the session preset:

claude-rs --enable-logs --diagnostics-preset session

The Wrong claude-rs Runs

The script install and the npm install use different layouts, and neither owns the other’s files. If both are present, PATH order decides which one runs, so an update can appear to do nothing.

Multiple script installations can also coexist after installing into a custom directory. The installer shows the current and other locations, then offers y Yes / N No cleanup for recognized copies after the new installation passes verification. Check the named directory before confirming; a temporary test installation may be offering to remove your normal copy. Unknown copies receive manual guidance instead.

List every claude-rs that is visible on macOS/Linux:

command -v claude-rs
which -a claude-rs

On Windows:

Get-Command claude-rs -All

Compare the resolved path with the install layout reported by:

claude-rs --version
claude-rs doctor

If the wrong one wins, remove the install you do not want, or reorder PATH so the one you want comes first. See Switching Install Methods and Uninstall.

Troubleshooting npm Installs

If npm omitted optional dependencies, the launcher cannot find the native platform package. Check your npm config and reinstall:

npm config get omit
npm install -g claude-code-rust

If the resolver reports a missing platform package, npm optional dependencies were likely omitted. Check npm config get omit and reinstall without --omit=optional.

Linux npm packages currently require glibc. On musl-based distributions, build from source until a matching npm package is available.

If claude-rs resolves to an older global shim, ensure your npm global bin directory comes first on PATH or remove the stale shim before retrying.

Reporting A Problem

For install failures, see Reporting Install Problems. For anything else, see Useful Issue Reports and attach a redacted bundle:

claude-rs logs --bundle --yes

Help

Claude Code Rust has two built-in help paths:

/help
/docs <topic>

/help opens the fullscreen Help tab. Use it when you want navigable in-app help without adding a message to the chat transcript.

/docs renders live help into the chat. Use it when you want the current commands, shortcuts, modes, models, or subagents copied into the conversation as reference material.

Fullscreen Help

The fullscreen Help tab has three sections:

SectionShows
ShortcutsKeyboard shortcuts for the current app state and focused UI context.
CommandsApp-owned slash commands plus slash commands advertised by the active SDK session.
SubagentsSubagents advertised by the active SDK session, including model labels when provided.

Use Left and Right to switch Help sections. Use Up and Down to move through the visible rows in the active section.

The Shortcuts section is state-sensitive. It changes depending on whether focus is in chat input, autocomplete, an inline permission prompt, an inline question, or a blocked state such as connecting or command-pending.

The Commands and Subagents sections are also session-sensitive. While the app is connecting, they show loading rows. If the active session does not advertise SDK commands or subagents, the Help tab shows an empty-state row instead of inventing unavailable entries.

In-Chat Docs

CommandShows
/docs modeCurrent and available session modes.
/docs modelsModels advertised by the active session.
/docs shortcutsKeyboard shortcuts for the current app state.
/docs commandsApp-owned and SDK-advertised slash commands.
/docs agentsSubagents advertised by the active session.

/docs covers two topics that are not sections in the fullscreen Help tab: mode and models. Those topics are based on the active session’s advertised modes and models.

The /docs output is based on the running app state. It can differ from this manual when the active session advertises different models, modes, commands, or agents.

Development

This page covers building and running Claude Code Rust from source. For CI checks, coding standards, and how to open a pull request, see CONTRIBUTING.md.

Build From Source

Use this path when developing the project or testing a fork without installing a global claude-rs command:

Source development requires Rust 1.88.0 or newer, Node.js 24 with npm, and Bun. These are developer toolchain requirements, not requirements for script-installed users.

Rust dependencies also require a C/C++ build toolchain: Visual Studio Build Tools with the C++ workload and Windows SDK on Windows, Xcode Command Line Tools on macOS, or GCC/Clang with the platform development headers on Linux. Syntect uses Oniguruma, whose bundled C sources are compiled and statically linked by onig_sys by default; no separate Oniguruma runtime installation is needed.

git clone https://github.com/srothgan/claude-code-rust.git
cd claude-code-rust
npm ci --prefix agent-sdk
npm run build --prefix agent-sdk
cargo run

Maintainer and source-build npm tooling targets Node.js 24. Packaged installs use the bundled private Bun runtime for the Agent SDK bridge.

Debug builds resolve agent-sdk/dist/bridge.js from the checkout after the bridge is built. They use bun from PATH unless CLAUDE_RS_AGENT_BRIDGE_RUNTIME points at a specific Bun executable.

For a release-mode source binary, build the bridge and binary, then provide both an explicit bridge script and a Bun runtime using the bundled-runtime filename. Release-mode source binaries do not use the debug PATH fallback for Bun.

npm ci --prefix agent-sdk
npm run build --prefix agent-sdk
cargo build --release --locked --bin claude-rs
cp "$(command -v bun)" ./target/release/claude-rs-bridge-bun
./target/release/claude-rs --bridge-script ./agent-sdk/dist/bridge.js

On Windows, copy bun.exe next to the binary as claude-rs-bridge-bun.exe, then run:

Copy-Item (Get-Command bun).Source .\target\release\claude-rs-bridge-bun.exe
.\target\release\claude-rs.exe --bridge-script .\agent-sdk\dist\bridge.js

Do not use cargo install --path . if you want to test the npm install shape. cargo install writes only the Rust binary to Cargo’s bin directory and does not install the bundled Agent SDK bridge, private Bun runtime, or platform package layout.

Manual Bridge Overrides

If you need to run a manually built binary outside the npm package layout, pass the bridge explicitly:

claude-rs --bridge-script /path/to/claude-code-rust/agent-sdk/dist/bridge.js

You can also set:

CLAUDE_RS_AGENT_BRIDGE=/path/to/agent-sdk/dist/bridge.js

Debug builds can use a local runtime override while developing the bridge:

CLAUDE_RS_AGENT_BRIDGE_RUNTIME=/path/to/bun

Release npm installs ignore runtime overrides and use the bundled claude-rs-bridge-bun executable from the platform package.

Architecture

Claude Code Rust is split into a native Rust terminal app and a TypeScript Agent SDK bridge.

Runtime Shape

The Rust binary owns the terminal UI and process lifecycle. It parses CLI options with Clap, starts a Tokio runtime, and runs the app inside a LocalSet because parts of the terminal and child-process runtime are not Send.

The app then starts or resumes a bridge session and renders the chat view directly in the terminal.

Interactive startup arguments resolve into one launch intent: a new session, a specified resume ID, the session picker, or the latest session in the working directory. Session overrides are applied through the existing launch-settings boundary and released after the initial session is selected. Launch configuration (--add-dir, --settings, --mcp-config, --strict-mcp-config and the system prompt flags) travels through the same boundary but is kept for every session the process starts. Rust resolves paths against the working directory, reads files and checks that JSON parses before logging, the bridge or the terminal start, so a bad flag stops the launch with nothing renamed or written. The bridge is the only place that turns the result into SDK options: it lays host restrictions over the --settings flag layer, merges MCP configs in command-line order, names a new or forked session through the SDK title option and a resumed one through renameSession(), and keeps its runtime guard prompt in every system prompt. Initial prompts use normal prompt queue admission once startup dialogs are complete.

Support commands run before bridge resolution. Shell completions and manual pages are generated from the same Clap command definitions as CLI help, so neither requires the bridge or authentication.

MCP elicitation ownership

The SDK onElicitation callback registers one resolver per original control request ID in the bridge. Public requestedSchema.properties key order is captured before JSON reaches Rust’s sorted maps; the private SDK property_order hint is not part of this contract. The bridge emits elicitation_settled with the original session and callback request ID on response, SDK abort, matching URL completion or teardown. URL completion matches both MCP server and elicitation ID. Teardown settlements carry the bridge session’s closing state so Rust drops the entire queue without promoting a queued URL. Outbound transport admission is not callback settlement.

Rust’s session-scoped ElicitationQueue owns each request, parsed schema, answers, omission flags, focus, errors and pending-send state. The Config overlay is only a marker projecting its active entry; schema support and typed validation belong to the form model, not the renderer or settings persistence. Requests activate FIFO and only active URL requests open a browser. Settlement removes the matching draft and retains only its ID to suppress redelivery; session reset clears the store. Correlated transport errors retain drafts for retry, and session fencing rejects old events. Neither bridge diagnostics nor Rust interaction diagnostics record answers.

Rust Terminal App

Important Rust areas:

AreaResponsibility
src/main.rsProcess entrypoint, runtime setup, logging setup, and exit behavior.
src/lib.rsCLI arguments, subcommands, and diagnostics presets.
src/agent/Bridge process resolution, NDJSON client, wire types, and bridge error handling.
src/app/App state, lifecycle, sessions, config, permissions, input, slash commands, plugins, MCP, usage, and trust.
src/ui/Ratatui rendering for messages, markdown, diffs, tool calls, config tabs, help, autocomplete, and input.

The current runtime uses inline terminal-owned rendering rather than an older fullscreen-only model. Fullscreen views are still used for config, help, status, usage, MCP, plugin and subagent surfaces. The reasons for that change are described in I rebuilt Claude Code’s terminal UI in Rust. Then I deleted 12,000 lines of it.

Syntax highlighting uses Syntect with the Oniguruma backend and the matching two-face syntax bundle. SourceHighlighter owns parser and scope state for one traversal. Collapsed Read previews parse every returned source line to preserve context through the hidden middle, but resolve theme styles and construct spans only for visible lines. Each Read result starts its own traversal; a file line number does not reconstruct syntax context preceding that result. Parsing remains synchronous, and layout cancellation is checked between source lines.

Agent SDK Bridge

In packaged npm installs, the Rust process resolves a private Bun runtime named claude-rs-bridge-bun or claude-rs-bridge-bun.exe from the installed package layout. That runtime runs:

agent-sdk/dist/bridge.js

The TypeScript bridge wraps @anthropic-ai/claude-agent-sdk. Rust and TypeScript communicate over stdin/stdout using newline-delimited JSON command and event envelopes.

The SDK owns subprocess option serialization. The bridge forwards its argument array unchanged to the child process; named --flag=value arguments and separately serialized settings JSON retain their original boundaries. Assistant text projection preserves text and Markdown links across streaming, completed-only replies and saved history. Structured citation objects supplied by the SDK are not transported to Rust or rendered as source references.

Rust sends commands such as session creation, session resume, prompt submission, permission responses, MCP actions, and runtime refresh requests. The bridge sends events such as assistant messages, tool updates, permission requests, question requests, available commands, modes, models, usage, and errors.

Subsystems

Each subsection names the owner of a concern and the invariants that keep the Rust side and the bridge from holding two versions of the same state.

Settings and trust

ConcernOwnerLocation
Setting catalog: IDs, labels, kinds, choices, writable scopes, panes, editor schemasBridgeagent-sdk/src/bridge/settings_catalog.ts, settings_layout.ts
Saved-value resolution across scopesAgent SDKpublic resolveSettings()
Mutation validation and targeted JSON writesBridgeagent-sdk/src/bridge/settings_service.ts
Config window, edit drafts, acknowledgement trackingRustsrc/app/config/, src/ui/config/
Workspace trust state and storeRustsrc/app/trust/
App preferences file and updater stateRustsrc/app/settings.rs

Rust receives catalog descriptors and sanitized snapshots over NDJSON and renders them. It does not merge settings files, mirror scope rules, or supply defaults for unset values. Saved defaults stay separate from active session choices: a settings save never becomes a session flag override. Snapshots and pending drafts are invalidated when the session scope changes. Offline claude-rs config inspection is a separate read-only view of the physical files and does not resolve the cascade.

The snapshot is the SDK’s raw file cascade. The running session additionally applies trust, managed policy, capability restrictions and explicit session choices, so an observed session value can differ from the saved one. SDK provenance is reported per top-level key, which does not prove that a particular leaf is enforced policy. resolveSettings() does not execute policyHelper.

The write path has one implementation for every setting, including the app-owned presentation.*, notifications.* and updates.* leaves:

  1. The bridge validates the value and the target scope against the catalog immediately before saving. Only the edited leaf is validated through the SDK’s resolver, so unknown keys, newer settings and unrelated invalid values survive.
  2. The current file is read and only the target key is patched. Reset removes the key and empty ancestor objects.
  3. A revision of the displayed target detects conflicting edits. Unrelated external edits are incorporated into the fresh document; a conflict refreshes the snapshot and keeps the editor draft.
  4. The write takes a cooperative lock, rechecks the file bytes, and replaces the file atomically. An external editor that ignores the lock can still race between the final recheck and the replacement; this is not a filesystem compare-and-swap.
  5. The acknowledgement is correlated with its originating mutation, so a delayed result cannot close a different editor. A pending save keeps the last acknowledged value visible.

Structured editors and their advanced JSON view share this one mutation and persistence path. Inspection and validation never execute hooks or credential helpers and never resolve secret files or environment variables.

Default effort targets modelSettings.<canonical model>.effortLevel. SDK model metadata selects the target: aliases and dated, context and provider spellings are normalized to the canonical key, and unknown model identities stay read-only. Mutation context checks stop an outdated edit from targeting a different model after Default model changes.

Workspace trust never uses the config snapshot as authority. Trust acceptance reads the current preferences document and preserves unrelated authentication and MCP data. Shared atomic file replacement is an I/O mechanism, not a domain resolver.

Automatic updates uses the same catalog and writer for the User-only updates.autoInstall leaf, and the Rust updater owns its application. Startup prompt selection skips the manual window when the preference is enabled, background check results return through the app event queue, and a normal post-TUI exit reads fresh saved consent and cached release metadata before selecting the installer. An install chosen in the update window runs in the terminal. An automatic install is handed to a detached run of the same executable through the hidden update-worker subcommand, which holds an OS file lock, sends installer output to its own log, stops the installer process tree at a time limit, and saves the outcome against the settings file because it has no session. The next start reads that outcome and shows a failure once the launch transcript is settled. Updater metadata saves omit the editable preference and preserve it, along with the presentation and notification namespaces, under the shared document lock. Checking is independent of installation.

Presentation and timing

Tool titles share a one-line display projection and a source-keyed inline cache in the existing block cache. Shell command titles render literally; other tool titles retain Markdown styling. Full titles and command inputs remain canonical data. Spinner/status chrome, metadata badges and width clipping stay live, while unchanged title content survives body updates and resize. Inline cache bytes participate in the existing render budget and eviction workflow.

ConcernOwnerLocation
Normalizing SDK wall timestamps, result elapsed and API timing, tool and task elapsed metadataBridgeagent-sdk/src/bridge/presentation_metadata.ts
Each message’s clock and timing provenance, stored on the canonical transcript messageRustsrc/app/presentation.rs
One formatter for locale, clock presets, custom patterns and timezoneRustsrc/app/presentation.rs

Presentation preferences are projections of the acknowledged config snapshot; Rust keeps no second presentation store. History replay removes locally observed times and preserves native timestamps without reordering messages. Completed duration rows go through the same scrollback boundary and commit protocol as other transcript rows.

Transcript rendering

The canonical transcript owns message and tool content. The chat session traverses it through a resumable row producer, with cursors for assistant sections, Markdown lists and code lines, and file-preview syntax state. Text rendering avoids generating an extra physical-row copy solely to measure height. Capped tool bodies lay out the visible prefix and tail without wrapping hidden middle lines when the source-line count already proves overflow.

Resize replay

Replay inserts ready rows before preparing more source. Tools can emit their title before their body is ready, and completed sections can be inserted before the rest of an assistant turn is laid out. Text production and terminal insertion use the same viewport-derived row target, while preparation also yields on a cooperative time budget. One replay stays open until both source traversal and insertion finish; an empty output queue alone does not confirm completion. No historical width layouts are retained.

Pending replay work is independent of the repaint flag. Preparation can continue without redrawing unchanged content, while input and other visible changes still request a repaint. The terminal reserves insertion space only when history rows are queued; an empty preparation slice leaves the viewport geometry intact. When replay stops at mutable content, completion schedules a render of the full live suffix from canonical state. Shutdown waits for pending preparation and insertion even when no repaint is requested.

Layout cancellation checkpoints observe terminal size independently of queued input events, including during Markdown parsing, source grouping, highlighting and physical-row conversion. A changed size discards the attempt and restarts through the resize owner. Transcript topology changes, changes to a tool being prepared, and reading-policy changes also discard an active replay; ordinary appended messages can be consumed by the existing traversal. Cancellation is cooperative: an individual parser or syntax-library call can exceed the scheduling budget before the next checkpoint.

inline_chat_layout_step records preparation duration and row count; inline_chat_draw_interrupted_by_resize uses phase layout when cancellation happens before terminal insertion.

Shutdown redraws the live viewport without resetting committed history. Reading returns to live output so its viewport copy does not remain beside native scrollback. The terminal owner finishes pending resize recovery and transcript replay before restoration; an explicit force interrupt can stop that recovery.

Transcript reading

Chat reading owns a stable transcript-segment anchor and a rendered-text position; the saved Auto-scroll setting controls only the following policy. Reading chooses the visible source window independently of scrollback restoration, survives reflow of retained content, and returns to following new output through an explicit keymap action.

While reading, the current replay accumulates the rows needed to resolve the saved text anchor and preserves that anchor until traversal finishes. These temporary rows belong to the active replay and are released with it.

/copy

/copy derives its material from the canonical response text and the text-joining rule shared with rendering, then writes through the clipboard boundary shared with MCP authorization. Its picker owns only the current selection and retry state.

Turn activity and thinking

ConcernOwnerLocation
Interpreting the live main-agent activity phase from SDK stream eventsBridgeagent-sdk/src/bridge/activity.ts
Presentation decision from the typed agent_activity_update phase, turn liveness, pending interactions, compaction and cancellationRustsrc/app/activity.rs

Only top-level message_start and indexed thinking or redacted_thinking block boundaries select the thinking phase, including blocks with empty or omitted text. A matching block stop, response stop or completion, retry or fallback, result or error, conversation replacement and session close reset it. SDK stream wrapper UUIDs identify individual frames; the API response ID scopes the ordered block stream and correlates completed assistant messages. A per-block assistant frame with a null stop reason keeps that scope open, and only a terminal, aborted or error frame closes its response. Stops carry no response ID and follow the SDK’s ordered response boundaries. The same correlation decides where reply text comes from: a streamed response is shown from its deltas, and a completed top-level message whose response never streamed, such as a local command’s reply, is shown from that message once; error messages report through the turn result. Subagent frames and completed history never start main-agent thinking. system/thinking_tokens estimates stay diagnostics, because they carry neither a response or block identity nor a matching stop.

Rust consumes the typed phases without interpreting SDK content and never infers thinking from text, tools or silence. One derived decision assigns the activity heading to the active assistant, or to the composer for standalone work without an assistant message. SDK thinking appears separately in the active assistant output as a temporary live row that is never committed to history. Waiting or completing without output removes the temporary heading and activity; real assistant output keeps its heading. Composer-only headings and the composer activity block never enter transcript or history output.

A turn keeps one verb and one shuffled traversal of the shared welcome tips, advanced by monotonic deadlines on the TUI wake loop, including under reduced motion. spinnerTipsEnabled from the acknowledged snapshot controls only the tip text; activity, its heading and SDK thinking are independent of it.

Background tool execution

The bridge normalizes confirmed launch results and SDK task lifecycle events into the existing Detached tool status. Requested background flags and host elapsed time do not confirm a handoff. Task-to-tool correlation survives foreground turn completion and resume; stale progress and repeated launch acknowledgements cannot reopen terminal execution. Live and replay use the same task adapters and transition rules.

Rust keeps execution state on the original ToolCallInfo. Its history projection freezes the launch at its creation position with the fixed ↗ icon, allowing the transcript prefix to enter terminal history while the task runs independently. Actual completion, failure or stopping appends one separately identified result linked to that tool. The session owns pending interactions; foreground turn reset preserves background controls, which remain mutable at the end of the live region during transcript replay after resize. Cache and retention accounting include the frozen projections without adding them to the execution index or foreground activity set.

A task row’s lifecycle is separate from its launching tool execution. task_id is the store key; message agent_id identifies that producing task, parent_task_id records task ancestry, and parent_tool_use_id retains tool nesting. Child-produced assistant/user messages resolve through the task’s launch association without changing main-thread reply, error or activity state. A nested Agent invocation belongs to its producer until the new child’s own lifecycle identifies it.

The bridge’s admitTaskRun decision is shared by live lifecycle edges, background inventory and replay. SDK run_id values order by plain string comparison within a task. Older runs are rejected before changing links, rows, tool output, timing or notifications. A newer run resets outcome, error, summary, timing and retry state even when first observed completed; it takes a new launch association only when one exists. source_tool_call_run_id records which run established that invocation, so a preserved historical launch can attribute producer messages without admitting unversioned old-run observations or reusing its model as current. The first identified run enriches an unversioned launch unless an explicit restart or different invocation establishes a new execution. Missing run IDs cannot replace identified state without matching invocation evidence. Same-run progress, starts and listings cannot reopen a recorded outcome; inferred interruption remains revivable. Individual terminal tool executions remain protected when their task resumes, and previous launch/result cards stay historical.

Lifecycle-owned rows survive background snapshots. Snapshot-only rows disappear when absent; their last run is retained as a session-scoped tombstone consulted only while the row is absent. Stale listed entries retain the current row and cannot make its newer execution appear missing. An empty snapshot has no run provenance and retains process-local interruption semantics: vanished running background work becomes interrupted without claiming an outcome. Saved running tasks likewise become interrupted on replay. A TaskList snapshot replaces plan tasks while retaining runtime rows. Saved task notifications preserve origin.runId and use the same run admission and launch metadata as live events.

The bridge composes tool task metadata before publication, including retry removal. Omitted task_metadata means no update; a present object is the complete replacement, including intentional absence of old fields. Rust replaces this projection without reinterpreting retry clears or merging fields. Restoring already-composed replay updates uses the same replacement contract.

Subagents view

ConcernOwnerLocation
Live subagent status, from the SDK task lifecycleBridgeagent-sdk/src/bridge/tasks.ts
Saved agent discovery and task restoration, at every nesting depthBridge, using SDK session historyagent-sdk/src/bridge/saved_subagents.ts
Saved transcript ids and messages, stop requestsAgent SDK, called by the bridgelistSubagents(), getSubagentMessages(), Query.stopTask() in agent-sdk/src/bridge/subagents.ts
/agents selection, transcript view, sent stop requests, footer countRustsrc/app/agents.rs, src/ui/agents.rs

The view projects non-ambient local_agent tasks from the existing inventory, one row per task in lifecycle order. Selection stays attached to task identity. Known parents, including finished parents, contribute subject/type to the subtitle and details; unknown parents do not hide children. Details show the current run when supplied. Shared model-source selection serves inline Agent cards and /agents: invocation-scoped observed resolved_model/models_used, inherited semantics for forks, requested model, then agent-definition default. Observed metadata from an earlier run is excluded from a newer run’s presentation. The footer counts current running task rows, including stop requests awaiting a lifecycle outcome.

Opening or refreshing /agents uses listSubagents(session_id) to discover saved agents at every depth and restore missing rows into the same task inventory. SDK getSubagentMessages() supplies the original launching tool and parent_agent_id; saved invocation records supply titles, types and foreground completion evidence, while native task notifications retain their run identities and outcomes. Missing outcomes are interrupted, not inferred from a saved reply or handback. Existing live state and recorded outcomes are preserved; inferred interruptions can take later saved evidence, and missing ancestry can be filled. Discovery emits only task updates and never inserts child text or tool cards into main chat. Main transcript replay remains separate and continues importing with includeSubagents: false. Unreadable metadata does not hide other listed agents, and a refresh can recover incomplete rows.

listSubagents() also owns saved-transcript availability. Reader requests capture session, task, accepted run and request identity. Late answers release only their own pending lane and cannot overwrite another run’s content or error. Run changes reconcile through task updates while the reader is open or the view is closed; they invalidate the saved-response preview even across consecutive completed runs. An open older transcript and its scroll remain a labeled saved snapshot until explicit refresh. The SDK returns the whole conversation without a run selector: Saved response is a persistence preview, not proof that the current run’s final report has been saved. The lifecycle owns the current outcome. Automatic response reads share one pending lane; failures are retried by r. The shared history classifier preserves handback reports, reminders, literal authored tags, compaction history and replay notification suppression.

Each stop operation captures task, optional intended run and request ID through the command, bridge response envelope and Rust client event. Immediately before native dispatch the bridge requires the task’s current run to match, including absence of a run ID, and requires a running local agent. A mismatch makes no SDK call. Identity is captured before awaiting the response, and only the matching pending operation may apply its acknowledgement or error. Run changes and terminal outcomes clear that run’s stopping state. Successful acknowledgement does not establish a stopped outcome. Stops remain in the scheduler’s unblocking lane. The public API is still stopTask(task_id) and cannot atomically target a particular run after dispatch.

The bridge announces each live top-level SDK response through the typed agent_response_started update before sending its text. A response triggered by a background completion receives a fresh mutable assistant owner even when no user prompt is pending; history replay does not activate live responses. The renderer groups consecutive visible assistant messages under one speaker label, carrying speaker context across content already inserted into terminal history. Streaming ownership, message identities and tool insertion order remain separate from that visual grouping.

Session title

ConcernOwnerLocation
Reporting and changing a session’s titleAgent SDKpublic getSessionInfo(), renameSession()
Reading the active session’s title and sending session_title_updateBridgeagent-sdk/src/bridge/session_title.ts
Holding the active session’s title for the Status tab, its rename draft and title generationRustsrc/app/state/session_runtime.rs
Listing snapshot of all sessions, including each custom_titleBridge, held by Rustagent-sdk/src/bridge/events.ts, recent_sessions
Whether the active session is saved, which renameSession() requiresRustsrc/claude_paths.rs, src/app/config/status.rs

The bridge reads getSessionInfo().customTitle after a connect, a replacement, a conversation reset, each top-level turn and each rename or title generation it performs, and sends every title it reads; a read that a later one overtakes is dropped. Rust keeps the active title as one value, strips control characters once in the converter, stores a repeated title idempotently, and clears it when the session id changes or the conversation resets. Neither side derives a title of its own. The session listing is a separate snapshot of all sessions, refreshed by listSessions() on connect, replacement and the Status-tab rename and generate actions; the Status tab falls back to it only while the active session has no title. customTitle falls back to a generated title, so an unnamed session shows that title after its first turn.

renameSession() appends to the session’s saved transcript and fails before Claude Code has written one, so the Status rename dialog confirms only once <session id>.jsonl exists as a non-empty regular file (the SDK skips an empty one). Rust looks where the SDK’s lookup does: under the configuration directory’s projects/, in the folder named from the resolved working directory with every non-alphanumeric UTF-16 unit replaced by - (or a valid CLAUDE_CODE_PROJECT_DIR_NAME with CLAUDE_CONFIG_DIR), and also in the folder of the directory the session is listed under when that differs, as for a session resumed from a sibling worktree. For a name longer than 200 characters Rust accepts any folder with the shortened prefix, a superset of the folders the SDK accepts; a transcript in a folder the SDK rejects surfaces as the SDK’s rename error. The check runs only at its refresh points, never per frame. ClaudePaths owns the folder name; the Status tab’s memory row builds its folder with the same encoder. A missing path is “not saved”; any other I/O error is reported as a failed check, unless another candidate folder has the transcript.

Notifications

ConcernOwnerLocation
Focus suppression, category enablement, terminal capability detection, transport selection, SDK delivery identities, external delivery boundaryRustsrc/app/notify.rs
Projecting native notices and verified proactive tool results into notification originsBridgeagent-sdk/src/bridge/notifications.ts
Shared wire and runtime payloadRustsrc/agent/notifications.rs
Session provenance validation and presentation of native noticesRustsrc/app/events/notifications.rs

Delivery waits for the first acknowledged settings snapshot, so startup cannot send using guessed preferences. Saved categories are read from that snapshot; there is no mirrored notification configuration struct. Local interaction handlers notify only after accepting a real waiting request, and pending-interaction ownership rejects duplicates. Turn completion sends only for an active, non-cancelled turn and skips SDK abortion reasons.

In the bridge, native key, UUID, session, original priority, color and timeout stay structured metadata. Proactive intent requires the actual PushNotification tool with status: proactive input, followed by a successful result without non-execution metadata. Delivery-report discovery is shared with tool rendering in tooling.ts; strings displayed in the transcript are never parsed to recover delivery decisions. Public isReplay provenance is carried through tool-result mapping.

General native notices are transcript-only because the SDK supplies no universal delivery category. Proactive fallback requires an explicit localSent: false and no native suppression other than no_transport; pushSent describes mobile transport and is kept separately. Unknown or missing delivery reports do not authorize another local send.

Replay never delivers. load_resume_history observes notifications as replay and primes terminal tool identities, including older histories without delivery reports. The manager keeps a bounded ledger of session/UUID and session/tool-ID identities across reconnects; native replacement keys are not event identities. Live suppression consumes an event instead of queuing it for a later focus change.

Session plugin attachments

The existing plugin reload owner handles both persistent plugin changes and local folder attachments through Query.reloadPlugins(). The NDJSON command carries folder intent and a request ID; the bridge resolves folders against the session cwd and requests holdOnCacheImpact. Rust retains the exact operation through a held confirmation, and Apply sends the same folders with a new request ID. Late acknowledgements cannot complete a different operation. A held result leaves commands, agents and MCP state unchanged. A native rejection, an applied result with error_count, and an applied result whose host reconciliation fails have distinct outcomes; the latter two never automatically retry an attachment.

plugin_inventory.ts owns normalization of SDK plugin metadata and selection of confirmed session attachments. SDK init frames and reload results populate that inventory; launch intent alone never creates a row. Rust holds the attachment snapshot in the existing Plugins state, separately from the CLI’s persistent installation inventory, and the Session list labels its source explicitly. Names, paths, versions and SDK sources are validated before crossing the display boundary. No installation record or marketplace configuration is fabricated.

When replacing the same active session, the bridge derives launch folders from its confirmed attachment inventory and supplies SDK Options.plugins. This includes resume, rewind and the first-message replacement path. A new session receives no attachment paths. The host does not persist these paths across process exit or switching away; native plain resume does not restore them. The first SDK init frame or an explicit reload refreshes the replacement’s inventory.

Packaging

The npm install is split across a root command package and platform payload packages.

The root package is claude-code-rust. It exposes the claude-rs command through the npm launcher and includes the built Agent SDK bridge under:

bin/claude-rs.js
agent-sdk/dist/bridge.js

The platform packages are selected through root package optional dependencies. They include the native Rust binary and private Bun runtime. The exact package mapping lives in scripts/shared/npm-package-config.mjs; supported npm payloads currently cover Linux x64/arm64 glibc, Windows x64/arm64, and macOS x64/arm64.

At runtime, npm’s generated shim starts bin/claude-rs.js. The launcher selects the matching platform package, sets CLAUDE_RS_AGENT_BRIDGE to the root package bridge script, and spawns the native binary. The native binary resolves the bundled Bun runtime from the platform package bin/ directory. No npm postinstall script, install-time binary download, or global Bun is required.

Release Model

Release packaging is designed around immutable artifacts:

  • Native binaries are built on GitHub-hosted runners for Linux x64 glibc, Linux arm64 glibc, Windows x64, Windows arm64, macOS x64, and macOS arm64.
  • Private Bun runtime files are staged into each platform package as third-party runtime artifacts.
  • Generated npm package directories are verified against allowlisted package contents before packing.
  • Unix install archives include man pages generated by the packaging host’s staged native binary. The Unix installer links those pages beside its command directory and removes only its own links on uninstall.
  • Packed npm tarballs are smoke-tested before publication.
  • GitHub Releases include native binaries, npm tarballs, package-content manifests, build metadata, and SHA256SUMS.
  • The release workflow generates and verifies build provenance attestations for native binaries before npm publication.
  • npm publication uses Trusted Publishing rather than a long-lived npm token.
  • The root package remains the user-facing npm install package and depends optionally on platform payload packages.

Source builds are different: cargo build or cargo install --path . produce only the Rust binary. They do not build or install the JavaScript bridge or private Bun runtime. Build the bridge with Node.js 24/npm and provide it through the checkout fallback, --bridge-script, or CLAUDE_RS_AGENT_BRIDGE. Debug builds can use CLAUDE_RS_AGENT_BRIDGE_RUNTIME to point at a local Bun runtime; release npm installs use only the bundled runtime. See Development for the exact steps.

Boundaries

Claude Code Rust owns the terminal UI, local settings surface, bridge process management, and event rendering. Anthropic owns the Agent SDK, authentication, service behavior, billing, models, and upstream Claude Code semantics.

The project does not depend on Agent SDK package subpath exports such as /browser, /bridge, or /assistant as the runtime path. The runtime path is the local TypeScript bridge in this repository.

Governance

This page records repository governance rules for maintainers and contributors. It describes who stewards the project, how conduct concerns are reported, how the repository is protected, how release authority is gated, how sponsorship is configured, and which GitHub settings are expected to remain in place.

Project Stewardship

The project is maintained by Simon Rothgang, who is currently the only maintainer and the only Community Moderator.

Repository rules, workflow permissions, release publication, and code of conduct enforcement are all owned by that single role. The project does not have an independent escalation contact today. If a concern involves the maintainer directly, there is no separate internal channel to route it to, and this page does not pretend otherwise.

Community Conduct and Reporting

The Code of Conduct is the policy and the source of truth for what is expected, what is restricted, and how violations are addressed. This section only describes how to reach the maintainer privately.

Conduct concerns must not be reported through public GitHub issues, GitHub Discussions, or GitHub Security Advisories. Those channels are public or reserved for security vulnerabilities, and none of them are an appropriate place for a report involving a person.

Report a concern by email to the Community Moderator, Simon Rothgang:

Include whatever you can of the following. Only what is needed to understand and respond to the report is expected:

  • what happened
  • where and when it happened
  • relevant links, messages, or screenshots
  • who was involved
  • any immediate safety or confidentiality needs

Reports are handled privately by the Community Moderator. This page does not promise absolute confidentiality or a fixed response time; the enforcement process and the possible outcomes are described in the Code of Conduct.

Repository Safeguards

Branch Protection

The main branch is protected by an active GitHub repository ruleset rather than classic branch protection.

The ruleset requires pull requests before merging to main and requires these status checks to pass:

  • pr-gate
  • Lint PR title

Pull request reviews are required. Review conversations must be resolved before merge, and new reviewable commits dismiss previous approvals.

GitHub Actions Permissions

Repository default GITHUB_TOKEN permissions are expected to be read-only. Workflows should request broader permissions only where a job needs them.

Examples of intentionally elevated job permissions include:

  • provenance attestations for release artifacts
  • OIDC tokens for npm Trusted Publishing and GitHub Pages deployment
  • GitHub Release creation and publication
  • issue creation or update from scheduled dependency monitoring

Do not rely on repository-wide write permissions for normal CI behavior.

Release Authority

Release workflow changes are maintainer-owned because they can affect package contents, provenance, publication, and user installation paths.

The npm-release environment gates publication jobs. It requires reviewer approval before npm publication or GitHub Release publication can proceed.

npm publication must use Trusted Publishing. The release process must not use a checked-in npm token or a long-lived NPM_TOKEN.

Funding

Sponsorship runs through GitHub Sponsors. .github/FUNDING.yml lists that account, and GitHub reads the file to render the Sponsor button on the repository.

No other funding platform is configured, and the project does not accept sponsorship through any channel that is not listed in that file. Adding or changing a funding target is a maintainer-owned change.

Tiers

Tiers are configured on the GitHub Sponsors account rather than per repository, so they are not specific to this project and may apply to any project the maintainer publishes. Each tier is standalone: a higher tier does not include the benefits of the ones below it.

AmountBenefitMonthlyOne-time
$5Named in the release notesWhile the sponsorship is active30 days
$25Logo on the maintainer’s GitHub profileWhile the sponsorship is active30 days
$50Logo at the top of the project READMEWhile the sponsorship is active30 days
$100Logo on the project websiteWhile the sponsorship is active30 days

Monthly and one-time tiers cost the same at every level. One-time placements run for 30 days from the day the placement goes live rather than from the payment date.

Sponsors send their logo and link after sponsoring, by email to the address given in the tier welcome message. Logo placements are added within five working days of receiving usable files, and are removed when a monthly sponsorship is cancelled or a one-time placement reaches the end of its 30 days.

Placement Policy

Placement is at maintainer discretion. Logos unrelated to software development, or that imply endorsement by or affiliation with Anthropic, are declined and the sponsorship refunded. The About page states the project’s relationship to Anthropic, and sponsor placement must not contradict it.

Sponsorship does not buy review priority, merge priority, or influence over the roadmap or governance rules on this page.

Governance Changes

Changes to repository rules, deployment environments, workflow permissions, npm Trusted Publishing configuration, or release publication behavior require explicit maintainer review.

When changing governance-sensitive files or settings, summarize the impact in the pull request and include verification of the relevant GitHub setting after the change is applied.

Changelog

All notable changes to this project will be documented in this file.

[0.16.1] - 2026-10-19 Changes

Fixes

  • Tool output (#500, @srothgan): Show actual shell, subagent, web, and plan results consistently before and after terminal resizing.
  • Tool preview performance (#501, @srothgan): Reduce rendering stalls in tool previews with long output lines.
  • Turn errors (#505, @srothgan): Show consistent errors for every failed reply, keep rate-limited input editable, and preserve the composer background.

Refactor

  • SDK and tool cleanup (#505, @srothgan): Consolidate duplicate SDK types and tool-state logic, and remove unused task tracking and cached error messages.

CI and Dependencies

  • Dependency updates (#502, #503, #504, @dependabot): Update arboard to 3.7.0, serde_json to 1.0.154, tokio to 1.53.3, CodeQL action pins, and actions/github-script to 9.0.0.

[0.16.0] - 2026-10-18 Changes

A special thank-you to Ayush Sharma (@ayush5harma) for his work and contributions. He has been the leading motivator behind this release, with his issues and ideas driving most of the work in 0.16.0.

Features

  • Background automatic updates (#437, @srothgan): Install automatic updates in the background after exit, and show a warning at startup when the last one failed.
  • Session name in Status (#445, @ayush5harma): Show the live session name in the Status tab.
  • Fullscreen Git diff viewer (#476, @srothgan): Add /diff with HEAD, staged, and unstaged comparisons, a file tree, and full file contents. Fixes #467.
  • Fullscreen session picker (#477, @srothgan): Replace /resume arguments with a searchable fullscreen picker, retain direct resume through claude-rs resume <session_id>, and show saved commands readably without internal fork points. Fixes #468.
  • Chat layout (#478, #480, @srothgan): Show sent messages as full-width cards marked with the composer prompt glyph, and group assistant text and tools under one response marker.
  • Welcome animation (#479, @ayush5harma): Animate the welcome crab while the first session connects.
  • Configurable footer (#481, #485, #493, @srothgan, @ayush5harma): Add a single-row footer with per-field visibility, alignment, order, colors, and a running-subagent count, and apply the saved layout from startup. Fixes #466, #482.
  • Mode and effort shortcuts (#486, @srothgan): Add Shift+Left and Shift+Right to change permission mode and Shift+Up and Shift+Down to change effort. Fixes #483.
  • Skills and styles reload (#487, @ayush5harma): Add /reload to reload skills and output styles in the active session. Fixes #464.
  • Conversation export (#491, @ayush5harma): Add /export [path] to save session history as Markdown without overwriting existing files. Fixes #465.
  • Session launch flags (#492, @ayush5harma): Add session naming and forking, extra directories, settings and MCP configuration, and system prompt replacement or extension from text or files. Fixes #462.
  • Subagents view (#493, #496, @ayush5harma, @srothgan): Add fullscreen /agents with live status, ancestry, stop controls, saved-response previews, and refreshable transcripts, and restore saved nested subagents without marking historical runs as active. Fixes #439.
  • Bridge and hook diagnostics (#494, @ayush5harma): Record bridge and SDK warnings and errors in the default log and show hook failures in the transcript. Fixes #463.
  • Agent SDK migration (#496, @srothgan): Upgrade Agent SDK from 0.3.288 to 0.3.302, add session-local plugin folders, typed MCP forms, hook failure policies, idleCompaction, CLAUDE_RS_CONFIG_DIR, and scheduler and notification timestamps, and correct startup, authentication, and extra-usage errors. Fixes #421.

Fixes

  • Local command replies (#444, @ayush5harma): Show missing replies to commands handled locally by Claude Code, including /rename, /color, and /context.
  • Markdown and tool previews (#478, #484, @srothgan): Preserve fenced code, streamed tables, nested lists, and full-file indentation, show numbered file source in Read previews, and retain shell output colors. Fixes #461.
  • Status tab rename (#488, @ayush5harma): Keep renaming unavailable until the session is saved and retain the draft when a rename fails. Fixes #469.
  • Path arguments (#489, @ayush5harma): Stop invalid --dir and --bridge-script paths from reaching the trust prompt or failing as a bridge spawn error. Fixes #472.
  • Trust prompt directory (#490, @ayush5harma): Show the directory that the trust prompt will trust. Fixes #473.
  • Read and replay performance (#495, #497, @srothgan): Reduce long stalls during large file reads, session resume, and terminal resizing, stop startup history purges, and add Read preview timing diagnostics and updated source-build instructions.
  • Markdown lists and tables (#498, @srothgan): Keep text following a list at the normal column and display tables with borders and wrapped cells.

Documentation

  • Contribution requirements (#470, @srothgan): Require an issue and maintainer scope agreement before implementation or pull requests.

CI and Dependencies

  • Dependency updates (#448, #449, #450, #451, #470, #484, @srothgan, @dependabot): Bump rustls to 0.23.46, zip to 9.0.4, and tokio to 1.53.2, remove ansi-to-tui, and update bridge dev dependencies, jscpd, and GitHub Actions pins.
  • Bridge test coverage (#471, @ayush5harma): Run the top-level bridge test files in CI. Fixes #446.
  • Issue triage automation (#474, @srothgan): Add the Issue Triage workflow with /triaged and /duplicate commands.

[0.15.2] - 2026-10-08 Changes

Fixes

  • Clipboard image paste on macOS and Linux (#432, @freddysae0): Attach clipboard images with Ctrl+V on macOS and Linux. Fixes #431.
  • Clipboard image paste on Wayland (#435, @srothgan): Attach clipboard images with Ctrl+V in Wayland sessions without XWayland. Fixes #385.
  • Session connect with large configurations (#434, @freddysae0): Stop sessions from failing to connect when the Claude Code configuration has many plugins or MCP servers. Fixes #433.

CI and Dependencies

  • Clipboard paste coverage (#435, @srothgan): Add workflow, encoder, and PTY tests for Ctrl+V image paste, and run the system clipboard test on the Linux, macOS, and Windows runners.

[0.15.1] - 2026-10-06 Changes

Fixes

  • Resumed session history (#426, @srothgan): Restore the full conversation when resuming a compacted session, and hide internal task notifications and compact summaries in resumed history.
  • Background tools (#426, @srothgan): Keep background tool cards in launch order with one linked result per finished task, keep their controls usable across turns, resize, and resume, and stream the reply that follows a finished task under one Claude label.
  • Scrollback across resizes (#422, @srothgan): Stop losing transcript rows from terminal scrollback after resizing, zooming, or resizing in reading mode.
  • Exit redraw (#426, @srothgan): Stop replaying the transcript into scrollback on exit.
  • Tool titles (#426, @srothgan): Show shell command titles literally instead of as Markdown, and stop re-rendering unchanged tool titles during animation and resize.
  • Installer interruption (#422, @srothgan): Stop a repeated Ctrl-C from cutting off installer cleanup.

CI and Dependencies

  • Terminal and installer test stability (#422, #424, #426, @srothgan): Stop intermittent failures in the PTY, settings, installer prompt, update-check, and unit diagnostics tests.
  • Resume and background task coverage (#426, @srothgan): Add bridge resume-history tests and PTY tests for background tools, shutdown, and scrollback.
  • Cargo build jobs (#422, @srothgan): Limit Cargo to one compilation job through .cargo/config.toml.

[0.15.0] - 2026-10-04 Changes

Features

  • SDK-resolved settings and rebuilt /config (#415, @srothgan): Rebuild /config on SDK settings with per-scope save and reset, searchable panes, and editors for hooks, permission rules, sandbox, memory, workflows, and worktrees. Add /memory, /permissions, /sandbox, and /hooks to open the matching pane.
  • Session and presentation controls (#415, @srothgan): Add /thinking, /copy, /effort reset, and /fast [on|off], plus settings for default effort, default agent, message timestamps, Auto-scroll, and reduced motion.
  • Notifications, automatic updates, and question timeout (#415, @srothgan): Add per-category notification toggles, a Notification method setting, an Automatic updates preference (default Off), and a Question timeout setting.
  • Startup flags and initial prompt (#413, @srothgan): Add an initial prompt argument, --resume [ID], --continue, and session-only --model, --effort, --permission-mode, and --agent.
  • Shell completions and man pages (#413, @srothgan): Add claude-rs completions <shell> for Bash, Zsh, Fish, PowerShell, and Elvish, and claude-rs man <dir>.
  • Agent SDK 0.3.288 migration (#414, @srothgan): Upgrade to Agent SDK 0.3.288 and update tool cards when detached web calls finish in a later turn.
  • Installer prompts and cleanup (#414, @srothgan): Add single-key y/n prompts, consistent progress output, and optional cleanup of other script and npm installations.

Fixes

  • Inline resize crash (#408, @srothgan): Stop the app from exiting when the terminal grows during a streamed reply. Fixes #407.
  • CLAUDE_CONFIG_DIR profile paths (#408, @srothgan): Honor CLAUDE_CONFIG_DIR for user settings, workspace trust, and file credentials.
  • User message paragraph spacing (#409, @srothgan): Keep blank lines between paragraphs in submitted user messages.
  • Draft and input preservation (#410, @srothgan): Stop losing unsent drafts, attachments, and typed input on send failures, turn errors, resize, paste, and authentication.
  • Edit diff line numbers (#412, @srothgan): Show file line numbers in completed Edit diffs instead of counting from 1.

Removed

  • Legacy commands (#415, @srothgan): Remove /1m-context and /opus-version.
  • Perf telemetry (#411, @srothgan): Remove the perf Cargo feature and the --enable-perf, --perf-log, and --perf-append flags. Debug bundles now use manifest schema claude-rs-debug-bundle/v2.

Documentation

  • Design history and performance claims (#406, @srothgan): Link the article on the 0.12.0 move to inline rendering and note that no benchmark against the stock interface exists yet.
  • CLI dependencies and feature overview (#413, @srothgan): Document which operations need a separately installed claude command and which stock interface features are unavailable.
  • Settings reference and agent instructions (#415, @srothgan): Restructure the settings and architecture pages and move personal agent instructions to an untracked PERSONAL.md.

Release and Packaging

  • Bundled manuals (#413, @srothgan): Ship man pages in Unix install archives and install them with the script installer.

CI and Dependencies

  • Real-terminal regression suite (#408, #410, @srothgan): Add PTY tests of the real binary, required on Ubuntu, Windows, and macOS.
  • Cross-platform Clippy and installer checks (#414, #415, @srothgan): Run Clippy on Ubuntu, Windows, and macOS and add installer regression tests to the PR workflow.
  • New dependencies (#413, #415, @srothgan): Add clap_complete, clap_mangen, chrono, chrono-tz, and sys-locale.

[0.14.9] - 2026-10-01 Changes

Features

  • Installer release advisories (#405, @srothgan): Warn during script installs when the selected release has a known issue.

Fixes

  • Slash command submission (#405, @srothgan): Make Enter complete and submit slash commands with or without arguments. Affects 0.12.0 through 0.14.8.
  • Slash command completion (#405, @srothgan): Rank exact matches first and keep SDK commands available after /clear.

[0.14.8] - 2026-10-01 Changes

Features

  • Opus 5.5, Sonnet 5.5, and Agent SDK 0.3.286 migration (#403, @srothgan): Upgrade to Agent SDK 0.3.286, add Opus 5.5 and Sonnet 5.5 support, and handle slash command aliases, SDK conversation resets, plugin load failure notices, and Artifact pin state.
  • /btw side questions (#403, @srothgan): Ask side questions with /btw <question> without interrupting the active turn, queueing up to ten.
  • /ultracode session controls (#403, @srothgan): Toggle and inspect Ultracode with /ultracode on, off, and status, keep it active across effort changes, and show a purple footer label only while it is effective.
  • Composer input surface (#392, @srothgan): Give the composer the user-message background with one-cell padding on every side.

Fixes

  • Actionable startup failures (#403, @srothgan): Map every SDK startup failure reason to an actionable message, suppress duplicate failures, and keep the composer input recoverable.
  • Bridge spawn diagnostics (#393, @srothgan): Preserve the OS error in the bridge spawn failure chain and remove the exec race behind the flaky bridge spawn test.

Documentation

  • GitHub Sponsors (#402, @srothgan): Add the repository Sponsor button and document sponsorship tiers and placement policy on the governance page.
  • Shared agent instructions (#403, @srothgan): Track AGENTS.md and add a CLAUDE.md that imports it.

CI and Dependencies

  • rustls security update (#393, @srothgan): Bump rustls to 0.23.45 to clear RUSTSEC-2026-0285 while keeping the 1.88.0 MSRV.

[0.14.7] - 2026-09-13 Changes

Features

  • Agent SDK 0.3.270 migration (#378, @srothgan): Upgrade to Agent SDK 0.3.270, honor permission safety hints and SDK-controlled Task and Todo availability, hold cache-invalidating plugin reloads behind explicit confirmation, and render staged writes, project memory, and expanded Artifact metadata.

Fixes

  • Prompt suggestion lifecycle (#377, @srothgan): Clear the SDK prompt suggestion only after a prompt is dispatched or queued, so local slash commands, rejected submissions, and send failures keep it visible.

[0.14.6] - 2026-09-02 Changes

Features

  • Active-turn message queue (#363, @srothgan): Upgrade to Agent SDK 0.3.258 and queue up to ten messages with correlated chat insertion.

Fixes

  • Responsive startup and file indexing (#352, @srothgan): Keep the composer editable while connecting, defer sends until the session is ready, and run one bounded post-connection file index.
  • Welcome overview wrapping (#351, @srothgan): Align wrapped tips and metadata beneath their values and hide Ferris on narrow terminals.

[0.14.5] - 2026-08-23 Changes

Features

  • Agent SDK and Bun migration (#349, @srothgan): Upgrade to Agent SDK 0.3.239 and Bun 1.4.0, render SDK-owned /context, and expand task and Artifact compatibility.

Documentation

  • Animated README demo (#348, @srothgan): Replace the static banner with a reproducible terminal recording that highlights Claude Code Rust’s terminal improvements.

[0.14.4] - 2026-08-13 Changes

Features

  • Claude Agent SDK 0.3.227 migration (#338, @srothgan): Add guarded resume-at, structured usage, cross-session message provenance, and current SDK metadata support.
  • Active-turn commands (#339, @srothgan): Allow safe commands during active turns and preserve blocked drafts instead of cancelling the turn.
  • Latest-message recall (#340, @srothgan): Recall the latest user message with Up when the chat input is empty, while preserving normal multiline cursor movement.

Fixes

  • Reliable TUI shutdown (#341, @srothgan): Close fullscreen views without interrupting active turns, support forced cleanup, restore terminal state, and preserve resume guidance.

[0.14.3] - 2026-08-01 Changes

Features

  • Installer download progress (#312, @srothgan): Stream release downloads with reliable retries, fixed-width progress bars, and optional transfer diagnostics.
  • Skill tool rendering (#318, @srothgan): Show Skill calls with a dedicated icon, readable names, compact arguments, and no redundant launch output.
  • Image read confirmations (#319, @srothgan): Replace image payloads with compact filename confirmations while preserving Read titles and errors.

Fixes

  • Runtime and tooling hardening (#317, @srothgan): Add privacy-minimized diagnostics, preserve resume hints, prevent phantom tool progress, and align dependency checks with release targets.
  • Compaction lifecycle (#320, @srothgan): Unify compaction state, surface failures, and prevent duplicate indicators and completion notices.

[0.14.2] - 2026-07-26 Changes

Features

  • Readline line-stepping (#305, @srothgan): Make Ctrl+A/Ctrl+E move to the line start/end, then step to the previous/next logical line on repeat.
  • Live fast-mode control (#309, @srothgan): Make /fast control the active SDK session with capability checks and synchronized state.
  • Opus 5 and Claude Agent SDK 0.3.220 migration (#310, @srothgan): Add Opus 5 support, preserve rejected and cancelled tool outcomes, warn on partial rewinds, and surface detached Skills, fast-mode failures, and Artifact live subscriptions.

Fixes

  • Lifecycle and bridge hardening (#309, @srothgan): Enforce session-authoritative state, prevent idle event-loop spin, serialize and bound bridge traffic, and give MCP monitoring and shutdown explicit ownership.

Release and Packaging

  • Claude CLI installer warning (#311, @srothgan): Warn when claude is missing from PATH and link to the Claude Code install guide without blocking claude-rs installation.

[0.14.1] - 2026-07-18 Changes

Documentation

  • Manual restructure (#282, @srothgan): Split installation into end-user install, development, and troubleshooting pages, document /agent, restore the conduct report contact in the issue chooser, and add tests keeping the slash command and CLI tables in sync with the code.

Release and Packaging

  • Installer progress and idempotency (#281, @srothgan): Add inline installer progress across PowerShell, macOS, and Linux while keeping CI output plain, and make same-version reinstalls a prompted opt-in with --yes/-Yes approval.

CI and Dependencies

  • Claude Agent SDK update (#285, @srothgan): Bump the bundled bridge to Agent SDK 0.3.214, preserve subagent model routes, retry and Bash timeout state, keep Grep and Artifact output accurate, and disable new review-dependent tools until the TUI can present them safely.

[0.14.0] - 2026-07-12 Changes

Features

  • In-chat usage limits (#270, @srothgan): Add /limits to print recent 5-hour, 7-day, and extra-credit usage into the chat from the existing usage snapshot/refresh pipeline, including a loading message for stale data and a concise refresh failure message while keeping /usage as the fullscreen Usage tab.
  • Native textarea cursor (#268, @srothgan): Use tui-textarea-2 native cursor positioning for the chat composer, hide the textarea-drawn cursor, and restore terminal cursor shape when leaving chat surfaces.
  • Startup update screen (#264, @srothgan): Show available updates in a startup screen with install, skip, and release-notes actions.

Fixes

  • Inline cursor tracking (#266, @srothgan): Avoid Unix/macOS live-loop DSR cursor reads in inline chat by using tracked cursor state for the ratatui viewport and invalidating cached seeds after external terminal ownership boundaries.
  • Markdown list rendering (#263, @srothgan): Keep streamed inline Markdown handoffs mutable only until delimiters resolve, let stable scrollback advance after resolved blocks, and preserve fenced code layout when code lines look like Markdown list items.

Documentation

  • Governance and source install docs (#262, @srothgan): Document repository release controls and clarify source-build auth/runtime setup.
  • Private conduct reporting (@srothgan): Add a dedicated private contact for code of conduct reports and keep security advisories focused on vulnerability disclosure.

Maintenance

  • Repository health cleanup (#262, @srothgan): Consolidate duplicated UI rendering helpers, add Rust SPDX headers, and remove stale TODO/header noise.

Release and Packaging

  • Install scripts (#259, #267, @srothgan): Add macOS/Linux and Windows install scripts that install from GitHub Releases without requiring npm, Node.js, or Bun on the user’s machine, and preserve the detected install method for in-app updates.
  • Release script phases (#260, @srothgan): Reorganize release tooling scripts into phase directories, add shared repository-root resolution, and expand PR validation for install archives and public installers.
  • Windows npm mock smoke (#262, @srothgan): Make local Windows mock package smoke tests use spawnable binaries and isolated npm cache state.

CI and Dependencies

  • Duplicate-code gate (#262, @srothgan): Add PR jscpd thresholds with a 1% warning, 2% failure, and pr-gate enforcement.
  • Advisory and tooling updates (#262, @srothgan): Refresh dependency advisory/tooling locks and remove resolved cargo-deny advisory ignores.
  • Claude Agent SDK update (#272, @srothgan): Bump the bundled bridge packages to Agent SDK 0.3.207, preserve new task metadata and terminal reason values, normalize the new permission-mode alias, and remove the unmatched mouse-capture restore action.
  • Release skip on unchanged version (#269, @srothgan): Skip the release workflow with a green no-op when a Cargo.toml push leaves the crate version unchanged.

[0.13.4] - 2026-07-06 Changes

Features

  • Bundled Bun bridge runtime (#245, @srothgan): Ship a private Bun runtime in each platform npm package so the Agent SDK bridge no longer needs a separately installed Node runtime to run.

CI and Dependencies

  • Node 24 maintainer floor (#254, @srothgan): Raise root and Agent SDK npm engine metadata to Node 24 for source-build tooling.

[0.13.3] - 2026-07-04 Changes

Features

  • ARM64 npm binaries (#243, @srothgan): Add Linux arm64 glibc and Windows arm64 MSVC platform packages to the npm release flow.

Fixes

  • File mention completion (#242, @srothgan): Let Tab commit selected or literal @ file mentions with quoted paths and cleaner autocomplete boundaries.
  • Release publication targeting (#238, #239, @srothgan): Verify reusable-workflow attestations and pin GitHub Release publishing to the target repository.

Release and Packaging

  • Platform package READMEs (@srothgan): Generate concise platform-specific npm READMEs with version, install, target, and platform details.
  • Dependency declarations (#240, @srothgan): Remove redundant direct npm dependencies while keeping runtime installs unchanged.

[0.13.2] - 2026-07-03 Changes

Features

  • Supportability commands (#235, @srothgan): Add claude-rs doctor, logs, redacted debug bundles, crash and bridge failure reports, and read-only redacted config inspection/export commands for installation and runtime diagnostics.

Release and Packaging

  • Platform npm packages (#232, @srothgan): Replace the install-time GitHub Release downloader with a root launcher plus platform-specific optional npm packages for macOS arm64/x64, Linux x64 glibc, and Windows x64 MSVC.
  • Trusted Publishing release flow (#232, @srothgan): Publish platform packages before the root package from a protected npm-release environment, with package-content manifests, checksums, provenance, and binary attestations.
  • Package validation (#232, @srothgan): Add generated package assembly, package layout verification, and tarball smoke tests so release candidates and npm releases validate the installed launcher and platform binary layout before publishing.
  • Release publication guardrail (#233, #236, @srothgan): Create the GitHub Release as a draft, publish npm platform and root packages from explicit local tarball paths, then publish the GitHub Release only after npm publication succeeds.

Testing

  • Bridge contract coverage (#234, @srothgan): Add Node-side NDJSON bridge contract tests and Rust-side bridge lifecycle failure coverage without requiring Claude credentials.
  • Direct binary smoke checks (#234, #236, @srothgan): Validate release binary startup with --version and --help across supported platforms outside the npm package smoke path.

CI and Supply Chain

  • Cargo Deny policy (#236, @srothgan): Add deny.toml and enforce Cargo dependency policy for advisories, licenses, duplicate-crate policy, and allowed sources.
  • Workflow consolidation (#236, @srothgan): Replace the broad PR workflow set with pr-gate, separate PR title lint, reusable Agent SDK and release build workflows, scheduled deep checks, and dependency monitoring.
  • Workflow action pinning (#236, @srothgan): Pin external GitHub Actions to full commit SHAs and align repository rules with the new required status checks.

Maintenance

  • Focused app state modules (#231, @srothgan): Split app state, runtime session, startup, turn, transcript, and SDK inventory bookkeeping into focused modules while preserving public behavior.

Documentation

  • Install architecture (#232, @srothgan): Document the optional-dependency install model, platform package troubleshooting, source-build bridge behavior, and release invariants for contributors.
  • Diagnostics and security docs (#235, #236, @srothgan): Document supportability commands, redacted config exports, current repository security controls, and the paused Agent SDK billing change.

Notes

  • 0.13.1 was skipped before npm publication after a failed release workflow. No 0.13.1 npm packages were published.

[0.13.0] - 2026-07-02 Changes

Features

  • Fable 5 and Claude Agent SDK 0.3.198 migration (#229, @srothgan): Make Fable 5 the default model alias, preserve resolved model IDs from the SDK catalog, and refresh bridge metadata handling for current models, MCP request timeouts, and newer SDK status fields.
  • Separate model and thinking effort config dialogs (#229, @srothgan): Split the combined /config model and effort picker into independent dialogs, keep effort choices filtered by the selected model, and explain the model-dependent effort behavior only in the effort dialog.
  • Mention file autocomplete (#226, @srothgan): Move @ file matching off the UI path, support raw indexed file and folder mentions with spaces, preserve whole-mention replacement boundaries, and rank shallow project paths ahead of deep dependency matches unless the query explicitly targets the deep path.
  • Atomic input placeholders (#227, @srothgan): Treat image badges and pasted-text placeholders as shared textarea atoms, keeping cursor movement, deletion, undo/redo, image attachment state, and paste expansion aligned through tui-textarea-2 0.12.0 atomic range support.
  • Question and list rendering (#228, @srothgan): Render markdown lists with indentation instead of injected blank gaps, and show AskUserQuestion answers as structured results with selected options, descriptions, previews, and notes.

Documentation

  • README banner (#217, @srothgan): Add a project screenshot banner to the README.

Fixes

  • SDK metadata and MCP preservation (#229, @srothgan): Preserve MCP request_timeout_ms through status display, diagnostics, and dynamic server removal, and keep app-owned slash commands from being duplicated by SDK command snapshots.
  • Inline chat resize transactions (#217, @srothgan): Treat terminal size as a draw-transaction snapshot, recover from mid-draw resizes with purge/replay, and clip stale inline viewport geometry before owned-region clears.
  • Streaming markdown tables (#226, @srothgan): Preserve table rendering across streamed cache splits so partial assistant updates do not corrupt table layout.

Maintenance

  • Dead test helper cleanup (#228, @srothgan): Remove stale test-only helpers that kept old production paths alive only through tests.
  • Social discoverability (#219, @srothgan): Add Open Graph and Twitter Card meta tags with a social preview image to the docs site, and expand the npm package keywords to mirror the repo topics.

CI and Dependencies

  • Workflow permission hardening (#229, @srothgan): Declare least-privilege GitHub Actions permissions for CI, audit, commit-lint, release dry-run, and Agent SDK workflows to resolve CodeQL code scanning alerts.
  • Claude Agent SDK update (#229, @srothgan): Bump @anthropic-ai/claude-agent-sdk to 0.3.198 in the root package and bundled bridge package locks.
  • CodeQL scanning (#228, @srothgan): Add a CodeQL workflow for repository code scanning.
  • quinn-proto advisory fix (#220, @srothgan): Bump quinn-proto to 0.11.15 for RUSTSEC-2026-0185 (remote memory exhaustion from unbounded out-of-order stream reassembly).
  • Security Audit workflow resilience (#220, @srothgan): Mark the cargo audit step continue-on-error so newly published advisories still report and file a tracking issue without failing the scheduled Security Audit run.
  • Dependency updates (#221, #222, #224, #223): Bump uuid to 1.23.4, anyhow to 1.0.103, tui-markdown to 0.3.8, and knip to 6.23.0 in agent-sdk.

[0.12.4] - 2026-06-26 Changes

Features

  • Claude Agent SDK 0.3.193 migration (#212, @srothgan): Refresh the bridge for the current SDK, add /rewind with conversation and code restore modes, render MCP resource directory listings, and surface new SDK system notices, rate-limit credit metadata, and SDK-created resume sessions.
  • Deterministic Read syntax highlighting (#210, @srothgan): Preserve tool locations for Read output, add broader syntax coverage, and render a brighter dark-terminal theme with a dim line-number gutter.

Fixes

  • Inline viewport bottom growth (#214, @srothgan): Scroll the terminal before autocomplete and composer expansion at the screen bottom so handed-off transcript rows are pushed up instead of overwritten.
  • Runtime resize and notice hardening (#211, @srothgan): Prevent notice migration and terminal row-range panics, preserve resize replay repaint requests, and clamp inline geometry after terminal shrinks.

Maintenance

  • Production module split (#215, @srothgan): Move inline module tests into sibling files and split keymap, agent model, app state, plugins, config, and MCP config code into focused child modules while preserving facade exports.

CI and Dependencies

  • Dependabot and Agent SDK monitor cleanup (#201, #207, @srothgan): Add npm version updates for root and bridge packages, make the SDK monitor the single Agent SDK update path, bump the bridge TypeScript toolchain, and clear Hono advisories.
  • Dependency updates (#196, #197, #198, #199, #200): Bump which to 8.0.4, ratatui to 0.30.2, time to 0.3.51, hono through 4.12.27, and rand to 0.8.6.
  • Workflow action bump (#195): Bump actions/checkout to 7.

[0.12.3] - 2026-06-16 Changes

Documentation

  • Agent SDK billing notice (@srothgan): Anthropic paused the Agent SDK credit change documented in (#165, @srothgan); SDK usage still draws from normal Claude subscription limits. Shrink the README warning to a compact note linking the support article.

Fixes

  • Startup repaint and PowerShell rendering (#193, @srothgan): Smooth the startup repaint and fix PowerShell tool-call rendering.

CI and Dependencies

  • SDK monitor and advisory checks (#186, #187, @srothgan): Add an Agent SDK update monitor and advisory quality checks.
  • Rust dependency updates (#189, #190, #191, #192): Bump uuid to 1.23.3, time to 0.3.49, ignore to 0.4.26, and which to 8.0.3.
  • Workflow action bump (#188): Bump actions/upload-artifact to 7.

[0.12.2] - 2026-06-14 Changes

Features

  • Claude Agent SDK 0.3.177 migration (#180, #182, @srothgan): Refresh the bridge for new SDK metadata, task events, dialogs, retractions, retry errors, and MCP status.
  • Opus 4.8 and effort controls (#180, @srothgan): Add /opus-version 4.8, /effort, xhigh, session-only max, and live /agent switching.
  • MCP configuration management (#180, #182, @srothgan): Add scoped server removal and track dynamic, plugin-owned, persisted, and runtime-only servers.

UI

  • Structured SDK tool rendering (#180, #182, @srothgan): Add readable renderers for new task, automation, workflow, MCP, search, project, artifact, and agent tool outputs.
  • MCP tool-call display (#184, @srothgan): Show readable MCP titles with a dedicated icon while keeping raw tool names intact.
  • Config dialog overlays (#180, @srothgan): Tighten fullscreen dialogs, confirmations, and small-screen overflow.

Fixes

  • SDK compatibility hardening (#180, #182, @srothgan): Normalize retry errors, overage fields, unavailable models, mirror errors, resume task replay, and MCP snapshot refresh.
  • Plugin and MCP scope accuracy (#180, #182, @srothgan): Filter plugin lists and stale MCP servers by the scopes that are actually active.

Diagnostics

  • Timestamped runtime logs (#183, @srothgan): Write default diagnostics to per-run files under logs/runtime with bounded retention.

Documentation

  • Commands and diagnostics manual updates (#180, #183, @srothgan): Document /effort, /opus-version 4.8, settings behavior, and diagnostics paths.

CI and Dependencies

  • Agent SDK package refresh (#180, #182, @srothgan): Update the Agent SDK bridge packages and npm lockfiles.
  • Rust dependency updates (#176, #177, #178, #179): Bump unicode-segmentation to 1.13.3, uuid to 1.23.2, reqwest to 0.13.4, and ratatui to 0.30.1.
  • Pages workflow updates (#173, #174, #175): Bump actions/upload-pages-artifact to 5, actions/deploy-pages to 5, and actions/configure-pages to 6.

[0.12.1] - 2026-05-28 Changes

Documentation

  • mdBook manual and GitHub Pages workflow (@srothgan): Add a repo-native manual and Pages deployment workflow.

Fixes

  • CLI help examples (@srothgan): Remove the invalid installed-binary --features perf example.

[0.12.0] - 2026-05-21 Changes

Features

  • Inline terminal chat runtime (#165, @srothgan): Replace the full-screen chat surface with inline terminal-owned rendering.
  • Resolved action-based keymap (#166, @srothgan): Route shortcuts through semantic actions and generate help from the resolved keymap.
  • macOS modifier key support (#159, @TomasWeisss): Support Command-key shortcuts in terminal modes.

Fixes

  • Inline rendering stability (#165, @srothgan): Stabilize resume, resize, fullscreen return, slash notices, and active-turn state on the inline path.
  • Tool-call and diff rendering (#152, #165, #166, @srothgan): Preserve diff indentation, show compact change counts, uncap plan markdown, and keep concrete tool output.
  • Agent SDK bridge events (#165, @srothgan): Suppress ToolSearch events, protect the packaged bridge runtime, and accept fractional API retry delays.

UI

  • Composer hints and Help tab (#165, #166, @srothgan): Move autocomplete into compact composer rows and Help into fullscreen config.
  • Compact inline tools and todos (#165, @srothgan): Render todos inline and tighten standard tool body caps.

Documentation

  • README billing and commands cleanup (#165, @srothgan): Document Agent SDK billing changes, custom slash commands, and remove the outdated Architecture section.

CI and Dependencies

  • Agent SDK 0.3.146 refresh (#165, @srothgan): Update the Agent SDK bridge dependencies and package locks.
  • Rust dependency updates (#151, #154, #155, #156, #157, #158, #160, #161, #162, #163, #164): Bump Rust dependencies and clarify the rand audit ignore.
  • rustls-webpki advisory fix (#153): Bump rustls-webpki to 0.103.13 for RUSTSEC-2026-0104.

[0.11.3] - 2026-04-19 Changes

Fixes

  • Plan approval Ctrl shortcuts (@srothgan): Replace plain y/n exit-plan approvals with Ctrl+y/Ctrl+n.

[0.11.2] - 2026-04-19 Changes

Features

  • Project-local Opus version controls (#146, @srothgan): Add /opus-version to pin the Opus alias per project.

Fixes

  • Model alias cleanup and Opus naming (#146, @srothgan): Replace Default with the explicit opus alias and normalize dated Opus labels.
  • Dev versus installed bridge resolution (#146, @srothgan): Make cargo run use the repo bridge and installed builds use the bundled bridge.
  • Tool-call diff rendering and scrollbar lane (#138, @srothgan): Reserve a dedicated scrollbar column and keep diff content out of it.
  • Versioned short model names (#139, @srothgan): Show resolved model versions in short model names.
  • Bridge script resolution precedence (#142, @srothgan): Prefer the bundled bridge script and keep repo-local fallback debug-only.
  • Update notice warning message (#143, @srothgan): Move upgrade hints from the footer into a warning system message.
  • Terminal ANSI output rendering (#144, @srothgan): Preserve command-emitted ANSI colors in terminal tool output.
  • Draft-focused inline prompts (#145, @srothgan): Keep pending prompts from stealing draft focus and move prompt handoff to Tab.

CI and Dependencies

  • Agent SDK 0.2.112 refresh (#141, @shyal): Bump @anthropic-ai/claude-agent-sdk to 0.2.112, update EXPECTED_AGENT_SDK_VERSION, and refresh 4.7 fixtures.

[0.11.1] - 2026-04-16 Changes

Features

  • Folder-local 1M context controls (@srothgan): Add /1m-context enable|disable|status to persist CLAUDE_CODE_DISABLE_1M_CONTEXT in .claude/settings.local.json, preserve neighboring local env keys, surface status, and point 1M-context recovery guidance at the new folder-local fallback

[0.11.0] - 2026-04-16 Changes

Features

  • Agent SDK 0.2.104 migration (#135, @srothgan): Upgrade the bundled Claude Agent SDK from 0.2.74 to 0.2.104 across the published package and local bridge; extend the Rust and TypeScript wire contract for current-model snapshots, runtime session state, API retry updates, settings parse errors, terminal reasons, task metadata, prompt suggestions, and refreshed tool metadata
  • Live session capability synchronization (#135, @srothgan): Reconcile current model and permission-mode support against the active SDK session instead of assuming startup-time state, and keep session/runtime status aligned through connect, resume, and turn lifecycle changes
  • Task patch updates and subagent grouping (#135, @srothgan): Propagate incremental task patches and parent tool linkage so subagent child tool calls collapse under their root task while still surfacing focused hidden permission prompts when user input is required
  • Welcome session snapshot and rotating tips (#135, @srothgan): Replace the welcome model badge with a lightweight snapshot showing version, subscription, cwd, and session ID, and rotate curated startup tips across sessions
  • Backgrounded tool state badges (#135, @srothgan): Surface assistant-backgrounded Bash commands and backgrounded task state directly in tool cards and summaries

Fixes

  • Resume ordering and runtime stability (#135, @srothgan): Preserve resumed history turn ordering and tighten turn/session state handling so reconnects, tool updates, and completion events stay consistent
  • External API provider auth handling (#135, @srothgan): Respect external API providers during auth validation instead of assuming the bundled Claude auth path
  • Permission and tool-result rendering cleanup (#135, @srothgan): Normalize SDK permission display and tool-result metadata, hide redundant permission headers, and treat killed tool calls as terminal failures in transcript rendering
  • Ctrl+V paste path split (#135, @srothgan): Make Ctrl+V exclusively trigger image paste while keeping normal text paste on the standard input path
  • Collapsed in-progress subagent summaries (#135, @srothgan): Show substantially more context in collapsed in-progress subagent cards without expanding completed tool calls

Documentation

  • Startup limitation note (#135, @srothgan): Document the current end-to-end startup latency constraint from the upstream Claude Agent SDK runtime in README.md

CI and Dependencies

  • Bump @anthropic-ai/claude-agent-sdk from 0.2.74 to 0.2.104 in both the published package and bundled bridge (#135, @srothgan)
  • Add dedicated agent-sdk CI for audit, lint, and knip, and gate audit failures on direct dependency advisories only (#135, @srothgan)
  • Add @anthropic-ai/sdk 0.81.0, @biomejs/biome 2.4.12, and knip 6.4.1 to the bundled bridge toolchain (#135, @srothgan)

[0.10.0] - 2026-04-11 Changes

Features

  • Clipboard image pasting (#104, @shyal): Paste images with Ctrl+V, send them as PNG image blocks, and render renumbered inline [Image #N] badges in the draft
  • Live git branch tracking (#114, @srothgan): Replace git branch --show-current shell-outs with in-process HEAD parsing and a filesystem watcher so the footer updates while the app stays focused
  • Terminal tab activity indicator (#115, @srothgan): Drive the OSC 2 tab title from app state with active and idle indicators and restore the plain cwd title on shutdown
  • Resume subcommand and startup picker (#116, @srothgan): Replace the --resume flag with claude-rs resume, add a dedicated startup picker, and cap it to recent project sessions
  • App-owned file index with live updates (#117, @srothgan): Move @ mention search to a shared file index with scan streaming, prewarm, and incremental watcher updates across cwd and gitignore changes

Fixes

  • Inline turn-scoped limit notices (#118, @srothgan): Dedup rate-limit and plan-limit notices inside the active assistant turn instead of appending duplicate trailing system rows
  • Rename watcher convergence (#120, @srothgan): Re-scan parent subtrees on file-index rename events, handle root-level renames, and refresh the yanked unicode-segmentation lockfile entry

Performance

  • Structured logging and render-path optimization (#119, @srothgan): Standardize Rust and Agent SDK diagnostics, switch to JSON rolling logs, and cut chat hot-path cost with assembled render caching and cheaper spinner frames

Documentation

  • Legal notice expansion (#113, @srothgan): Clarify the project’s relationship to Claude Code, the Agent SDK, Anthropic terms, and the recent source leak

CI and Dependencies

  • Bump uuid from 1.22.0 to 1.23.0 (#106, @dependabot)
  • Bump notify-rust from 4.12.0 to 4.13.1 (#109, @dependabot)
  • Bump similar from 2.7.0 to 3.0.0 (#110, @dependabot)
  • Bump tokio from 1.50.0 to 1.51.0 (#111, @dependabot)

Project

  • Collaboration template cleanup (#121, @srothgan): Simplify PR and issue templates, collapse CODEOWNERS, and align CONTRIBUTING.md with the current workflow

[0.9.0] - 2026-03-26 Changes

Features

  • Two-line footer replaces header (#102): Remove the header and consolidate location, branch, mode badges, permission counts, and MCP auth hints into a two-row adaptive footer

Fixes

  • Unified viewport geometry handling (#101): Single geometry entry point with separate width/height semantics and tail invalidation on topology changes
  • Centralized geometry state and wrapped panel measurement (#101): Immediate resize geometry refresh and wrapped-text measurement replacing fixed-height panel assumptions
  • Topology invalidation and batch message dirtiness (#101): Tracked insert/remove/clear paths own tool index and terminal ref repair
  • Active turn ownership across history pruning (#101): Keep active assistant turn out of retention drop candidates and remap ownership after pruning
  • Scroll anchor preservation (#101): Delay anchor restore until heights are exact and preserve anchors across pruning and marker operations
  • Unified message layout model (#101): Shared MessageLayout replaces split role-specific render/measure branches
  • Turn cleanup normalization (#101): Single cleanup boundary for resume, cancel, auth-required, connection-failure, and fatal exits
  • Chat focus ownership (#101): Rebuild focus from surviving state on transitions and render selected prompt choices in rust orange
  • Streaming invalidation and selection snapshots (#101): Refresh selection snapshots on redraw and protect active streaming assistant in cache budgeting
  • Session state reset at authority boundaries (#101): Scope async responses to the active session epoch and discard stale results
  • Persisted authority reconciliation (#101): Rederive trust state from current cwd on reconnect and clear stale session identity on failure boundaries
  • Tool index rebuilds and multi-index sync (#101): Gate scope updates on successful lookup and normalize interaction queues to prevent stale prompt drops
  • Display-width-aware copy (#101): Slice copied text by display columns so emoji, CJK, and combining marks match visual selection
  • Esc cancel and queued submit lifecycle (#101): Clear deferred submit on Esc and let manual cancel override auto-resubmit

Performance

  • Offscreen row skip and wrapped-height culling (#101): Render from the first visible message’s structural offset and use exact wrapped row coverage for culling

[0.8.4] - 2026-03-23 Changes

Fixes

  • Chat bottom-height drift: Stop rendering and measuring the trailing separator row after the final chat message so auto-scroll no longer lands on a persistent empty line beneath the last Claude response; add regression tests for last-message rendering and height measurement

[0.8.3] - 2026-03-23 Changes

Performance

  • Unified layout invalidation and progressive remeasure (#98): Replace the dirty_from suffix watermark with per-message staleness tracking, separated prefix-sum dirtiness, and a visible-first remeasure plan; preserve scroll anchors across in-flight resize and global remeasure replacement; single-message updates do exact changed-message remeasure plus targeted prefix repair instead of invalidating the entire suffix
  • Incremental history retention accounting (#98): Cache per-message retained-byte estimates and maintain a rolling total so retention enforcement stops rescanning the full message list every cycle; cache tool raw_input byte estimates to avoid repeated JSON serialization in hot paths
  • Incremental render cache budget (#98): Replace per-frame full cache budget scans with incremental slot metadata, rolling byte totals, and a pre-sorted eviction set rebuilt only when over budget
  • Derive tool collapse state at render time (#98): Remove per-tool collapsed field; tools_collapsed is the session-level source of truth read at render time so Ctrl+O no longer walks and mutates every tool-call block
  • Index terminal tool-call refs (#98): Replace linear duplicate checks on terminal subscriptions with a HashSet membership index; route attach, detach, and rebuild through shared tracking helpers

Dependencies

  • Bump aws-lc-sys from 0.38.0 to 0.39.0 and aws-lc-rs from 1.16.1 to 1.16.2 (fixes RUSTSEC-2026-0044, RUSTSEC-2026-0048)
  • Bump rustls-webpki from 0.103.9 to 0.103.10 (fixes RUSTSEC-2026-0049)
  • Bump pulldown-cmark from 0.13.1 to 0.13.3 (#97)

[0.8.2] - 2026-03-18 Changes

Fixes

  • Startup service status handling: Keep startup Claude service warnings and errors as transcript messages only; status errors no longer clear the draft or block users from trying a request during partial or uneven outages

[0.8.1] - 2026-03-18 Changes

Fixes

  • Startup session settings propagation: Pass configured model and defaultPermissionMode through the SDK’s top-level session startup options so new sessions start with the expected live model and permission mode instead of falling back to provisional defaults
  • Welcome banner model sync: Keep the welcome banner and header aligned through Connecting..., provisional default, and the first authoritative model update; freeze the welcome banner once the session model is resolved while allowing the header to continue tracking live model changes
  • Claude status relevance filtering: Query the status summary endpoint and only surface startup warnings for Claude Code and Claude API, avoiding false-positive outage banners caused by unrelated Anthropic components
  • Config cleanup: Remove obsolete MCP callback overlay code and stale config UI expectations left behind by the MCP management changes

[0.8.0] - 2026-03-17 Changes

Features

  • Agent SDK 0.2.74 migration (#83): Upgrade from SDK 0.2.63 to 0.2.74; inline session settings replace per-flag overrides; agent progress summaries rendered in task tool-call bodies; model capability badges (adaptive thinking, fast mode, auto mode) shown in settings overlay
  • AskUserQuestion support (#83): Dedicated question/response bridge path with horizontal and vertical option layouts; multi-select state tracking; inline annotation editing; question progress indicator; shared focus cycling infrastructure with permissions
  • MCP management tab (#89): Live MCP server list with connection status indicators and tool counts; /mcp slash command; server detail overlay with context-aware actions (reconnect, toggle, authenticate, clear auth); OAuth authentication flow with browser launch and manual callback URL entry; elicitation support for URL-based and form-based modes; stale status revalidation with 30-second cooldown auto-reconnect
  • Usage tab with quota visualization (#88, closes #87): Dual-source fetching (OAuth API first, CLI fallback); gauge bars with color-coded utilization (green/yellow/red); 5-hour, 7-day, and per-model quota windows; extra credits panel; /usage slash command and r manual refresh; 30-second TTL caching; OAuth credential expiry validation
  • Plugin management (#85): Three-section Plugins tab (Installed, Marketplace, Marketplace Sources) with CLI-backed operations; install/enable/disable/update/uninstall actions via overlay dialogs; marketplace source add/remove with text input; MCP capability badges; /plugins slash command; 5-second inventory cache with background refresh
  • Status tab and /status command (#80): Session, account, model, and settings information display; lazy account snapshot fetching via SDK; login method labels (Claude Max, API key variants); session name resolution with custom title/summary/prompt fallback chain; memory path and active setting sources display
  • Unified syntax highlighting (#84): Replace ansi-to-tui with syntect for theme-aware coloring across shell commands, code blocks, and terminal output; ANSI escape stripping state machine; automatic raw unified diff detection and semantic coloring; language-aware code highlighting with extension-based syntax detection
  • Session management enhancements (#83): Repository-scoped session discovery with worktree inclusion; session rename and AI-generated title actions in Status tab; text overlay for rename input with immediate visual feedback
  • Tool output metadata (#83): Structured metadata for Bash (assistant-backgrounded badge, token-saver state), ExitPlanMode (ultraplan badge), TodoWrite (verification-needed badge), and Write/Edit (git repository labels in diff headers); MCP resource content typing with URI, MIME type, and blob saved-path hints

Fixes

  • Paste-handled Enter suppression (#83): Treat paste-handled Enter as fully consumed in key dispatch; prevent suppressed paste newlines from falling through to non-char cleanup; restores inline multiline paste insertion for sub-1000 character payloads
  • Bell notification fallback (#83): Restore bell alongside desktop notifications on terminals without OSC 9 support; keep auto notification routing aligned with pre-settings behavior

UI

  • Config tab activation helper (#88): Centralized activate_tab function for consistent tab-switch behavior across /plugins, /status, /usage, /mcp, and keyboard navigation
  • Shared text input widget (#85): Reusable text_input_line() and render_text_input_field() components used by Language, Session Rename, and Add Marketplace overlays
  • Setting stepping (#85): Left/Right arrow editing for enum settings (Theme, Notifications, EditorMode, DefaultPermissionMode) in config view

Performance

  • Progressive resize height recomputation (#90): Replace synchronous full-remeasure on terminal width change with frame-budgeted progressive convergence; scroll anchor preservation across resize; per-message exactness tracking with expanding measurement frontiers around the visible window; measurement budget of max(12, viewport_height) messages and max(256, viewport_height * 8) wrapped lines per frame
  • Background file walker for mentions (#81): Replace synchronous BFS with ignore crate WalkBuilder on a background thread; query refinement refilters from cache instead of restarting the walk; pre-computed lowercase path variants eliminate per-sort allocation; bounded channel (1024 entries) with 500-entry drain budget per tick
  • Input redraw and cache optimization (#82): Split input versioning into cursor-only and content epochs; syntax highlighting and height measurement caches keyed on content version; key handlers return visibility signals to suppress redraws for non-visual events; Windows paste burst jitter tolerance in pending confirmation window
  • Background bash terminal detachment (#86): Detach terminal references when Bash tools reach completed or failed state; skip polling for non-running tools; prevent late bridge progress updates from reopening finalized tools; clear execute terminal references during forced tool finalization
  • Dev/test profile tuning (#83): Line-tables-only debug info and disabled incremental builds for faster compilation

Licensing

  • Apache-2.0: Switch project license from AGPL-3.0-or-later to Apache-2.0; SPDX single-line identifiers replace full header blocks across all source files

CI and Dependencies

  • Bump @anthropic-ai/claude-agent-sdk from 0.2.63 to 0.2.74 (#83)
  • Replace ansi-to-tui with syntect 5.3.0 (#84)
  • Bump tui-textarea-2 from 0.10.1 to 0.10.2 (#82)
  • Add version comparison to release dry-run workflow to skip unchanged versions (#82)

[0.7.1] - 2026-03-12 Changes

Fixes

  • npm rollback for installs and releases: Revert active package manager guidance, package scripts, and GitHub release workflows from pnpm back to npm; runtime reinstall guidance now recommends npm install -g
  • Leading blank row before Claude text: Trim leading rendered blank rows before the first visible assistant text block while preserving paragraph spacing for later content
  • Deferred Enter submit stability: Plain Enter now snapshots and restores the exact draft instead of mutating the input before submit, fixing hidden newline leaks when the cursor is in the middle of the text

[0.7.0] - 2026-03-12 Changes

Features

  • Native /login and /logout commands (#67): Shell out to claude auth login/logout with TUI suspend/resume; credential verification reads ~/.claude/.credentials.json directly; skip redundant operations when already authenticated or not authenticated
  • User settings system (#74): 14 persisted settings across three JSON files (~/.claude/settings.json, <project>/.claude/settings.local.json, ~/.claude.json); metadata-driven two-column config view with compact narrow-terminal fallback; toggle/cycle/overlay mutation with immediate persistence
  • Workspace trust (#74): Startup gated on per-project trust acceptance; path normalization for Windows drive letters, UNC paths, and symlinks; trust state persisted in ~/.claude.json
  • Session launch settings (#74): Saved preferences (model, language, permission mode, thinking mode, effort level) propagate into every new session via SessionLaunchSettings; available models flowed back from SDK for dynamic UI
  • Cancel-and-resubmit (#68): Submitting while the agent is running cancels the current turn and auto-resubmits once ready; draft stays visible and editable throughout with cancellation spinner banner
  • Desktop and bell notifications (#68, #74): NotificationManager tracks terminal focus via DECSET 1004; fires bell + OS-native desktop toasts on permission requests and turn completion when unfocused; channel-based delivery (disabled, bell, OSC 9, desktop) driven by user preference
  • Compaction overhaul (#68): /compact keeps chat history and appends a success system message after the turn completes; input and keyboard blocked during compaction; auto-compaction clears silently without a banner
  • Cache observability (#69): CacheMetrics accumulator with rate-limited structured tracing; warn-level alerts for high utilization and eviction spikes with cooldown; integration test suite covering the full stream-to-split-to-measure-to-prefix-sums pipeline
  • Unified textarea input (#70): Replace snapshot-based input state plus shadow editor with one persistent TextArea as source of truth; fixes wrapped visual-row cursor navigation; & subagent autocomplete now eager, matching @ and / behavior
  • Incremental mention search (#74): Replace repeated full rescans with incremental BFS (400 entries/tick budget) and 4-tier ranking; .gitignore awareness with global, local, and nested rule support; search threshold lowered from 3 characters to 1

Fixes

  • Permission allow_always persistence (#68, #71): Synthesize persistent addRules fallback when the SDK omits suggestions, fixing silent degradation to one-time allow; allow_always fallback now persists to localSettings
  • Paste burst reliability (#71): Reworked burst detection into a timing-based state machine (Idle/Pending/Buffering) with idle flush; retro-capture cleanup for leaked leading characters; enter suppression during and immediately after paste; CRLF normalized to LF in insert_str
  • Bridge reject_once match arm (#68): Added missing match arm that caused spurious warning logs on every permission prompt

UI

  • Help panel keyboard navigation (#67): Up/Down scroll and selection for Slash Commands and Subagents tabs; dynamic visible-item computation from wrapped text heights; fixed panel height across tabs; orange highlight for selected item
  • Paragraph gap preservation (#74): TextBlock state with trailing spacing metadata preserves paragraph gaps in chat rendering
  • Built-in slash entries (#74): /config, /login, /logout appear in slash help and autocomplete
  • Input blocking during async commands (#67): General CommandPending status with dynamic spinner text used by /login, /logout, /mode, /model, /new-session, /resume

Performance

  • Capacity-based byte accounting (#69): Replace heuristic message sizing with IncrementalMarkdown::text_capacity measurement
  • Protected-bytes tracking (#69): Non-evictable streaming-tail blocks excluded from eviction targets in render budget enforcement
  • Layout invalidation consolidation (#69): InvalidationLevel enum and invalidate_layout helper replace ad-hoc invalidation across event flows

Refactoring

  • Codebase split (#68): ui/tool_call.rs, app/connect.rs, app/slash.rs, app/state.rs, app/events.rs split into submodule directories (4-9 files each); bridge.ts split into 8 files under bridge/; all public APIs preserved via re-exports
  • Usage pipeline removal (#68): Delete entire usage_update pipeline (bridge/usage.ts, UsageUpdate types, session/message token tracking, footer cost display) across TypeScript and Rust
  • Input state unification (#70): Remove rebuild/sync debt from snapshot-based input; route all input reads/writes through accessor + replace flows on a single TextArea instance

CI and Dependencies

  • Bump uuid from 1.21.0 to 1.22.0 (#72)
  • Bump which from 8.0.0 to 8.0.2 (#73)
  • Switch tui-textarea-2 from local path dependency to crates.io 0.10.1 (#70)
  • Switch remaining npm command surfaces to pnpm across workflows, docs, and scripts (#74)

[0.6.0] - 2026-03-03 Changes

Features

  • Agent SDK 0.2.63 migration (#64): Upgrade from SDK 0.2.52 to 0.2.63; align bridge, wire types, and session APIs with the new SDK surface
  • Fast mode support (#64): Wire fast mode state end-to-end from bridge to TUI; footer badge shows FAST or FAST:CD during cooldown; deduplicated state change emission
  • Rate limit updates (#64): Parse and display rate limit events with readable user-facing summaries including overage and reset timing
  • Available agents and subagent autocomplete (#64): Wire available_agents_update across bridge and rust layers; & ampersand autocomplete for subagents; new Subagents help tab with two-column layout
  • Session resume via SDK-native APIs (#64): Replace legacy JSONL parsing with resume_session backed by listSessions and getSessionMessages; align to SDK session metadata fields
  • Interactive plan approval (#61): Intercept ExitPlanMode and render structured Approve/Reject widget with arrow navigation, y/n quick shortcuts, and allowedPrompts display
  • Write diff capping (#61): Truncate Write tool diffs exceeding 50 lines to head/tail window with omission marker; auto-scroll on oversized writes; plan files exempted
  • Startup service status checks (#65): Query status.claude.com during startup; emit warning or error system messages; lock input on outage-level errors
  • Subagent thinking indicator (#60): Debounced (1500ms) idle indicator between subagent tool calls to avoid flicker; suppress normal spinner when subagent indicator is active
  • System message severity levels (#64): Replace SystemWarning with MessageRole::System plus Info/Warning/Error severity with matching label colors
  • Slash command output in transcript (#64): Local slash command results now surface in assistant transcript

Fixes

  • Context percentage formula (#61): Exclude output_tokens from context calculation – Anthropic input formula is cache_read + cache_creation + input only; context % now updates as soon as input_tokens arrive
  • Stale task scope cleanup (#65): Clear active_task_ids on tool scope reset to prevent subagent misclassification after cancelled tasks
  • Subagent indicator false positives (#65): Gate thinking indicator on active spinner state to prevent false idle rendering
  • SDK rejection sanitization (#65): Harden bridge rejection replacement with exact and known-prefix matching only on failed tool results
  • Saturating coordinate math (#65): Use saturating arithmetic for header, input, autocomplete, and todo padding to prevent overflow panics

UI

  • Footer module extraction (#61): Move all footer logic into dedicated src/ui/footer.rs; clean up imports in mod.rs
  • Autocomplete stabilization (#61): Stable popover width; shift left near right edge; UTF-8-safe case-insensitive highlight ranges
  • Help overlay improvements (#64): Add subagents tab; move tab-switch hint into help title; rename footer hint from “Shortcuts + Commands” to “Help”

Refactoring

  • Handler decomposition (#61): Split large connection/event/key/slash/message handlers into smaller helpers; remove clippy::too_many_lines suppressions; FocusContext builder-style API

CI and Dependencies

  • Bump actions/upload-artifact from 6 to 7 (#62)
  • Bump actions/download-artifact from 7 to 8 (#63)
  • Migrate from npm package-lock.json to pnpm pnpm-lock.yaml in agent-sdk (#64)

[0.5.1] - 2026-02-27 Changes

Fixes

  • Input smoothness during rapid keys: Restore frame rendering during non-paste active key bursts by narrowing suppression to confirmed paste bursts only; preserves paste placeholder anti-flicker behavior

[0.5.0] - 2026-02-27 Changes

Features

  • Paste handling overhaul (#53): Character-count threshold (1000 chars) replaces line-count; placeholder label updated; session identity tracking prevents append across separate pastes; burst finalization scoped to newly pasted range only
  • Turn error classification (#54): TurnError strings matched against known patterns (rate limit, plan limit, max turns, quota, 429); actionable recovery hint pushed as a system message in chat; unclassified errors preserve existing behavior

Fixes

  • Typed AppError enum (#54): NodeNotFound, AdapterCrashed, AuthRequired, ConnectionFailed, SessionNotFound variants with per-variant exit codes and user-facing messages

Performance

  • Unified cache budgeting + LRU history retention (#52): Single cache budget across all message blocks; LRU eviction for long sessions; reduces memory growth on extended conversations

UI

  • Footer three-column layout: Update hint and context percentage now render in separate right-aligned columns simultaneously instead of either-or

[0.4.1] - 2026-02-27 Changes

Fixes

  • Dynamic bridge log levels (client.rs): Bridge stderr lines are now routed to the correct tracing level – [sdk error]/panic lines go to error!, [sdk warn] lines to warn!, and ordinary SDK chatter to debug! – instead of unconditionally emitting error! for every line
  • Height cache invalidated on interruption (events.rs): TurnComplete and TurnError now call mark_message_layout_dirty on the tail assistant message so the height cache is re-measured after a cancelled or failed turn, fixing stale layout after interruption

[0.4.0] - 2026-02-27 Changes

Features

  • Agent SDK migration (#45, closes #23): Replace @zed-industries/claude-code-acp with the in-repo Agent SDK bridge; align permission suggestions with SDK session/always-allow scope
  • Session resume (#46, closes #22): --resume is cwd-aware and restores full transcript state; input locked while resuming; recent sessions shown in welcome context
  • Token and cost tracking (#47, closes #21): Footer shows live Context: XX%; assistant turns show per-turn (Xk tok / $X.XX); compaction spinner during SDK-reported compaction
  • Slash command popovers and AskUserQuestion (#48): Variable-input slash commands show dynamic argument popovers; full AskUserQuestion flow with option rendering and answer propagation

Fixes

  • TodoWrite flicker (#45): Ignore transient payloads without a todos array so the list no longer clears and reappears mid-turn
  • Failed Bash rendering (#45): Compress failed tool output to a single exit-code summary line instead of the full stderr dump
  • Ctrl+C determinism (#46): Copy only when selection is non-empty and clear it after; otherwise quit
  • Submission pipeline (#47): Single queue gate for submissions; cancel active turn before dispatching queued action; wait for turn-settle before ready
  • Persisted tool-result normalization (#48): Strip leading box-drawing prefixes from tool result summaries

Performance

  • Streaming frame cost (#49): Generation-keyed tool call measurement cache with O(1) fast path; terminal output delta-append; skip invalidation for no-op updates

Internal

  • Agent SDK bridge modularized into focused modules (commands.ts, tooling.ts, permissions.ts, usage.ts, history.ts, auth.ts, shared.ts) (#48)
  • Perf instrumentation markers for key invalidation, measurement, and snapshot paths (#49)

[0.3.0] - 2026-02-25 Changes

Features

  • Startup update check (#30): Non-blocking check via GitHub Releases API with 24h cache, footer hint, Ctrl+U dismiss, --no-update-check / CLAUDE_RUST_NO_UPDATE_CHECK=1 opt-out
  • Shortcuts during connecting (#38): Navigation and help shortcuts work while ACP adapter connects; input keys remain blocked
  • Global Ctrl+Q quit (#38): Safe quit available in all states including connecting and error
  • Input height API and word wrapping (#40): Adopt tui-textarea-2 v0.10 TextArea::measure() for input sizing, switch to WrapMode::WordOrGlyph, remove custom InputWrapCache plumbing

Fixes

  • Height cache recalculation (#39): Track dirty message index and re-measure non-tail messages when content or tool blocks change
  • Error state and input locking (#39): Connection and turn failures surface immediately with quit hint; input blocked during connecting/error
  • Scroll clamp after permission collapse (#39): Clamp overscroll when content shrinks; ease scroll position for smooth settling; consume Up/Down with single pending permission
  • Permission shortcut reliability (#29): Ctrl+Y/A/N work globally while prompts are pending with fallback option matching
  • Tool-call error rendering (#29): Improved error handling with raw_output fallback and cleaner failed-call display

CI and Dependencies

  • Bump actions/upload-artifact 4 to 6, actions/setup-node 4 to 6, actions/download-artifact 5 to 7 (#31, #32, #33)
  • Bump pulldown-cmark from 0.13.0 to 0.13.1 (#34)
  • Unify cargo publish, binary build, GitHub release, and npm publish into one workflow (#30)
  • Add revert to allowed semantic PR title types (#37)

Internal

  • Attempted migration to claude-agent-acp (#29), reverted to claude-code-acp (#37) due to feature parity gaps
  • Regression tests for height remeasurement, scroll clamp, permission keys, connecting shortcuts, and update check

[0.2.0] - 2026-02-22 Changes

Rename and Distribution

  • Rename crate/package to claude-code-rust
  • Rename command to claude-rs
  • Update release workflows and artifacts to publish/build under the new names

[0.1.3] - 2026-02-21 Changes

Fixes

  • Rescan files on each @ mention activation so new/deleted files are reflected during a session
  • Add keywords to npm package.json for better discoverability

[0.1.2] - 2026-02-21 Changes

UX and Interaction

  • Add OS-level shutdown signal handling (Ctrl+C/SIGTERM) so external interrupts also trigger graceful TUI teardown
  • Keep in-app Ctrl+C key behavior for selection copy versus quit, while unifying shutdown through the existing cleanup path
  • Make chat scrollbar draggable with proportional thumb-to-content mapping
  • Ensure scrollbar dragging can reach absolute top and bottom of chat history

[0.1.1] - 2026-02-21 Changes

CI and Release

  • Replace release-plz with direct cargo and npm publish workflows
  • release-cargo.yml: publishes to crates.io on Cargo.toml version bump
  • release-npm.yml: builds cross-platform binaries, creates verified GitHub Release, publishes to npm with provenance
  • Triggers based on Cargo.toml version changes instead of tag chaining
  • Tags created by github-actions[bot] for verified provenance
  • Remove release-plz.toml and cliff.toml

[0.1.0] - 2026-02-20 Changes

Release Summary

Claude Code Rust reaches a strong pre-1.0 baseline with near feature parity for core Claude Code terminal workflows:

  • Native Rust TUI built with Ratatui and Crossterm
  • ACP protocol integration via @zed-industries/claude-code-acp
  • Streaming chat, tool calls, permissions, diffs, and terminal command output
  • Modern input UX (multiline, paste burst handling, mentions, slash commands)
  • Substantial rendering and scrolling performance work for long sessions
  • Broad unit and integration test coverage across app state, events, permissions, and UI paths

The only major parity gap intentionally excluded from this release is token/cost usage display because the upstream ACP adapter currently does not emit usage data.

Architecture And Tooling

  • Three-layer runtime design:
    • Presentation: Rust + Ratatui
    • Protocol: ACP over stdio
    • Agent: Zed ACP adapter process
  • Async runtime and event handling:
    • Tokio runtime with ACP work kept on LocalSet (!Send futures)
    • mpsc channels between ACP client events and UI state machine
  • CLI and platform support:
    • Clap-based CLI (--model, --resume, --yolo, -C, adapter/log/perf flags)
    • Cross-platform adapter launcher fallback (explicit path, env path, global bin, npx)
    • Windows-safe process resolution via which

Core Features

  • Chat and rendering:
    • Native markdown rendering including tables
    • Inline code/diff presentation and tool-call block rendering
    • Welcome/system/tool content unified in normal chat flow
  • Input and commands:
    • tui-textarea-2 powered editor path
    • Multiline paste placeholder pipeline and burst detection
    • @ file/folder mention autocomplete with resource embedding
    • Slash command workflow with ACP-backed filtering and help integration
  • Tool execution UX:
    • Unified inline permission controls inside tool-call blocks
    • Focus-aware keyboard routing for mention, todo, and permission contexts
    • Better interruption semantics and stale spinner cleanup
    • Internal ACP/adapter failures rendered distinctly from normal command failures
  • Session and app UX:
    • Parallel startup (TUI appears immediately while ACP connects in background)
    • In-TUI connecting/auth failure messaging and login hinting
    • Header model/location/branch context
    • Help overlay and shortcut discoverability improvements
    • Mouse selection and clipboard copy support
    • Smooth chat scroll and minimal scroll position indicator

Performance Work

Performance optimization was a major release theme across recent commits:

  • Block-level render caching and deduplicated markdown parsing
  • Incremental markdown handling in streaming scenarios
  • Prefix sums + binary search for first visible message
  • Viewport culling for long-chat scaling
  • Ground-truth height measurement and improved resize correctness
  • Conditional redraw paths and optional perf diagnostics logging
  • Additional targeted UI smoothing for scroll and scrollbar transitions

Reliability, Quality, And Tests

  • Significant test investment across both unit and integration layers
  • Current codebase includes over 400 Rust #[test] cases
  • Dedicated integration suites for ACP events, tool lifecycle, permissions, state transitions, and internal failure rendering
  • CI includes test, clippy (-D warnings), fmt, MSRV, and lockfile checks

Release And Distribution Setup

  • Rust crate is now publish-ready for crates.io as claude-code-rust
  • CLI executable name is claude-rs
  • npm global package added as claude-code-rust:
    • installs claude-rs command
    • downloads matching GitHub release binary during postinstall
  • Tag-based GitHub Actions release workflow added for:
    • cross-platform binary builds (Windows/macOS/Linux)
    • GitHub release asset publishing
    • npm publishing (when NPM_TOKEN is configured)
  • release-plz remains in place for release PR automation and changelog/version workflows

Known Limitations

  • Slash command availability is intentionally conservative for this release:
    • /login and /logout are not offered
    • they remain excluded until ACP/Zed support is reliable enough for production use
  • Token usage and cost tracking is blocked by current ACP adapter behavior:
    • UsageUpdate events are not emitted
    • PromptResponse.usage is None
  • Session resume (--resume) is blocked on an upstream adapter release that contains a Windows path encoding fix