Skip to main content

🐎 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.

License: MIT CI Dependencies Python Claude Code


💸 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's bin/ on the path of its own sessions, which is where the skills, the commands and the agents call rein. In a plain terminal rein will 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-kit then claude plugin update rein@rein-agentic-kit — qualified with the marketplace, or it reports Plugin "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
rein gate        # ✅ did they PASS — 0 green · 1 the code is wrong · 126 the environment could not run them
                 # --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
                 # always exits 0 (D5: never a silent skip, never a hard stop) — the
                 # judgement there is the planner's. ✅ `--gate` is for a RUNNER: exits 1
                 # on a BLOCKING finding. `--tasks T001,T002` scopes it — a finding pinned
                 # to a task nobody will run cannot stop it, while one with no task id is
                 # plan-level and always counts
rein role <name> # ✅ one role's operating profile (planner|implementer|reviewer) as
                 # markdown — the same section /rein:rein-role reads, for any agent
                 # that cannot invoke a Claude Code skill
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 event task <id> <started|verified|blocked|merged>
                 # record a task TRANSITION as it happens — rejects any other word
                 # by name, without writing
rein state       # per-task transitions folded from the event log + plan; given a
                 # workspace, folds every member into one table
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
rein workspace   # discover .rein/workspace.json and report each member repo's
                 # branch and head; one explanatory line, exit 0, when none is found
rein linear list # issues from Linear, filtered (--repo / --priority /
                 # --max-priority / --state / --flow / --label / --parent) and
                 # ordered urgent-first. Linear numbers priority 1=urgent…4=low
                 # and reserves 0 for "none", so unprioritised sorts LAST.
                 # The 14 index cards are excluded unless --groupers
rein linear show # one issue with its prose, --json for the parsed record
rein linear comment
                 # leave a comment: --body TEXT, or --body-file PATH (`-` for
                 # stdin, which is what multi-line markdown wants). It exists so
                 # nothing has to reach for the raw GraphQL endpoint with your
                 # API key. There is deliberately no bare `linear state`: moving
                 # to Done belongs to `rein land`, behind its merge check.
                 # All three need REIN_LINEAR_API_KEY
rein intake      # take an issue: Beads issue in the owning repo (only when its
                 # flow.config.json says tracker.kind: "beads"), branch named
                 # the way Linear already named it, Backlog → In Progress, and a
                 # comment saying where the work went. Re-running resumes; it
                 # never files a second Beads issue for one bug
rein land        # close it out: Beads closed, Linear → Done, both carrying the
                 # merge commit. Refuses when the base branch holds no commit
                 # naming the issue — a squash merge keeps the id, not the sha

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 / validatenever 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 verify executes 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 (plus sync to 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's get_symbols_overview / find_symbol / find_referencing_symbols cover 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 --fast that 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.
  • discover was 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.

Built with Claude Code, reviewed by an agent that wrote none of it.

Release files for rein-agentic-kit 0.15.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rein-agentic-kit 0.15.0
File Size Uploaded
rein_agentic_kit-0.15.0.tar.gz 409.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rein-agentic-kit 0.15.0
File Interpreter ABI Platform
rein_agentic_kit-0.15.0-py3-none-any.whl Python 3 none any Details

Total release size: 641.8 kB

Release files / rein_agentic_kit-0.15.0.tar.gz

Download URL rein_agentic_kit-0.15.0.tar.gz
Size 409.8 kB
Tags Source
SHA-256 checksum
How to use checksums
6f0b17a997ecac46f9d6496146e8e307d0b80b21bf44a92c1e457e1465fac518
BLAKE2b-256 checksum
How to use checksums
e51c7512e7e542f7991033e5dd91b222ff08233b511ca3576491552eab9e2dc8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release files / rein_agentic_kit-0.15.0-py3-none-any.whl

Download URL rein_agentic_kit-0.15.0-py3-none-any.whl
Size 232.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7d78f2e6bd802095f99053d5ad4061034213e0791170cce522215a8c085286d3
BLAKE2b-256 checksum
How to use checksums
a6757cac05fd665d6c97a91796f7bdfc719dd84ae61432e4cc4bf5274576486d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.15.0 This release

2 release files

0.13.3

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page