
Clean agent tool output. Lower token burn.
A Claude Code plugin that replaces the harness's built-in file and shell tools with structured
equivalents that return only what the model needs. The default Read/Edit/Write/Grep/
Glob/NotebookEdit tools dump full files, full directories, and full shell logs into the
model's context. relaywash returns ranked snippets, signature views, parsed errors, and
truncated diffs instead.
Install
/plugin marketplace add AgentWorkforce/wash
/plugin install relaywash@agentworkforce
That's it. relaywash takes effect on the next session: the active agent has built-in file
tools disabled, and the MCP server exposes the structured replacements.
What's in the box
| Tool | Replaces | Notes |
|---|
relaywash__Search | Glob + Grep + Read | Ranked snippets across matched files. One call where vanilla takes ~9. |
relaywash__Read | Read | AST-aware: signatures mode for known languages, mtime cache, range follow-ups. |
relaywash__Edit | Edit | Batched multi-file edits with whitespace/Unicode fuzzy matching, atomic per file, tree-sitter post-check. |
relaywash__GitState | git status/diff/log/show | Structured: file lists + summary stats; per-file diffs truncated. |
relaywash__TestRun | pnpm test / pytest / jest / go test / cargo test | Counts + failed-test summaries. Use getFailureLog to drill into one failure. |
relaywash__Build | tsc / cargo / go / pnpm build | One line on success; parsed errors[] on tsc/cargo/go failures; errorTail otherwise. |
relaywash__GhPR | gh pr view/list/diff + gh api ...pulls... | Field selector; truncated bodies and hunks. |
Each result carries _meta: { replaces, collapsedCalls } so relayburn (the measurement
side of the project) can attribute savings.
What's disabled and why
The active agent (relaywash:code) has these built-in tools blocked:
Read, Edit, Write, Grep, Glob, NotebookEdit
A PreToolUse safety-net hook also blocks them at the harness level, so even sub-agents
or /agents switches can't fall through to vanilla Read. Bash is still available; a
warn-only hook nudges you toward the structured equivalent when a known shell pattern shows
up (e.g. git status, pnpm test).
Measurement
relaywash depends on the relayburn-sdk crate
for ledger reads/writes. On every session end, the Stop hook calls sdk::ingest, which
reads the Claude Code transcript directly — including each tool result's
_meta: { replaces, collapsedCalls } annotation — and folds it into the local ledger at
~/.agentworkforce/burn/ (override with RELAYBURN_HOME). To see your savings:
/relaywash-savings
Repository layout
.claude-plugin/ plugin.json + marketplace.json
.mcp.json launches bin/wash.mjs (which resolves the native binary)
settings.json activates the relaywash:code agent
agents/ code (default) + explore (cheap haiku read-only)
hooks/ PreToolUse / PostToolUse / SessionStart / Stop
scripts/ hook scripts + /relaywash-savings + copy-binary
bin/wash.mjs Node launcher that resolves the platform binary at runtime
crates/wash/ Rust source — the wash binary
src/mcp/ minimal MCP server over stdio
src/tools/ one file per relaywash__ tool
src/ast/ tree-sitter signature extraction + parses_cleanly
src/fuzzy.rs whitespace + Unicode normalization for Edit matching
src/search.rs ripgrep-stack search (no shell-out to `rg`)
src/walk.rs .gitignore-aware file enumeration
packages/ per-platform npm packages — binaries injected by CI
wash-darwin-arm64/
wash-darwin-x64/
wash-linux-arm64/
wash-linux-x64/
wash-win32-x64/
fixtures/corpus/ recorded sessions for burn-compare
docs/ including compaction-attribution.md
Distribution
Single channel: npm, using the optionalDependencies pattern (esbuild / swc / rolldown / agent-relay all do this):
- Wrapper package
relaywash ships only the launcher (bin/wash.mjs). Its optionalDependencies list five platform-specific siblings.
- Per-platform packages (
@relaywash/wash-{platform}-{arch}) each carry one prebuilt binary in bin/. Each declares os / cpu so npm installs only the matching one per machine.
- The launcher resolves the platform package via
require.resolve at runtime and execs the binary. Falls back to target/release/wash for local dev. RELAYWASH_BIN overrides everything.
- CI (
.github/workflows/release.yml) builds the binary on each target platform on tag push, then publishes the five platform packages plus the wrapper to npm at the same version.
The plugin's .mcp.json calls the launcher script directly: