claude-code
Toolog keeps a forensic log of Claude Code tool calls
Claude News
claude-codeToolog captures every shell command, file edit and network fetch Claude Code runs on macOS and writes it into an embedded SQLite database, joining two collection lanes because the OTEL exporter truncates tool inputs at 512 characters. The project, published on Github and posted to Show HN, ships as one signed application and keeps everything on the machine.
At a glance
- Two lanes feed the store: an OTLP receiver bound to 127.0.0.1:47318 records who approved or refused each call, and a file watcher tails ~/.claude/projects for the untruncated command and diff.
- Twelve deterministic rules assign severity, and an optional local 4.6B quantized model, a 3.1 GB download against a 166 MB store, scores the calls no rule matched, in a separate column.
- The author reports 77% of his own store was Bash commands no rule had ever matched, reported as nothing, which reads as approval but means those calls were never examined.
Agent runtimes have outpaced the record of what they actually executed: once a terminal session scrolls away, the commands and file edits Claude Code ran are gone, along with the decision that let them through. Toolog reads as an attempt to make that record auditable without adding a network dependency, and the design leans on build-time checks rather than assurances, which likely matters more to teams that need evidence than to individual users.
The app makes no network calls beyond a receiver bound to 127.0.0.1:47318
Toolog is a universal build signed with a Developer ID and notarized by Apple, installed with brew install --cask zaghaghi/tap/toolog or from a .dmg in Releases. The same binary is the menu-bar app and the CLI: toolog doctor --fix configures Claude Code telemetry, and toolog backfill imports existing history.
There is no analytics, no crash reporting, no remote config, no account and no update check, with brew upgrade --cask toolog as the update path instead. A CI test runs a full ingest and every query the window issues, then asks the operating system which sockets the process holds; any address that is not loopback fails the build.
A second test opens a socket pointed off the machine and asserts the census sees it. Because toolog links llama.cpp, whose own --hf-repo fetcher a check reading Cargo.toml cannot see, the release also asserts that otool -L on the shipped binary lists no libcurl and no TLS library.
OTEL truncates tool inputs at 512 characters, so a transcript tailer supplies the full text
Transcripts carry the untruncated content, the full shell command and the full file diff, while the OTEL lane carries what transcripts never record: who approved or refused each call, under which rule, and how long it took. The two are joined exactly on tool_use_id.
Where the lanes disagree, toolog treats the difference as a finding: a call only the transcript saw is a gap in collection, and a call only OTEL saw had no transcript body written. Neither lane sits on Claude Code's critical path, one being a read-only file watch through fsevents and the other a fire-and-forget export whose failure costs nothing.
The stored calls, in SQLite with WAL and FTS5, are exposed through three views: a timeline newest first under a single query box, a permission and risk review, and the state of capture. Queries such as @risk:high and @model-risk:>=4 filter by rule severity and by model score.
An optional 4.6B quantized model reads the calls no rule matched
Twelve rules evaluate each call and are shown worst first, with what each one looks for whether or not it matched. Calls that match no rule are reported as nothing, and pointing toolog at a local .gguf file gives them a one-line reading of what each was doing.
The model output is never a rule, never a severity and never a number in the summary: it gets its own column, its own section and its own block in the detail pane. toolog model set points at a .gguf and never downloads one.
The author states the model is wrong sometimes: on his own store the 4.6B quantized model scored a benign cargo test at 2 and needed its rubric spelled out before it called a raw-device dd dangerous. The author gives that as the reason it is opt-in, advisory and kept visibly apart from the rules, a 3.1 GB dependency against a 166 MB store.
The limitations the readme states
macOS 11 or later, and macOS only; only the LaunchAgent assumes the platform, so a port would need a systemd user unit for both install and uninstall. Decisions and latency exist only for sessions captured live, because the OTEL lane is not replayable, and toolog verify reports which sessions those are. api_request records are stored and counted while no spend or token figure is shown, which the author calls a scope decision rather than an omission.
Comments
No comments yet. Be the first.
Join the conversation
Sign in with Google to leave a comment. Your name and avatar come from your Google profile, and the comment appears after moderation.
We only use your name and avatar from Google. We never store your email address.
