Rein — keep your Claude Code agents lean and in control. Token-lean, stack-aware agentic dev flow.
Project description
🐎 Rein
Keep your Claude Code agents lean and in control.
A Claude Code plugin that turns agent work into a bounded, measured, independently-reviewed flow — and tells you what it actually cost, per model.
💸 The problem, measured
Optimizing agent cost by "making the model write less" does nothing. Over real Claude Code transcripts:
| Where the tokens go | Share |
|---|---|
🔴 cache_read — context re-read every turn |
~90% |
🟠 cache_write |
~10% |
| 🟢 output — what a compressor would attack | ~0.3% |
| ⚪ fresh input | ~0% |
Cost ≈ turns × context size. One agent that ran 241 turns, re-reading ~234k of context on every single turn, was most of a 112M-token run.
And Claude Code has no native eviction of stale tool results — only /compact, which is
lossy and breaks the prompt cache. A long agent's context only grows.
Measured effect of this kit: 241 turns → 26 · Opus 100% → 0% · ~7× less context per turn.
🔁 The flow
flowchart TD
A["🧭 /rein:rein-plan<br/><i>Why · Scope · Decisions · Tasks</i>"]
B{{"rein next<br/><i>deterministic gate</i>"}}
C["⚙️ Implement<br/><i>bounded loop of FRESH agents</i><br/><i>context resets each step</i>"]
D{{"Verify<br/><i>ask the plan, not the agent</i>"}}
E["🔍 /rein:rein-audit<br/><i>whole change · 5 axes</i>"]
F["✅ merge"]
G["✋ escalate to you"]
X["🛑 stop"]
A -->|you confirm| B
B -->|ready| C
C --> D
D -->|contradiction| X
D -->|consistent| E
E -->|"APPROVED + gate green"| F
E -->|"needs your judgement"| G
E -->|"CHANGES_REQUESTED · max 3"| C
style A fill:#1e3a5f,stroke:#4a90d9,color:#fff
style C fill:#1e4620,stroke:#4caf50,color:#fff
style E fill:#5f1e3a,stroke:#d94a90,color:#fff
style F fill:#2d4a1e,stroke:#8bc34a,color:#fff
style X fill:#4a1e1e,stroke:#d94a4a,color:#fff
style G fill:#4a3a1e,stroke:#d9a94a,color:#fff
Three roles, and no agent approves its own implementation. Every run works in its own git worktree; unapproved work is never merged.
🚀 Quickstart
claude plugin marketplace add luisfarfan/rein-agentic-kit
claude plugin install rein@rein-agentic-kit --scope user
Restart Claude Code, then run inside it:
/rein:rein-ping → is it wired here, and what did it detect?
/rein:rein-setup → probe the optional tools · confirm to provision them
ping reports the detected stack, the resolved commands and where each one
came from. If it got everything right, you configure nothing.
Everything runs inside Claude Code — there is nothing to add to your
$PATH. Claude Code puts the plugin'sbin/on the path of its own sessions, which is where the skills, the commands and the agents callrein. In a plain terminalreinwill not be found, and that is expected: the CLI exists to be called by the flow, and the two commands a person runs by hand have slash commands above.
Want rein in your own terminal too?
The plugin's bin/ is only on the path of Claude Code's own sessions — a plugin
cannot add anything to your shell. For rein dashboard, rein ledger or
rein doctor from a terminal, install the CLI the way every tool this kit
integrates ships (serena and graphify via uv, codegraph and openspec via npm):
uv tool install rein-agentic-kit # or: pipx install rein-agentic-kit
Same code, same version, zero dependencies. The two channels cannot drift: a test fails the build if their version strings ever disagree.
To update:
claude plugin marketplace update rein-agentic-kitthenclaude plugin update rein@rein-agentic-kit— qualified with the marketplace, or it reportsPlugin "rein" not found.
Then, per change:
/rein:rein-discover → think it through, until the unknowns that matter are closed
/rein:rein-plan → you confirm the plan
/rein:rein-apply → read the verdict
You come back when it finished, not before.
🧰 What you get
Skills — the three roles
🔭 /rein:rein-discover |
Think a problem through before committing to a shape — investigate, ask, produce understanding. Writes no plan, implements nothing |
🎭 /rein:rein-role |
Assign this session's role: planner · implementer · reviewer |
🧭 /rein:rein-plan |
Plan into verifiable tasks — dry-run and explicit confirmation before writing |
🔨 /rein:rein-step |
Exactly one task. Max 3 attempts, max 5 failed commands, no self-approval |
🔁 /rein:rein-steps |
Bounded loop of step, stopping on verifiable signals only |
🔍 /rein:rein-audit |
The independent gate: mechanical checks first, then five-axis judgement |
♾️ /rein:rein-apply |
Runs all three end-to-end in an isolated worktree |
CLI — the deterministic half
rein doctor # 🩺 start here: stack, resolved commands, and the source of each
# plus a "version : <verdict> -- <reason>" line -- up-to-date / stale /
# unknown against the marketplace clone, with fix commands when stale
# --json: {"version", "pluginRoot", "project", "plan", "verifyState",
# "ledger", "staleness"} -- staleness is {"verdict", "reason",
# "installedVersion", "availableVersion"}
rein setup # probe the optional tools · --install provisions what is missing
rein detect # stack + commands, with the source of each
rein tasks # the plan, parsed
rein context # detect + plan in ONE round-trip — what the loop's first agent runs
rein verify # actually RUN each resolved command and report the truth — an inference is not a fact
# --plan: run each TASK's own Verification before implementers are paid.
# Failing is fine (the work does not exist yet); proving NOTHING is not —
# a missing test module or a selector matching zero tests exits non-zero
rein plan-check # mechanical findings on a drafted plan's own text — what a regex can
# honestly decide; the semantic call belongs to /rein:rein-plan's critique
rein next # ✅ the gate: is there a task to claim, and may it be
rein close T001 # tick a checkbox deterministically — no agent hand-edits the plan
rein review # record / check a verdict bound to a code state
rein token-report# what a run really cost, per agent and per model, plus its wall clock,
# agent-minutes and their ratio (1.00x = nothing overlapped)
rein event <name># record a skill invocation — an EVENT, never folded into a run total
rein ledger # history across projects, with deltas vs a marked baseline
# --json: {"runs": [...], "events_by_project": {...}} -- runs are
# unchanged row objects; events (D3) are counted separately, never
# folded into a run total
rein baseline # mark the run everything is compared against
rein dashboard # 📊 serve it all as a local page
The rule that separates them: if it's a parse, a script does it. If it's a judgement, an agent does it. Every fact an agent doesn't have to rediscover is turns you don't pay for.
⚖️ The three levers
1️⃣ Bounded loop of fresh agents. Each task is at most N short, fresh agents handing off a
compact ledger (progress / remaining / filesTouched / verification) — never one agent
running 200+ turns. Context resets at every boundary, so spend stops growing without a ceiling.
2️⃣ Per-agent model routing. Mechanical → Haiku · code → Sonnet · the review gate → Opus. On a subscription this doesn't lower the bill — it frees the scarce Opus quota, which is the limit you actually hit.
3️⃣ Verifiable signals, not model judgement. A loop that stops when the model feels finished
has no gate. rein next answers "is there work to claim" from the plan; rein review check
answers "does this approval still apply" from content hashes. Neither asks a model anything.
❌ Deliberately not included
Tried and discarded with data, not taste:
- Output compressors — they attack the 0.3%.
- Multi-provider API swarms — the saving doesn't apply on a subscription, and more agents means more contexts re-read.
- Cross-session memory tools — orthogonal to the actual cost driver.
- Cache-aware proxies — no-op on already-cached traffic.
- Persona prompts ("you are a hexagonal architecture expert") — the same model with the same weights. Constraints that can be violated are useful; job titles are not.
⚙️ Configure
Everything is optional. Drop a flow.config.json at your project root to override:
{
"commands": {
"test": "uv run pytest -q",
"testOne": "uv run pytest -q {target}",
"lint": "uv run ruff check .",
"typecheck": "uv run mypy ."
},
"models": { "aux": "haiku", "impl": "sonnet", "review": "opus" },
"limits": { "maxTaskSteps": 8, "maxReviewRounds": 3 }
}
Precedence: flow.config.json › task runner (justfile / Makefile / Taskfile / mise) ›
autodetection. A project that already declares how it is built is never second-guessed.
🧱 Supported stacks
| Stack | Detected by | Verification |
|---|---|---|
| 🐍 Python | pyproject.toml, uv / poetry |
pytest · ruff · mypy |
| 🟨 Node / TS | package.json, pnpm / npm / yarn / bun |
vitest or jest · eslint · tsc |
| 🦀 Rust | Cargo.toml |
cargo test · clippy · check |
| 🐹 Go | go.mod |
go test · vet |
| 🎨 Frontend (Next, Vite, Astro, SvelteKit, Nuxt, Remix) | dependencies | rendered verification — unit tests alone don't catch "the tests pass but the UI is broken" |
| ☁️ Serverless / infra | serverless.yml, sst.config.ts, *.tf |
plan / validate — never deploy |
| 📦 Monorepo | sub-projects one or two levels down, no root manifest | two or more candidates are reported — it never picks one for you; exactly one candidate is not a choice, so it is resolved directly, reporting that project's own stack with its path carried (cd <dir> && ...) |
A resolved command is an inference until something runs it.
rein verifyexecutes each one and reports what happened, distinguishing "the binary is missing" (a setup problem) from "the suite ran and failed" (a code problem) — conflating them sends you to the wrong file. The loop runs it at Prepare: a broken gate found there costs nothing, the same one found at review costs a whole run.
Optional tools (serena, codegraph, graphify, openspec) are probed, never
required: if one is absent the flow degrades, it does not break. rein setup reports
what is missing and installs it on request — and distinguishes installed from usable,
because graphify without an index and a just-registered MCP server are both present and
inert.
No retrieval speedup is claimed. With codegraph present, the loop's implementers are taught
codegraph query/callers/callees/node/impact(plussyncto refresh the index after their own edits) as the one owner of "what is this / who touches it / what breaks if I change it"; with codegraph absent, serena'sget_symbols_overview/find_symbol/find_referencing_symbolscover the same ground as a fallback. Whether either reduces the turns an agent spends orienting is unmeasured, and the one control available points the other way. See docs/decisions.md D2.
One owner per question. A tool is dropped from the prompts for having no exclusive question — not for being bad:
flowchart LR
Q1["❓ what is this?<br/>who touches it?<br/>what breaks if I change it?"] --> CG["🔎 codegraph<br/><i>query · callers · callees</i><br/><i>node · impact</i>"]
Q2["❓ edit this symbol<br/>type errors, no build"] --> SE["✏️ serena<br/><i>replace_symbol_body</i><br/><i>get_diagnostics_for_file</i>"]
Q3["❓ docs · papers · images"] --> GR["📚 graphify<br/><i>/graphify skill</i><br/><i>outside the loop</i>"]
style CG fill:#1e4620,stroke:#4caf50,color:#fff
style SE fill:#1e3a5f,stroke:#4a90d9,color:#fff
style GR fill:#4a3a1e,stroke:#d9a94a,color:#fff
Measured on this repo, same question, same index cost (~1.5s, no LLM, no API key for either):
asked "where is it decided that a command is not invocable?", codegraph returns
NOT_INVOCABLE_EXIT_CODES = (126,127) with its file and line in 258 tokens; the graph
tool it replaced returned 546 tokens of an unrelated example config, because a JSON key
happened to match. Confident noise is worse for an agent than no answer — it cannot tell the
two apart, and it pays for the difference on every later turn.
📊 Measure
rein token-report && rein dashboard
Reads Claude Code's own JSONL transcripts (including cache_read) and breaks a run down per
agent and per model. Every run is summarized into ~/.claude/rein/runs.jsonl, so history
survives transcript rotation.
On the word "savings": this measures consumption. A saving needs a baseline. Mark one with
rein baseline mark and every later run in that project gets a signed delta. Without one, the
honest numbers are the three that predict cost — turns/agent, ctx_max/turn,
% of tokens on Opus.
🙃 Honest limitations
Things a README usually hides:
- The reviewer is calibrated hard. Across 9 runs of this repo, 8 used all 3 rounds, and the
LAST round produced a real BLOCKING finding in 4 of them. Review is ~52% of a run's wall
clock and it earns it — which is why there is no
--fastthat reviews less. - A stalled agent burns wall-clock. One run spent 3.4 hours almost entirely in silent API retries.
- Runs are serial. Every run measured so far reports an overlap of
1.00x— tasks that declare no dependency can now run concurrently, but the plans written here have been chains, so the parallel path has yet to fire on real work. discoverwas considered and rejected — a per-run version of it was measured in the origin project and did not move the needle. See docs/decisions.md.
🗺️ Roadmap
| Phase | Scope | |
|---|---|---|
| 0 | Plugin plumbing · token-report · ledger · stack detection |
✅ findings |
| 1 | Config-driven core loop · tasks.md adapter — measured |
✅ |
| 2 | Stack-aware verification policy | ✅ |
| 3 | Local dashboard · per-agent model config | ✅ |
| 4 | Compose real browser verification | ✅ |
| 5 | Docs · a second distribution channel (PyPI) · release automation | ✅ |
| 6 | A second real-world project, and the parallel path on a plan that has one | ⏳ |
📄 License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rein_agentic_kit-0.13.1.tar.gz.
File metadata
- Download URL: rein_agentic_kit-0.13.1.tar.gz
- Upload date:
- Size: 319.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30726131d39388c013541137f868841756a94a4afe5fd7be98b108c16b4d8e5e
|
|
| MD5 |
6adf102e6d5613e4d2e77d1b7fde2f15
|
|
| BLAKE2b-256 |
02445196c4d7f3e8bb1d9f0bf807370ef9f1519901699f7933cc49d5a5b5005e
|
Provenance
The following attestation bundles were made for rein_agentic_kit-0.13.1.tar.gz:
Publisher:
publish.yml on luisfarfan/rein-agentic-kit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rein_agentic_kit-0.13.1.tar.gz -
Subject digest:
30726131d39388c013541137f868841756a94a4afe5fd7be98b108c16b4d8e5e - Sigstore transparency entry: 2318567462
- Sigstore integration time:
-
Permalink:
luisfarfan/rein-agentic-kit@466a2ab907a75fcb17994edc1758400f24f82485 -
Branch / Tag:
refs/tags/rein--v0.13.1 - Owner: https://github.com/luisfarfan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@466a2ab907a75fcb17994edc1758400f24f82485 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rein_agentic_kit-0.13.1-py3-none-any.whl.
File metadata
- Download URL: rein_agentic_kit-0.13.1-py3-none-any.whl
- Upload date:
- Size: 179.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58f001588f38a2ee07b44d743757373a2849193e3e7cd48d195b7e9ccb6c476d
|
|
| MD5 |
d3146eaf0e0f59c4e6b9ee3bc34a3ddf
|
|
| BLAKE2b-256 |
55833748696e12fb698fe7db3ad521c75a7fffc4efa666aa70b81dc0369a62cb
|
Provenance
The following attestation bundles were made for rein_agentic_kit-0.13.1-py3-none-any.whl:
Publisher:
publish.yml on luisfarfan/rein-agentic-kit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rein_agentic_kit-0.13.1-py3-none-any.whl -
Subject digest:
58f001588f38a2ee07b44d743757373a2849193e3e7cd48d195b7e9ccb6c476d - Sigstore transparency entry: 2318567548
- Sigstore integration time:
-
Permalink:
luisfarfan/rein-agentic-kit@466a2ab907a75fcb17994edc1758400f24f82485 -
Branch / Tag:
refs/tags/rein--v0.13.1 - Owner: https://github.com/luisfarfan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@466a2ab907a75fcb17994edc1758400f24f82485 -
Trigger Event:
push
-
Statement type: