Diagnostics & Logging
Claudette writes structured, daily-rotated logs to disk so user-reported bugs can be reconstructed from the file alone — without needing the user to reproduce while the app is attached to a debugger. The pipeline is on by default in every build.
Where logs live
Section titled “Where logs live”The default log directory is ~/.claudette/logs/ (sibling to ~/.claudette/workspaces and ~/.claudette/plugins). Files are named claudette.<YYYY-MM-DD>.log (the tracing-appender layout is <prefix>.<date>.<suffix>) and rotate daily. A startup retention sweep deletes anything older than 14 days so the directory never grows unbounded.
You can override the location with the CLAUDETTE_LOG_DIR environment variable — handy when running multiple dev instances side-by-side and you want each one’s logs in its own folder.
Every log line carries the process PID, so even when two Claudette instances share the same daily file you can demux by grep pid=NNN.
Settings → Diagnostics
Section titled “Settings → Diagnostics”The Diagnostics section in Settings (between Editor and Git) gives you three controls without ever needing to touch an environment variable.
Log level
Section titled “Log level”Restart-required filter applied to the file log when RUST_LOG is unset. Choose:
| Level | Captures |
|---|---|
default | info overall plus debug for Claudette’s own crates, with mdns_sd capped at warn — the shipping default |
warn | warnings and errors only |
info | startup, shutdown, every Tauri command lifecycle event |
debug | the above plus Claudette debug events and span timings for slow ops (DB migrations, git fetches, diff parsing, agent spawns) |
trace | maximum Claudette detail; not recommended for normal use |
The in-app selector scopes coarse levels to Claudette’s own crates and keeps dependencies below debug/trace. It also caps mdns_sd at warn so mDNS packet chatter does not flood the daily log.
If RUST_LOG is set in the process’s environment, this select is locked and a banner explains why — RUST_LOG always wins so the env var workflow is preserved.
Frontend log verbosity
Section titled “Frontend log verbosity”How much of the React side’s console.* output is mirrored into the daily log. Takes effect immediately, no restart needed.
| Verbosity | Mirrored sources |
|---|---|
| Errors only (default) | uncaught browser errors, promise rejections, React error-boundary catches, console.error |
| Errors + warnings | the above plus console.warn |
| Everything | the above plus console.log and console.info |
Browser-side uncaught errors and unhandled promise rejections are always captured, regardless of verbosity — only the explicit console.* calls are gated. React’s StrictMode warnings are forwarded under “Errors + warnings” if you need to see them in the file log.
Open Logs Folder / Copy path
Section titled “Open Logs Folder / Copy path”Two buttons. The first reveals the log directory in your file manager (Finder on macOS, the system handler on Linux/Windows). The second copies the path to your clipboard — useful for pasting into a bug report.
Filtering verbosity by domain
Section titled “Filtering verbosity by domain”When investigating a specific subsystem, use a per-domain RUST_LOG filter rather than turning every domain up to trace. RUST_LOG is honored verbatim, so it can still enable dependency targets when you deliberately need them. Every event in Claudette is emitted under a claudette::<domain> target:
# Only chat lifecycle eventsRUST_LOG=claudette::chat=trace cargo tauri dev
# Chat plus MCP supervisionRUST_LOG=claudette::chat=trace,claudette::mcp=debug cargo tauri dev
# Everything from the React webviewRUST_LOG=claudette::frontend=trace cargo tauri devEstablished domains:
| Target | Covers |
|---|---|
claudette::startup | process boot, paths, multi-instance warning |
claudette::panic | Rust panic hook output (with backtrace) |
claudette::db | database open, migrations, and compaction |
claudette::chat | turn lifecycle, persistent session reuse / respawn |
claudette::agent | Claude CLI subprocess events |
claudette::backend | alternative-provider gateway |
claudette::mcp | MCP supervisor and server registration |
claudette::plugin | Lua plugin runtime + Claude-Code marketplace |
claudette::git | git CLI shellouts |
claudette::diff | diff parsing |
claudette::scm | PR / CI provider plugin invocations |
claudette::pty | terminal spawn / exit |
claudette::voice | Whisper / Speech.framework |
claudette::ws | WebSocket server (remote workspaces) |
claudette::ipc | local CLI ↔ GUI socket |
claudette::remote | remote-control commands |
claudette::ui | theme load, settings persistence |
claudette::frontend | events forwarded from the React webview |
claudette::updater | update checks, boot probation, and rollback |
Voice click→prompt latency
Section titled “Voice click→prompt latency”Every mic click logs a structured event on the claudette::voice target so the time between clicking the mic and the recorder opening is visible in the daily log. The event fires whether the start succeeded or not:
- Success — info level,
provider_id,total_ms(full command duration), andstream_open_ms(just the cpal input-stream open). - Failure — error level, with the propagated error string (permission denied, model missing, recorder open failure, already-active recording, etc.) on the same target.
2026-05-08T17:32:14.123Z INFO claudette::voice voice_start_recording{provider_id=apple-speech total_ms=312 stream_open_ms=308}: voice start recording latencyTo watch in real time, tail the daily log file (path under Settings → Diagnostics → Open log directory) or run with RUST_LOG=claudette::voice=info cargo tauri dev. Useful when filing a bug report about voice startup feeling slow — copy the matching line into the report and the relevant timings are right there.
There is no cold/warm dimension on the event because Claudette intentionally does not prewarm voice subsystems at launch (this keeps macOS from showing an unprompted microphone permission dialog on boot). Treat every click as a cold start.
File format
Section titled “File format”Logs default to a compact text format (one event per line, with a tab-separated key=value tail of structured fields):
2026-05-08T17:32:14.123Z INFO claudette::chat send_chat_message{chat_session_id=4f… workspace_id=ws-abc…}: turn dispatchedFor machine-parseable output set CLAUDETTE_LOG_FORMAT=json before launching — every event becomes a JSON line, which is friendlier to jq post-mortems:
CLAUDETTE_LOG_FORMAT=json cargo tauri dev# Later:jq 'select(.target=="claudette::chat" and .level=="ERROR")' \ ~/.claudette/logs/claudette.2026-05-08.logDatabase compaction on upgrade
Section titled “Database compaction on upgrade”Claudette stores app state in claudette.db under the OS data directory (~/Library/Application Support/claudette/ on macOS, $XDG_DATA_HOME/claudette/ on Linux, and %APPDATA%/claudette/ on Windows unless CLAUDETTE_DATA_DIR overrides it).
Older builds left SQLite auto-vacuum disabled, so deleting checkpoint snapshots could free pages inside SQLite without shrinking the database file on disk. The first launch of a build with database compaction may run a one-time SQLite VACUUM to apply incremental auto-vacuum and reclaim those stranded pages. For very large databases, startup can pause while that rewrite finishes. Other database connections wait up to 30 seconds for the maintenance lock before retrying on a later open.
After conversion, routine database opens only check that the compaction mode is in place. High-churn delete paths, such as checkpoint and workspace cleanup, run bounded incremental vacuum work after the delete commits. To inspect this lifecycle, filter logs for the claudette::db target.
Multiple dev instances
Section titled “Multiple dev instances”Claudette has no single-instance lock — running ./scripts/dev.sh twice gives you two independent processes against the same SQLite database. Logs from both instances interleave into the same daily file by default, demuxable via the pid=NNN field on every line.
If you’d rather isolate them, set CLAUDETTE_LOG_DIR to a per-instance path before launching. The dev launcher leaves this up to you so you can choose interleaved-in-one-file or separate-files based on what you’re investigating.
On startup, Claudette also scans ${TMPDIR}/claudette-dev/*.json (the discovery files scripts/dev.sh writes) and emits a WARN if another live PID is already running against the same DB path. The warning fires once at boot and explains exactly why it can corrupt persisted state — useful when an old instance lingers and you didn’t notice.
Update boot-health rollback
Section titled “Update boot-health rollback”After an in-app update, Claudette starts the new build on a short probation window (20 s by default). During that window Claudette records boot-stage breadcrumbs in the probation sentinel: process start, webview creation, React mount, initial workspace-data loading, and any initial-data load error. The React app sends the final boot heartbeat after the first commit past the loader (viewStateHydrated is true and loadInitialData resolved). If that heartbeat never arrives, Claudette treats the update as failed to start and tries to restore the previous self-contained install.
When rollback succeeds, the next launch shows a native dialog saying which version failed, which version was restored, and the last boot stage reached. Startup failures, initial workspace-load failures, and slow starts get different wording so the report starts from the right symptom. When rollback cannot be applied (for example, there was no usable previous-install backup or the install location could not be replaced), Claudette writes a no-loop failure report and shows a dialog with the failed version, the captured boot stage, and the release URL to download manually.
A force-quit during the probation window leaves the sentinel on disk; the next launch increments the attempt counter and treats attempts >= 2 as “this build runs” (the user already booted past the timer once), clears the sentinel, and skips arming the timer. This avoids spurious rollbacks on an otherwise healthy build whose user happens to quit during every probation window.
Backups under ~/.claudette/updates/previous/ are pruned to a single generation each time prepare_for_update runs, so the directory does not grow unbounded across updates.
Useful files for a rollback bug report:
| File | Meaning |
|---|---|
~/.claudette/updates/previous/<version>/ | Backup of the previous self-contained install, when one was available. |
OS data dir boot-probation.json | Internal sentinel for the update currently on probation. Cleared after a healthy boot. |
OS data dir boot-rollback-report.json | One-shot report consumed on next launch to show the native rollback dialog. Includes the failed boot stage, probation timeout, rollback execution error (if any), and a bounded tail of the failed build’s daily log. |
~/.claudette/logs/claudette.<DATE>.log | Structured timeline under the claudette::updater target. |
The OS data dir is ~/Library/Application Support/claudette/ on macOS, $XDG_DATA_HOME/claudette/ on Linux, and %APPDATA%/claudette/ on Windows unless CLAUDETTE_DATA_DIR overrides it.
Tuning the probation window
Section titled “Tuning the probation window”CLAUDETTE_BOOT_PROBATION_SECS overrides the default 20 s probation. Useful for slow first-launch scenarios (e.g. cold-cache Linux builds where libwebkit2gtk dynamic loading dominates startup time) and for shrinking the window while testing the rollback path locally. Values are clamped to the range 1–120 s; non-numeric values fall back to the default. Setting CLAUDETTE_BOOT_PROBATION_SECS=2 plus an artificial pre-render hang in the React tree is the recommended way to exercise the rollback dialog from a dev build.
Sandboxed (fresh-user) sessions
Section titled “Sandboxed (fresh-user) sessions”For testing first-run UX (the welcome card, onboarding, plugin seeding) you can launch Claudette with a completely empty data tree:
./scripts/dev.sh --new.\scripts\dev.ps1 --newThe flag points three env vars at a per-PID directory under ${TMPDIR}/claudette-dev/new-<pid>/ ($env:TEMP\claudette-dev\new-<pid>\ on Windows) and removes the tree on exit:
CLAUDETTE_HOMEoverrides the~/.claudette/tree (workspaces, plugins, themes, logs, models, packs).CLAUDETTE_DATA_DIRoverrides the OS data directory holdingclaudette.db.CLAUDE_CONFIG_DIRoverrides the Claude CLI’s~/.claude/tree, which Claudette reads and writes forsettings.json,.credentials.json, installed plugins, and marketplace registrations. Without this override, a--newrun that touches plugins or auth would write into the real~/.claude/and survive the sandbox tear-down — defeating the “simulate a new user” purpose of the flag.
Cloned (real-state) sessions
Section titled “Cloned (real-state) sessions”--clone is the inverse of --new: it pre-populates a stable sandbox dir (${TMPDIR}/claudette-dev/clone/) with an rsync -a --delete mirror of your real ~/.claudette/, claudette.db, and ~/.claude/, so the dev build inherits your existing workspaces, themes, plugins, and Claude credentials but writes to the sandbox copy rather than the originals. The sandbox is not a copy-on-write snapshot — rsync makes full copies (sized by source) and re-runs sync incrementally, only transferring changed files. The cloned claudette.db is rsync’d raw, so quit the release app before launching if you need a guaranteed-consistent DB snapshot. Mutually exclusive with --new. Currently macOS/Linux only — the PowerShell launcher doesn’t implement --clone.
Nuking stale sandboxes
Section titled “Nuking stale sandboxes”If a --new or --clone session is killed with SIGKILL it misses its cleanup trap and leaves a directory under ${TMPDIR}/claudette-dev/ behind. Run:
./scripts/dev.sh --clean.\scripts\dev.ps1 --cleanto wipe everything under ${TMPDIR}/claudette-dev/ ($env:TEMP\claudette-dev\ on Windows). This is a blunt nuke — no PID check, every new-<pid>/, clone-<pid>/, and <pid>.json is removed regardless of whether the owning process is still alive. If you have a dev session currently running, its sandbox is removed too and the dev app will start seeing missing files mid-session, so prefer to quit running dev instances first. The command exits after the sweep without launching the app.
You can also set any of these env vars manually for a longer-lived sandbox:
CLAUDETTE_HOME=/tmp/claudette-demo \CLAUDETTE_DATA_DIR=/tmp/claudette-demo/data \CLAUDE_CONFIG_DIR=/tmp/claudette-demo/claude \ ./scripts/dev.sh$env:CLAUDETTE_HOME = "$env:TEMP\claudette-demo"$env:CLAUDETTE_DATA_DIR = "$env:TEMP\claudette-demo\data"$env:CLAUDE_CONFIG_DIR = "$env:TEMP\claudette-demo\claude".\scripts\dev.ps1Filing a bug report
Section titled “Filing a bug report”- Reproduce the issue.
- Settings → Diagnostics → Copy path to grab the log directory.
- Open the most recent
claudette.<DATE>.log— that’s your timeline. - If you want fuller detail, switch the Log level to
debug, restart Claudette, reproduce, and the file log will include span timings + every command’s entry/exit fields. - Attach the relevant log file to the GitHub issue along with the reproduction steps.
The frontend-bridge default catches React render crashes and uncaught browser errors automatically, so the file log usually has enough context to triage even if you can’t reproduce on demand.