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

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.