Retrieved article excerpt
Open article ยท Retrieved 2026-10-05T20:39:44.077626+00:00
# rashomon
**Your coding agent can tell you it finished the job. Did it actually?**
`rashomon` keeps an independent record of what your agent actually did, then
puts that record beside the agent's own account.
**[Join the Rashomon Discord](https://discord.gg/Qg3hybAHpU)**
*For Claude Code only, on macOS and Linux. Alpha: v1.1.0.*
[Claude says all tests pass; rashomon's end-of-turn line reports a recorded failure, and an excerpt of the report shows it](https://github.com/altrace-dev-role/rashomon/blob/main/docs/images/rashomon-example.png)
## In plain words
When Claude Code finishes a task, it tells you what it did: "Done, all tests
pass." That summary comes from the agent itself.
rashomon keeps its own record of every step the agent takes, like each command
it runs and each file it edits, and whether each one worked. It puts that record
beside the agent's summary: if a step failed and the closing message uses none
of rashomon's failure words, it tells you at the end of the turn. Every report
also lists what subagents did, which the main conversation does not show.
You keep working the way you do now. rashomon stays quiet unless something is
worth a look. The name comes from *Rashomon*, the film in which witnesses give
different accounts of the same event.
## Get started
Pick **one** of these two ways. Using both records everything twice.
**As a Claude Code plugin:**
```
claude plugin marketplace add altrace-dev-role/rashomon
claude plugin install rashomon@rashomon
claude plugin enable rashomon@rashomon
```
Then start a new Claude Code session. Inside it, `/rashomon:report` shows what
was recorded.
**From the command line** (macOS and Linux):
```
curl -fsSL https://raw.githubusercontent.com/altrace-dev-role/rashomon/main/install.sh | sh
rashomon watch
```
Then use `claude` as usual, and run `rashomon report` whenever you want to look.
The installer puts `rashomon` in `~/.local/bin`; if your shell cannot find it,
add that folder to your `PATH`.
## What you'll see
Most of the time, nothing: a turn with nothing worth a look prints nothing.
When something is off, one line appears at the end of the turn (or, if you
refused a permission prompt, when you send your next prompt, marked
`previous turn`):
```
โป rashomon: 1 recorded failure.
โ rashomon report --session <id>
```
With the plugin, the arrow points at `/rashomon:report --session <id>` instead.
That command shows the whole story. Here is an example.
## What a disagreement looks like
Here the tests failed while a helper agent (a subagent) looked through the
code, yet the agent's closing message says the tests pass. The session is built
by `test/acceptance/readme_test.go`, which feeds hook payloads through the real
recorder, and that test fails if this excerpt and the render ever differ. This
excerpt is `rashomon report` exactly as it renders that session:
```
the agent's account:
"Done. I refactored ParseConfig and all tests pass."
subagents: 1
agent-a41f (Explore): 3 declarations, 3 executions, 1 Bash
(these calls do not appear in the main transcript)
failed calls: 1
the final message contains none of these 43 words: fail, failed, failing, error, errors, couldn't, could not, unable, not able, didn't, did not, blocked and 31 more of 43 (--json lists them all)
test runs: 1 (0 ok, 1 failed)
```
The first line quotes the agent. The rest comes from rashomon's own record,
checked against those words: one call failed (its record holds exit code 1, and
`--chain` shows which call it was), and the subagent's three calls are recorded
under the subagent's own transcript, not the main one. The last line counts the
calls rashomon recognised as a test runner (`go test`, `pytest`, `npm test` and
a fixed list of others) by how they ended. The report lists the failure words
the summary does *not* use; it does not guess why.
## What a report tells you
- **What subagents did**: the helper agents Claude starts on its own, whose
steps the main conversation never shows.
- **Which steps failed**, and whether the agent's closing summary uses any of
rashomon's failure words. It lists the ones that are *absent*; it never
guesses at intent.
- **What ran differently from what was asked**, for example another hook that
rewrote a command's input before it ran.
- **What rashomon could not see**, on every report, even a healthy one.
## Try it yourself
You can produce the same kind of report in a few minutes:
1. Install rashomon (see [Get started](https://github.com/altrace-dev-role/rashomon#get-started)).
2. In a project you have open, break one test on purpose.
3. Start `claude`. Ask it to have a subagent look through the code, then to run
the tests and finish with a one-line summary.
4. Run `rashomon report` (or `/rashomon:report` inside Claude Code).
The report quotes the summary above the `subagents` and `failed calls` lines.
Whether the failure is flagged depends on what the agent writes. If the summary
contains none of rashomon's 43 failure words (matched as substrings, so "debug"
counts as "bug"), the `failed calls` line lists them. Most honest summaries
contain one, and then the report says so instead.
## Common questions
**Does it see my code or my prompts?**
It sees them in passing and keeps none of them. Claude Code hands every hook the
tool call's full input (for Write and Edit, that includes the file's text) and
hands the next-prompt hook your prompt; rashomon reads what it needs and
discards the rest. It stores no prompts, responses, file contents or tool
output. A command is reduced to its program name, an argument count and a keyed
digest, by a parser that names nothing when it is unsure. The one thing it keeps
from inside a command is any hostname the command names (and the host of a
WebFetch URL), stored in clear so the report can list it. The working directory
and transcript path are stored too; see
[What is recorded](https://github.com/altrace-dev-role/rashomon#what-is-recorded-and-what-never-is). When you run
`rashomon report`, it quotes the agent's final message from Claude Code's own
transcript; that quote is never stored.
**Does it send anything anywhere?**
It has no account, no telemetry and no network code of its own, and what it
records is kept in a folder on your machine. No rashomon package imports a
networking package, and CI checks that on every pull request, every push to
main and every release tag. On Linux, CI also runs the
declaration hook with the network switched off; the other hooks, the report and
the end-of-turn line have no such runtime test yet.
**Can it break my agent?**
No. It never stops a command, and if something inside it goes wrong, it exits
quietly so Claude Code carries on.
**Does it work with Cursor or Codex?**
No. This release supports Claude Code only. Cursor (by default) and Codex (after
`/import`) read Claude Code's settings, so they can trigger the recorder anyway,
and what it records for them can be wrong. If you use Cursor, see
[Scope](https://github.com/altrace-dev-role/rashomon#scope-and-threat-model) for the setting to turn off.
**Is it a sandbox or a security tool?**
No. It does not stop or contain the agent, and it cannot stop a determined agent
from changing its records. It is a second, independent account of what happened,
to set beside the agent's own.
**Can I see network activity?**
rashomon itself observes no network traffic in this alpha: the report says
`destinations: not observed in this alpha`, and `--chain` lists only the hosts
each command *named*. If you run Claude Code inside the
[nono](https://github.com/nolabs-ai/nono) sandbox,
`rashomon report --nono-audit <path to nono's audit-events.ndjson>` adds what
nono allowed and refused in that session's window. This is experimental, and
nono writes that file when its session ends. See
[Inside a sandbox](https://github.com/altrace-dev-role/rashomon#inside-a-sandbox) first.
**How do I turn it off?**
Plugin: open `/plugin` in Claude Code and turn it off. Command line:
`rashomon detach`. Your records stay in `~/.local/state/rashomon` (by default)
until you delete that folder.
**Is it finished?**
No. This is an alpha: Windows is not supported yet, and network destinations are
not observed in this release.
## The details
Everything below is the precise version: what gets installed, what is stored,
and what the report can and cannot see.
## Install options, in detail
**As a Claude Code plugin** (macOS and Linux):
```
claude plugin marketplace add altrace-dev-role/rashomon
claude plugin install rashomon@rashomon
claude plugin enable rashomon@rashomon
```
Installing does not start recording; enabling does. Start a new Claude Code
session after enabling. `/plugin` shows it and turns it off again, and
`/rashomon:status` / `/rashomon:report` work inside Claude Code. The plugin
installs the release's `rashomon-plugin.zip`, which carries a prebuilt recorder
per platform, because a plugin cannot compile Go at install time. So it needs
a tagged release to exist. To try the plugin from a checkout instead:
```
scripts/build-plugin.sh
claude --plugin-dir ./plugin --settings '{"enabledPlugins": {"rashomon@inline": true}}'
```
The plugin ships disabled, and a plugin loaded with `--plugin-dir` (Claude Code
names it `rashomon@inline`) is enabled only through settings. Without the
`--settings` flag the session loads the plugin and records nothing.
If you already ran `watch`, run `rashomon detach` first. With both installed,
every call is recorded twice, and the report marks the session
`duplicate_declarations`. `rashomon status` names the overlap for a plugin
installed from the marketplace; it cannot see one loaded with `--plugin-dir`.
**As a settings install** (Windows is not usable yet; see [Status](https://github.com/altrace-dev-role/rashomon#status)).
From a release, on macOS or Linux:
```
curl -fsSL https://raw.githubusercontent.com/altrace-dev-role/rashomon/main/install.sh | sh
```
It downloads the release archive for your platform, checks it against the
release's `checksums.txt`, refuses to install on a mismatch, and puts one
binary in `~/.local/bin` (set `RASHOMON_INSTALL_DIR` to change that). Or with
Go:
```
go install github.com/altrace-dev-role/rashomon/cmd/rashomon@latest
```
This writes to `$GOBIN`, or `$(go env GOPATH)/bin` when `GOBIN` is unset; make
sure that folder is on your `PATH`. A binary built this way, or from a clone,
reports its version as `dev`: only release builds carry the version number. Or
clone and build:
```
git clone https://github.com/altrace-dev-role/rashomon
cd rashomon && go build ./cmd/rashomon
```
> **Install to a location that will not move.** `watch` writes the running
> binary's absolute path into your Claude Code settings, and Claude Code
> executes that path on **every tool call**. If you built inside a clone you
> later delete, every tool call fires a hook that cannot start. Build into a
> directory you keep (or `go install` it), and re-run `watch` after any move.
> `watch` records the path with symlinks resolved, so a stable symlink that
> points into a clone still breaks when the clone goes. (`watch` refuses a
> binary whose path runs through a `go-build` directory, which is where
> `go run` builds it.)
>
> **Why a broken hook matters more than usual:** a `PreToolUse` hook that exits
> non-zero in the wrong way can *block* the tool call, and the user sees Claude
> Code failing rather than this program. Every recoverable failure here is
> engineered to exit 0 for that reason (a Go runtime fatal error cannot be
> caught, so those are prevented structurally instead, for example by capping
> how much input a hook reads); see
> [`docs/design-notes.md`](https://github.com/altrace-dev-role/rashomon/blob/main/docs/design-notes.md).
## What `watch` sets up
```
rashomon watch # install the recorders (the only command that installs anything)
claude # work normally
rash