Diagnostic Logging
The --debug flag on the start command enables two things simultaneously:
-
Structured lifecycle logs — INFO-level events written to
.codescout/diagnostic-*.log, covering server startup, heartbeats, tool calls, and shutdown. Useful for diagnosing MCP disconnect and silence issues. -
Usage traceability — full
input_jsonandoutput_jsoncolumns written tousage.dbfor every tool call, enabling post-mortem replay of failures.
--diagnosticis a deprecated alias for--debugand will be removed in a future release.
Enabling
Pass --debug when starting the server:
codescout start --project /path/to/project --debug
Or, if using cargo run:
cargo run -- start --project . --debug
Log file
Each server instance writes to its own file:
.codescout/diagnostic-<4hex>.log
The <4hex> suffix is a random 4-character hex instance ID unique to that
process. Old files are rotated automatically: the 6 most recent
diagnostic-*.log files are kept by modification time; older ones are deleted
at startup.
What is logged
| Event | When | Fields |
|---|---|---|
codescout_start | Server boot | pid, version, project, transport, instance |
heartbeat | Every 30 s | uptime_secs, active_projects, lsp_servers |
tool_call | Tool invoked | tool, arg_keys |
tool_done | Tool returned | tool, duration_ms, ok |
service_exit | Shutdown | reason (signal name or quit reason) |
All events are INFO level and written in a structured format alongside the existing stderr INFO layer.
Reading the log
cat .codescout/diagnostic-*.log
# or tail the most recent:
ls -t .codescout/diagnostic-*.log | head -1 | xargs tail -f
When to use it
- MCP client disconnects silently —
service_exitcaptures the shutdown reason (SIGHUP, SIGTERM, pipe close, etc.). - Tool call hangs — compare
tool_callandtool_donetimestamps to find which tool never returned. - Heartbeat gaps — a missing heartbeat indicates the server process was suspended or killed.
- Reproduce a failure —
input_json+output_jsoninusage.dblet you replay a broken tool call at the exact codescout and project version that produced it.
Debug Mode Coverage
--debug is the single flag for all verbose/debug behavior:
| What | Output |
|---|---|
| Lifecycle events (start, heartbeat, tool call/done, exit) | .codescout/diagnostic-*.log (INFO, 6-file rotation) |
| Verbose internal state, LSP protocol traces | .codescout/debug.log (DEBUG level) |
| Full tool input/output JSON | usage.db input_json / output_json columns |
Usage Traceability
Every tool call in usage.db records these columns (always, regardless of debug mode):
| Column | Description |
|---|---|
codescout_sha | Git SHA of the codescout binary (baked at compile time) |
project_sha | Git HEAD of the active project at activation time |
session_id | UUID identifying this server session |
In debug mode, two additional columns are populated:
| Column | Populated when |
|---|---|
input_json | Always (in debug mode) |
output_json | Only on errors and recoverable errors |
Replay Workflow
To reproduce a failed tool call:
- Query
usage.dbfor the failure (see Reading the log above) git checkout <project_sha>— restore the project to its exact state- In the codescout repo:
git checkout <codescout_sha>+cargo build --release - Start codescout, activate the project, re-invoke the tool with the stored
input_json
Records are pruned after 30 days alongside normal usage records.
Limitations
- The instance ID (
<4hex>) is derived fromRandomStateseeded at process start — it is not a cryptographic or globally unique ID. - Log rotation is by mtime, not sequence number. If the filesystem does not update mtime reliably (some network filesystems), rotation order may be incorrect.
arg_keyslogs parameter names only, not values, to avoid capturing sensitive content in log files.project_shais captured once atworkspace(action: activate). If HEAD moves mid-session (e.g. a commit lands while the server is running), the stored SHA reflects the state at activation, not at call time — still a valid reproduction point.
Querying failed calls
To query failed calls with captured inputs from usage.db:
sqlite3 .codescout/usage.db \
"SELECT tool_name, input_json, codescout_sha, project_sha, called_at
FROM tool_calls
WHERE outcome != 'success' AND input_json IS NOT NULL
ORDER BY called_at DESC LIMIT 10;"
Sibling tables (non-codescout writers)
Other tools may add their own tables to your project’s .codescout/usage.db.
codescout does not write to or depend on them — they are sibling
observability surfaces that read tool_calls.
If you use the codescout-pika buddy specialist (a buddy plugin
specialist that watches codescout tool usage for Iron Law violations,
misuse, tool bugs, and recurring patterns), you will see a
pika_observations table created lazily on the first user-asked scan.
Schema, predicate matrix, and rationale are documented in
docs/superpowers/specs/2026-05-17-pika-observability-design.md.
The table is FK-anchored to tool_calls.id with ON DELETE CASCADE,
so observations die with their parent tool-call rows during the normal
30-day pruning — codescout requires no orphan cleanup.
Stale-when: Phase 2 of Pika observability ships a new schema version
(pika_schema_version > 1); update this section’s link to point at the
new spec.