Skip to main content

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.

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
                 # --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 / 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rein_agentic_kit-0.13.0.tar.gz (317.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rein_agentic_kit-0.13.0-py3-none-any.whl (178.0 kB view details)

Uploaded Python 3

File details

Details for the file rein_agentic_kit-0.13.0.tar.gz.

File metadata

  • Download URL: rein_agentic_kit-0.13.0.tar.gz
  • Upload date:
  • Size: 317.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for rein_agentic_kit-0.13.0.tar.gz
Algorithm Hash digest
SHA256 3f59b8edba6784e92729f1b3eb5559128bedcc0bf3243aaf1026921c4c031653
MD5 b154d5009b61ea5b3c9ac9745452c29c
BLAKE2b-256 a96f0033e08ac449d05e5ca18565a1b238b572770a73b25831aafd4d2b46b49f

See more details on using hashes here.

Provenance

The following attestation bundles were made for rein_agentic_kit-0.13.0.tar.gz:

Publisher: publish.yml on luisfarfan/rein-agentic-kit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rein_agentic_kit-0.13.0-py3-none-any.whl.

File metadata

File hashes

Hashes for rein_agentic_kit-0.13.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5463f98b0c7d2d8e5808d47b3a140f0e38da23fc4216c6fe47bf4d03bc843033
MD5 7cd7ea85c5c495cbd423480d686d198a
BLAKE2b-256 3b5218cf21e7be7391b6960aa997b5e428855bb0584f0ac8444e677ac09d08fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for rein_agentic_kit-0.13.0-py3-none-any.whl:

Publisher: publish.yml on luisfarfan/rein-agentic-kit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page