rein-agentic-kit 0.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. rein_agentic_kit-0.7.1/LICENSE +21 -0
  2. rein_agentic_kit-0.7.1/PKG-INFO +340 -0
  3. rein_agentic_kit-0.7.1/README.md +320 -0
  4. rein_agentic_kit-0.7.1/plugins/rein/.claude-plugin/plugin.json +19 -0
  5. rein_agentic_kit-0.7.1/plugins/rein/__init__.py +0 -0
  6. rein_agentic_kit-0.7.1/plugins/rein/_entry.py +39 -0
  7. rein_agentic_kit-0.7.1/plugins/rein/bin/rein +716 -0
  8. rein_agentic_kit-0.7.1/plugins/rein/commands/ping.md +35 -0
  9. rein_agentic_kit-0.7.1/plugins/rein/commands/setup.md +34 -0
  10. rein_agentic_kit-0.7.1/plugins/rein/flow.config.example.json +59 -0
  11. rein_agentic_kit-0.7.1/plugins/rein/lib/dashboard.py +1311 -0
  12. rein_agentic_kit-0.7.1/plugins/rein/lib/detect.py +885 -0
  13. rein_agentic_kit-0.7.1/plugins/rein/lib/events.py +149 -0
  14. rein_agentic_kit-0.7.1/plugins/rein/lib/gate.py +283 -0
  15. rein_agentic_kit-0.7.1/plugins/rein/lib/plan.py +348 -0
  16. rein_agentic_kit-0.7.1/plugins/rein/lib/plan_check.py +219 -0
  17. rein_agentic_kit-0.7.1/plugins/rein/lib/serve.py +413 -0
  18. rein_agentic_kit-0.7.1/plugins/rein/lib/setup.py +455 -0
  19. rein_agentic_kit-0.7.1/plugins/rein/lib/token_report.py +716 -0
  20. rein_agentic_kit-0.7.1/plugins/rein/lib/verify.py +412 -0
  21. rein_agentic_kit-0.7.1/plugins/rein/lib/version_staleness.py +330 -0
  22. rein_agentic_kit-0.7.1/plugins/rein/skills/loop/SKILL.md +96 -0
  23. rein_agentic_kit-0.7.1/plugins/rein/skills/plan/SKILL.md +166 -0
  24. rein_agentic_kit-0.7.1/plugins/rein/skills/review/SKILL.md +107 -0
  25. rein_agentic_kit-0.7.1/plugins/rein/skills/role/SKILL.md +78 -0
  26. rein_agentic_kit-0.7.1/plugins/rein/skills/run/SKILL.md +59 -0
  27. rein_agentic_kit-0.7.1/plugins/rein/skills/run-auto/SKILL.md +70 -0
  28. rein_agentic_kit-0.7.1/plugins/rein/workflows/loop.js +2335 -0
  29. rein_agentic_kit-0.7.1/pyproject.toml +53 -0
  30. rein_agentic_kit-0.7.1/rein_agentic_kit.egg-info/PKG-INFO +340 -0
  31. rein_agentic_kit-0.7.1/rein_agentic_kit.egg-info/SOURCES.txt +66 -0
  32. rein_agentic_kit-0.7.1/rein_agentic_kit.egg-info/dependency_links.txt +1 -0
  33. rein_agentic_kit-0.7.1/rein_agentic_kit.egg-info/entry_points.txt +2 -0
  34. rein_agentic_kit-0.7.1/rein_agentic_kit.egg-info/top_level.txt +1 -0
  35. rein_agentic_kit-0.7.1/setup.cfg +4 -0
  36. rein_agentic_kit-0.7.1/tests/test_baseline.py +295 -0
  37. rein_agentic_kit-0.7.1/tests/test_baseline_cli.py +172 -0
  38. rein_agentic_kit-0.7.1/tests/test_cli_resolution.py +98 -0
  39. rein_agentic_kit-0.7.1/tests/test_dashboard.py +831 -0
  40. rein_agentic_kit-0.7.1/tests/test_dashboard_glossary.py +384 -0
  41. rein_agentic_kit-0.7.1/tests/test_dashboard_history.py +380 -0
  42. rein_agentic_kit-0.7.1/tests/test_dashboard_summary.py +260 -0
  43. rein_agentic_kit-0.7.1/tests/test_detect.py +151 -0
  44. rein_agentic_kit-0.7.1/tests/test_doctor_cli.py +309 -0
  45. rein_agentic_kit-0.7.1/tests/test_events.py +409 -0
  46. rein_agentic_kit-0.7.1/tests/test_gate.py +283 -0
  47. rein_agentic_kit-0.7.1/tests/test_gate_precheck.py +280 -0
  48. rein_agentic_kit-0.7.1/tests/test_graph_index.py +255 -0
  49. rein_agentic_kit-0.7.1/tests/test_graph_retrieval.py +313 -0
  50. rein_agentic_kit-0.7.1/tests/test_loop_policy.py +696 -0
  51. rein_agentic_kit-0.7.1/tests/test_measure_step.py +296 -0
  52. rein_agentic_kit-0.7.1/tests/test_monorepo.py +301 -0
  53. rein_agentic_kit-0.7.1/tests/test_packaging.py +102 -0
  54. rein_agentic_kit-0.7.1/tests/test_parallel_groups.py +410 -0
  55. rein_agentic_kit-0.7.1/tests/test_parallel_worktree_git.py +263 -0
  56. rein_agentic_kit-0.7.1/tests/test_plan.py +269 -0
  57. rein_agentic_kit-0.7.1/tests/test_plan_self_check.py +464 -0
  58. rein_agentic_kit-0.7.1/tests/test_python39_compat.py +72 -0
  59. rein_agentic_kit-0.7.1/tests/test_render_policy.py +630 -0
  60. rein_agentic_kit-0.7.1/tests/test_run_duration.py +369 -0
  61. rein_agentic_kit-0.7.1/tests/test_serena_worktree.py +140 -0
  62. rein_agentic_kit-0.7.1/tests/test_serve_probe.py +472 -0
  63. rein_agentic_kit-0.7.1/tests/test_setup.py +532 -0
  64. rein_agentic_kit-0.7.1/tests/test_token_report.py +229 -0
  65. rein_agentic_kit-0.7.1/tests/test_verify_commands.py +423 -0
  66. rein_agentic_kit-0.7.1/tests/test_verify_policy.py +768 -0
  67. rein_agentic_kit-0.7.1/tests/test_version_lock.py +51 -0
  68. rein_agentic_kit-0.7.1/tests/test_version_staleness.py +351 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Luis Farfan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,340 @@
1
+ Metadata-Version: 2.4
2
+ Name: rein-agentic-kit
3
+ Version: 0.7.1
4
+ Summary: Rein — keep your Claude Code agents lean and in control. Token-lean, stack-aware agentic dev flow.
5
+ Author: Luis Farfan
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/luisfarfan/rein-agentic-kit
8
+ Project-URL: Source, https://github.com/luisfarfan/rein-agentic-kit
9
+ Keywords: claude,claude-code,agents,tokens,cost,review,planning
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Software Development :: Quality Assurance
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ <div align="center">
22
+
23
+ # 🐎 Rein
24
+
25
+ **Keep your Claude Code agents lean and in control.**
26
+
27
+ A Claude Code plugin that turns agent work into a bounded, measured, independently-reviewed flow —
28
+ and tells you what it actually cost, per model.
29
+
30
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
31
+ [![CI](https://github.com/luisfarfan/rein-agentic-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/luisfarfan/rein-agentic-kit/actions/workflows/ci.yml)
32
+ [![Dependencies](https://img.shields.io/badge/runtime%20deps-none-success.svg)](#)
33
+ [![Python](https://img.shields.io/badge/python-3.9%2B%20stdlib-blue.svg)](#)
34
+ [![Claude Code](https://img.shields.io/badge/Claude%20Code-plugin-8A2BE2.svg)](https://claude.com/claude-code)
35
+
36
+ </div>
37
+
38
+ ---
39
+
40
+ ## 💸 The problem, measured
41
+
42
+ Optimizing agent cost by "making the model write less" does nothing. Over real Claude Code
43
+ transcripts:
44
+
45
+ | Where the tokens go | Share |
46
+ |---|---:|
47
+ | 🔴 `cache_read` — context re-read **every turn** | **~90%** |
48
+ | 🟠 `cache_write` | ~10% |
49
+ | 🟢 **output** — what a compressor would attack | **~0.3%** |
50
+ | ⚪ fresh input | ~0% |
51
+
52
+ **Cost ≈ turns × context size.** One agent that ran 241 turns, re-reading ~234k of context on
53
+ every single turn, was most of a 112M-token run.
54
+
55
+ And Claude Code has **no native eviction of stale tool results** — only `/compact`, which is
56
+ lossy and breaks the prompt cache. A long agent's context only grows.
57
+
58
+ > **Measured effect of this kit: 241 turns → 26 · Opus 100% → 0% · ~7× less context per turn.**
59
+
60
+ ---
61
+
62
+ ## 🔁 The flow
63
+
64
+ ```mermaid
65
+ flowchart TD
66
+ A["🧭 /rein:plan<br/><i>Why · Scope · Decisions · Tasks</i>"]
67
+ B{{"rein next<br/><i>deterministic gate</i>"}}
68
+ C["⚙️ Implement<br/><i>bounded loop of FRESH agents</i><br/><i>context resets each step</i>"]
69
+ D{{"Verify<br/><i>ask the plan, not the agent</i>"}}
70
+ E["🔍 /rein:review<br/><i>whole change · 5 axes</i>"]
71
+ F["✅ merge"]
72
+ G["✋ escalate to you"]
73
+ X["🛑 stop"]
74
+
75
+ A -->|you confirm| B
76
+ B -->|ready| C
77
+ C --> D
78
+ D -->|contradiction| X
79
+ D -->|consistent| E
80
+ E -->|"APPROVED + gate green"| F
81
+ E -->|"needs your judgement"| G
82
+ E -->|"CHANGES_REQUESTED · max 3"| C
83
+
84
+ style A fill:#1e3a5f,stroke:#4a90d9,color:#fff
85
+ style C fill:#1e4620,stroke:#4caf50,color:#fff
86
+ style E fill:#5f1e3a,stroke:#d94a90,color:#fff
87
+ style F fill:#2d4a1e,stroke:#8bc34a,color:#fff
88
+ style X fill:#4a1e1e,stroke:#d94a4a,color:#fff
89
+ style G fill:#4a3a1e,stroke:#d9a94a,color:#fff
90
+ ```
91
+
92
+ Three roles, and **no agent approves its own implementation**. Every run works in its own git
93
+ worktree; unapproved work is never merged.
94
+
95
+ ---
96
+
97
+ ## 🚀 Quickstart
98
+
99
+ ```bash
100
+ claude plugin marketplace add luisfarfan/rein-agentic-kit
101
+ ```
102
+
103
+ ```bash
104
+ claude plugin install rein@rein-agentic-kit --scope user
105
+ ```
106
+
107
+ **Restart Claude Code**, then run inside it:
108
+
109
+ ```
110
+ /rein:ping → is it wired here, and what did it detect?
111
+ /rein:setup → probe the optional tools · confirm to provision them
112
+ ```
113
+
114
+ `ping` reports the detected stack, the resolved commands and where each one
115
+ came from. **If it got everything right, you configure nothing.**
116
+
117
+ > **Everything runs inside Claude Code — there is nothing to add to your `$PATH`.**
118
+ > Claude Code puts the plugin's `bin/` on the path of its own sessions, which is
119
+ > where the skills, the commands and the agents call `rein`. In a plain terminal
120
+ > `rein` will *not* be found, and that is expected: the CLI exists to be called by
121
+ > the flow, and the two commands a person runs by hand have slash commands above.
122
+ ### Want `rein` in your own terminal too?
123
+
124
+ The plugin's `bin/` is only on the path of Claude Code's own sessions — a plugin
125
+ cannot add anything to your shell. For `rein dashboard`, `rein ledger` or
126
+ `rein doctor` from a terminal, install the CLI the way every tool this kit
127
+ integrates ships (serena and graphify via `uv`, codegraph and openspec via `npm`):
128
+
129
+ ```bash
130
+ uv tool install rein-agentic-kit # or: pipx install rein-agentic-kit
131
+ ```
132
+
133
+ Same code, same version, zero dependencies. The two channels cannot drift: a
134
+ test fails the build if their version strings ever disagree.
135
+
136
+ > To update: `claude plugin marketplace update rein-agentic-kit` then
137
+ > `claude plugin update rein@rein-agentic-kit` — qualified with the marketplace,
138
+ > or it reports `Plugin "rein" not found`.
139
+
140
+ Then, per change:
141
+
142
+ ```
143
+ /rein:plan → you confirm the plan → /rein:loop → read the verdict
144
+ ```
145
+
146
+ You come back when it finished, not before.
147
+
148
+ ---
149
+
150
+ ## 🧰 What you get
151
+
152
+ ### Skills — the three roles
153
+
154
+ | | |
155
+ |---|---|
156
+ | 🎭 **`/rein:role`** | Assign this session's role: planner · implementer · reviewer |
157
+ | 🧭 **`/rein:plan`** | Plan into verifiable tasks — dry-run and **explicit confirmation** before writing |
158
+ | 🔨 **`/rein:run`** | Exactly **one** task. Max 3 attempts, max 5 failed commands, no self-approval |
159
+ | 🔁 **`/rein:run-auto`** | Bounded loop of `run`, stopping on **verifiable signals** only |
160
+ | 🔍 **`/rein:review`** | The independent gate: mechanical checks first, then five-axis judgement |
161
+ | ♾️ **`/rein:loop`** | Runs all three end-to-end in an isolated worktree |
162
+
163
+ ### CLI — the deterministic half
164
+
165
+ ```bash
166
+ rein doctor # 🩺 start here: stack, resolved commands, and the source of each
167
+ # plus a "version : <verdict> -- <reason>" line -- up-to-date / stale /
168
+ # unknown against the marketplace clone, with fix commands when stale
169
+ # --json: {"version", "pluginRoot", "project", "plan", "verifyState",
170
+ # "ledger", "staleness"} -- staleness is {"verdict", "reason",
171
+ # "installedVersion", "availableVersion"}
172
+ rein setup # probe the optional tools · --install provisions what is missing
173
+ rein detect # stack + commands, with the source of each
174
+ rein tasks # the plan, parsed
175
+ rein context # detect + plan in ONE round-trip — what the loop's first agent runs
176
+ rein verify # actually RUN each resolved command and report the truth — an inference is not a fact
177
+ rein next # ✅ the gate: is there a task to claim, and may it be
178
+ rein close T001 # tick a checkbox deterministically — no agent hand-edits the plan
179
+ rein review # record / check a verdict bound to a code state
180
+ rein token-report# what a run really cost, per agent and per model
181
+ rein ledger # history across projects, with deltas vs a marked baseline
182
+ # --json: {"runs": [...], "events_by_project": {...}} -- runs are
183
+ # unchanged row objects; events (D3) are counted separately, never
184
+ # folded into a run total
185
+ rein baseline # mark the run everything is compared against
186
+ rein dashboard # 📊 serve it all as a local page
187
+ ```
188
+
189
+ > **The rule that separates them:** if it's a *parse*, a script does it. If it's a *judgement*,
190
+ > an agent does it. Every fact an agent doesn't have to rediscover is turns you don't pay for.
191
+
192
+ ---
193
+
194
+ ## ⚖️ The three levers
195
+
196
+ **1️⃣ Bounded loop of fresh agents.** Each task is at most *N* short, fresh agents handing off a
197
+ **compact ledger** (`progress` / `remaining` / `filesTouched` / `verification`) — never one agent
198
+ running 200+ turns. Context **resets at every boundary**, so spend stops growing without a ceiling.
199
+
200
+ **2️⃣ Per-agent model routing.** Mechanical → Haiku · code → Sonnet · the review gate → Opus. On a
201
+ subscription this doesn't lower the bill — it frees the **scarce Opus quota**, which is the limit
202
+ you actually hit.
203
+
204
+ **3️⃣ Verifiable signals, not model judgement.** A loop that stops when the model *feels* finished
205
+ has no gate. `rein next` answers "is there work to claim" from the plan; `rein review check`
206
+ answers "does this approval still apply" from content hashes. Neither asks a model anything.
207
+
208
+ ### ❌ Deliberately not included
209
+
210
+ Tried and discarded **with data**, not taste:
211
+
212
+ - **Output compressors** — they attack the 0.3%.
213
+ - **Multi-provider API swarms** — the saving doesn't apply on a subscription, and more agents means
214
+ more contexts re-read.
215
+ - **Cross-session memory tools** — orthogonal to the actual cost driver.
216
+ - **Cache-aware proxies** — no-op on already-cached traffic.
217
+ - **Persona prompts** ("you are a hexagonal architecture expert") — the same model with the same
218
+ weights. Constraints that can be *violated* are useful; job titles are not.
219
+
220
+ ---
221
+
222
+ ## ⚙️ Configure
223
+
224
+ Everything is optional. Drop a `flow.config.json` at your project root to override:
225
+
226
+ ```json
227
+ {
228
+ "commands": {
229
+ "test": "uv run pytest -q",
230
+ "testOne": "uv run pytest -q {target}",
231
+ "lint": "uv run ruff check .",
232
+ "typecheck": "uv run mypy ."
233
+ },
234
+ "models": { "aux": "haiku", "impl": "sonnet", "review": "opus" },
235
+ "limits": { "maxTaskSteps": 8, "maxReviewRounds": 3 }
236
+ }
237
+ ```
238
+
239
+ **Precedence:** `flow.config.json` › task runner (`justfile` / `Makefile` / `Taskfile`) ›
240
+ autodetection. A project that already declares how it is built is never second-guessed.
241
+
242
+ ## 🧱 Supported stacks
243
+
244
+ | Stack | Detected by | Verification |
245
+ |---|---|---|
246
+ | 🐍 Python | `pyproject.toml`, uv / poetry | pytest · ruff · mypy |
247
+ | 🟨 Node / TS | `package.json`, pnpm / npm / yarn / bun | vitest or jest · eslint · tsc |
248
+ | 🦀 Rust | `Cargo.toml` | cargo test · clippy · check |
249
+ | 🐹 Go | `go.mod` | go test · vet |
250
+ | 🎨 **Frontend** *(Next, Vite, Astro, SvelteKit, Nuxt, Remix)* | dependencies | **rendered verification** — unit tests alone don't catch "the tests pass but the UI is broken" |
251
+ | ☁️ Serverless / infra | `serverless.yml`, `sst.config.ts`, `*.tf` | `plan` / `validate` — **never deploy** |
252
+ | 📦 Monorepo | sub-projects one or two levels down, no root manifest | reports each sub-project and its own commands — **it never picks one for you**, even when there is only one candidate |
253
+
254
+ > **A resolved command is an inference until something runs it.** `rein verify` executes each one
255
+ > and reports what happened, distinguishing *"the binary is missing"* (a **setup** problem) from
256
+ > *"the suite ran and failed"* (a **code** problem) — conflating them sends you to the wrong file.
257
+ > The loop runs it at Prepare: a broken gate found there costs nothing, the same one found at
258
+ > review costs a whole run.
259
+
260
+ Optional tools (`serena`, `codegraph`, `graphify`, `openspec`) are **probed, never
261
+ required**: if one is absent the flow degrades, it does not break. `rein setup` reports
262
+ what is missing and installs it on request — and distinguishes *installed* from *usable*,
263
+ because graphify without an index and a just-registered MCP server are both present and
264
+ inert.
265
+
266
+ > **No retrieval speedup is claimed.** With codegraph present, the loop's implementers are
267
+ > taught `codegraph query` / `callers` / `callees` / `node` / `impact` (plus `sync` to
268
+ > refresh the index after their own edits) as the one owner of "what is this / who touches
269
+ > it / what breaks if I change it"; with codegraph absent, serena's `get_symbols_overview` /
270
+ > `find_symbol` / `find_referencing_symbols` cover the same ground as a fallback. Whether
271
+ > either reduces the turns an agent spends orienting is **unmeasured**, and the one control
272
+ > available points the other way. See [docs/decisions.md](docs/decisions.md) D2.
273
+
274
+ **One owner per question.** A tool is dropped from the prompts for having no *exclusive*
275
+ question — not for being bad:
276
+
277
+ ```mermaid
278
+ flowchart LR
279
+ 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>"]
280
+ Q2["❓ edit this symbol<br/>type errors, no build"] --> SE["✏️ serena<br/><i>replace_symbol_body</i><br/><i>get_diagnostics_for_file</i>"]
281
+ Q3["❓ docs · papers · images"] --> GR["📚 graphify<br/><i>/graphify skill</i><br/><i>outside the loop</i>"]
282
+
283
+ style CG fill:#1e4620,stroke:#4caf50,color:#fff
284
+ style SE fill:#1e3a5f,stroke:#4a90d9,color:#fff
285
+ style GR fill:#4a3a1e,stroke:#d9a94a,color:#fff
286
+ ```
287
+
288
+ Measured on this repo, same question, same index cost (~1.5s, no LLM, no API key for either):
289
+ asked *"where is it decided that a command is not invocable?"*, codegraph returns
290
+ `NOT_INVOCABLE_EXIT_CODES = (126,127)` with its file and line in **258 tokens**; the graph
291
+ tool it replaced returned **546 tokens of an unrelated example config**, because a JSON key
292
+ happened to match. Confident noise is worse for an agent than no answer — it cannot tell the
293
+ two apart, and it pays for the difference on every later turn.
294
+
295
+ ## 📊 Measure
296
+
297
+ ```bash
298
+ rein token-report && rein dashboard
299
+ ```
300
+
301
+ Reads Claude Code's own JSONL transcripts (including `cache_read`) and breaks a run down per
302
+ agent and **per model**. Every run is summarized into `~/.claude/rein/runs.jsonl`, so history
303
+ survives transcript rotation.
304
+
305
+ **On the word "savings":** this measures *consumption*. A saving needs a baseline. Mark one with
306
+ `rein baseline mark` and every later run in that project gets a signed delta. Without one, the
307
+ honest numbers are the three that predict cost — **turns/agent**, **ctx_max/turn**,
308
+ **% of tokens on Opus**.
309
+
310
+ ---
311
+
312
+ ## 🙃 Honest limitations
313
+
314
+ Things a README usually hides:
315
+
316
+ - **The reviewer is calibrated hard.** 4 of 6 runs here exhausted their 3 rounds. A three-task
317
+ change will often use them all.
318
+ - **A stalled agent burns wall-clock.** One run spent 3.4 hours almost entirely in silent API
319
+ retries.
320
+ - **`discover` was considered and rejected** — a per-run version of it was measured in the origin
321
+ project and did not move the needle. See [docs/decisions.md](docs/decisions.md).
322
+
323
+ ## 🗺️ Roadmap
324
+
325
+ | Phase | Scope | |
326
+ |---|---|---|
327
+ | 0 | Plugin plumbing · `token-report` · ledger · stack detection | ✅ [findings](docs/phase-0-findings.md) |
328
+ | 1 | Config-driven core loop · `tasks.md` adapter — **measured** | ✅ |
329
+ | 2 | Stack-aware verification policy | ✅ |
330
+ | 3 | Local dashboard · per-agent model config | ✅ |
331
+ | 4 | Compose real browser verification | ✅ |
332
+ | 5 | Docs · polish · a second real-world project | ⏳ |
333
+
334
+ ## 📄 License
335
+
336
+ MIT — see [LICENSE](LICENSE).
337
+
338
+ <div align="center">
339
+ <sub>Built with Claude Code, reviewed by an agent that wrote none of it.</sub>
340
+ </div>
@@ -0,0 +1,320 @@
1
+ <div align="center">
2
+
3
+ # 🐎 Rein
4
+
5
+ **Keep your Claude Code agents lean and in control.**
6
+
7
+ A Claude Code plugin that turns agent work into a bounded, measured, independently-reviewed flow —
8
+ and tells you what it actually cost, per model.
9
+
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
11
+ [![CI](https://github.com/luisfarfan/rein-agentic-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/luisfarfan/rein-agentic-kit/actions/workflows/ci.yml)
12
+ [![Dependencies](https://img.shields.io/badge/runtime%20deps-none-success.svg)](#)
13
+ [![Python](https://img.shields.io/badge/python-3.9%2B%20stdlib-blue.svg)](#)
14
+ [![Claude Code](https://img.shields.io/badge/Claude%20Code-plugin-8A2BE2.svg)](https://claude.com/claude-code)
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## 💸 The problem, measured
21
+
22
+ Optimizing agent cost by "making the model write less" does nothing. Over real Claude Code
23
+ transcripts:
24
+
25
+ | Where the tokens go | Share |
26
+ |---|---:|
27
+ | 🔴 `cache_read` — context re-read **every turn** | **~90%** |
28
+ | 🟠 `cache_write` | ~10% |
29
+ | 🟢 **output** — what a compressor would attack | **~0.3%** |
30
+ | ⚪ fresh input | ~0% |
31
+
32
+ **Cost ≈ turns × context size.** One agent that ran 241 turns, re-reading ~234k of context on
33
+ every single turn, was most of a 112M-token run.
34
+
35
+ And Claude Code has **no native eviction of stale tool results** — only `/compact`, which is
36
+ lossy and breaks the prompt cache. A long agent's context only grows.
37
+
38
+ > **Measured effect of this kit: 241 turns → 26 · Opus 100% → 0% · ~7× less context per turn.**
39
+
40
+ ---
41
+
42
+ ## 🔁 The flow
43
+
44
+ ```mermaid
45
+ flowchart TD
46
+ A["🧭 /rein:plan<br/><i>Why · Scope · Decisions · Tasks</i>"]
47
+ B{{"rein next<br/><i>deterministic gate</i>"}}
48
+ C["⚙️ Implement<br/><i>bounded loop of FRESH agents</i><br/><i>context resets each step</i>"]
49
+ D{{"Verify<br/><i>ask the plan, not the agent</i>"}}
50
+ E["🔍 /rein:review<br/><i>whole change · 5 axes</i>"]
51
+ F["✅ merge"]
52
+ G["✋ escalate to you"]
53
+ X["🛑 stop"]
54
+
55
+ A -->|you confirm| B
56
+ B -->|ready| C
57
+ C --> D
58
+ D -->|contradiction| X
59
+ D -->|consistent| E
60
+ E -->|"APPROVED + gate green"| F
61
+ E -->|"needs your judgement"| G
62
+ E -->|"CHANGES_REQUESTED · max 3"| C
63
+
64
+ style A fill:#1e3a5f,stroke:#4a90d9,color:#fff
65
+ style C fill:#1e4620,stroke:#4caf50,color:#fff
66
+ style E fill:#5f1e3a,stroke:#d94a90,color:#fff
67
+ style F fill:#2d4a1e,stroke:#8bc34a,color:#fff
68
+ style X fill:#4a1e1e,stroke:#d94a4a,color:#fff
69
+ style G fill:#4a3a1e,stroke:#d9a94a,color:#fff
70
+ ```
71
+
72
+ Three roles, and **no agent approves its own implementation**. Every run works in its own git
73
+ worktree; unapproved work is never merged.
74
+
75
+ ---
76
+
77
+ ## 🚀 Quickstart
78
+
79
+ ```bash
80
+ claude plugin marketplace add luisfarfan/rein-agentic-kit
81
+ ```
82
+
83
+ ```bash
84
+ claude plugin install rein@rein-agentic-kit --scope user
85
+ ```
86
+
87
+ **Restart Claude Code**, then run inside it:
88
+
89
+ ```
90
+ /rein:ping → is it wired here, and what did it detect?
91
+ /rein:setup → probe the optional tools · confirm to provision them
92
+ ```
93
+
94
+ `ping` reports the detected stack, the resolved commands and where each one
95
+ came from. **If it got everything right, you configure nothing.**
96
+
97
+ > **Everything runs inside Claude Code — there is nothing to add to your `$PATH`.**
98
+ > Claude Code puts the plugin's `bin/` on the path of its own sessions, which is
99
+ > where the skills, the commands and the agents call `rein`. In a plain terminal
100
+ > `rein` will *not* be found, and that is expected: the CLI exists to be called by
101
+ > the flow, and the two commands a person runs by hand have slash commands above.
102
+ ### Want `rein` in your own terminal too?
103
+
104
+ The plugin's `bin/` is only on the path of Claude Code's own sessions — a plugin
105
+ cannot add anything to your shell. For `rein dashboard`, `rein ledger` or
106
+ `rein doctor` from a terminal, install the CLI the way every tool this kit
107
+ integrates ships (serena and graphify via `uv`, codegraph and openspec via `npm`):
108
+
109
+ ```bash
110
+ uv tool install rein-agentic-kit # or: pipx install rein-agentic-kit
111
+ ```
112
+
113
+ Same code, same version, zero dependencies. The two channels cannot drift: a
114
+ test fails the build if their version strings ever disagree.
115
+
116
+ > To update: `claude plugin marketplace update rein-agentic-kit` then
117
+ > `claude plugin update rein@rein-agentic-kit` — qualified with the marketplace,
118
+ > or it reports `Plugin "rein" not found`.
119
+
120
+ Then, per change:
121
+
122
+ ```
123
+ /rein:plan → you confirm the plan → /rein:loop → read the verdict
124
+ ```
125
+
126
+ You come back when it finished, not before.
127
+
128
+ ---
129
+
130
+ ## 🧰 What you get
131
+
132
+ ### Skills — the three roles
133
+
134
+ | | |
135
+ |---|---|
136
+ | 🎭 **`/rein:role`** | Assign this session's role: planner · implementer · reviewer |
137
+ | 🧭 **`/rein:plan`** | Plan into verifiable tasks — dry-run and **explicit confirmation** before writing |
138
+ | 🔨 **`/rein:run`** | Exactly **one** task. Max 3 attempts, max 5 failed commands, no self-approval |
139
+ | 🔁 **`/rein:run-auto`** | Bounded loop of `run`, stopping on **verifiable signals** only |
140
+ | 🔍 **`/rein:review`** | The independent gate: mechanical checks first, then five-axis judgement |
141
+ | ♾️ **`/rein:loop`** | Runs all three end-to-end in an isolated worktree |
142
+
143
+ ### CLI — the deterministic half
144
+
145
+ ```bash
146
+ rein doctor # 🩺 start here: stack, resolved commands, and the source of each
147
+ # plus a "version : <verdict> -- <reason>" line -- up-to-date / stale /
148
+ # unknown against the marketplace clone, with fix commands when stale
149
+ # --json: {"version", "pluginRoot", "project", "plan", "verifyState",
150
+ # "ledger", "staleness"} -- staleness is {"verdict", "reason",
151
+ # "installedVersion", "availableVersion"}
152
+ rein setup # probe the optional tools · --install provisions what is missing
153
+ rein detect # stack + commands, with the source of each
154
+ rein tasks # the plan, parsed
155
+ rein context # detect + plan in ONE round-trip — what the loop's first agent runs
156
+ rein verify # actually RUN each resolved command and report the truth — an inference is not a fact
157
+ rein next # ✅ the gate: is there a task to claim, and may it be
158
+ rein close T001 # tick a checkbox deterministically — no agent hand-edits the plan
159
+ rein review # record / check a verdict bound to a code state
160
+ rein token-report# what a run really cost, per agent and per model
161
+ rein ledger # history across projects, with deltas vs a marked baseline
162
+ # --json: {"runs": [...], "events_by_project": {...}} -- runs are
163
+ # unchanged row objects; events (D3) are counted separately, never
164
+ # folded into a run total
165
+ rein baseline # mark the run everything is compared against
166
+ rein dashboard # 📊 serve it all as a local page
167
+ ```
168
+
169
+ > **The rule that separates them:** if it's a *parse*, a script does it. If it's a *judgement*,
170
+ > an agent does it. Every fact an agent doesn't have to rediscover is turns you don't pay for.
171
+
172
+ ---
173
+
174
+ ## ⚖️ The three levers
175
+
176
+ **1️⃣ Bounded loop of fresh agents.** Each task is at most *N* short, fresh agents handing off a
177
+ **compact ledger** (`progress` / `remaining` / `filesTouched` / `verification`) — never one agent
178
+ running 200+ turns. Context **resets at every boundary**, so spend stops growing without a ceiling.
179
+
180
+ **2️⃣ Per-agent model routing.** Mechanical → Haiku · code → Sonnet · the review gate → Opus. On a
181
+ subscription this doesn't lower the bill — it frees the **scarce Opus quota**, which is the limit
182
+ you actually hit.
183
+
184
+ **3️⃣ Verifiable signals, not model judgement.** A loop that stops when the model *feels* finished
185
+ has no gate. `rein next` answers "is there work to claim" from the plan; `rein review check`
186
+ answers "does this approval still apply" from content hashes. Neither asks a model anything.
187
+
188
+ ### ❌ Deliberately not included
189
+
190
+ Tried and discarded **with data**, not taste:
191
+
192
+ - **Output compressors** — they attack the 0.3%.
193
+ - **Multi-provider API swarms** — the saving doesn't apply on a subscription, and more agents means
194
+ more contexts re-read.
195
+ - **Cross-session memory tools** — orthogonal to the actual cost driver.
196
+ - **Cache-aware proxies** — no-op on already-cached traffic.
197
+ - **Persona prompts** ("you are a hexagonal architecture expert") — the same model with the same
198
+ weights. Constraints that can be *violated* are useful; job titles are not.
199
+
200
+ ---
201
+
202
+ ## ⚙️ Configure
203
+
204
+ Everything is optional. Drop a `flow.config.json` at your project root to override:
205
+
206
+ ```json
207
+ {
208
+ "commands": {
209
+ "test": "uv run pytest -q",
210
+ "testOne": "uv run pytest -q {target}",
211
+ "lint": "uv run ruff check .",
212
+ "typecheck": "uv run mypy ."
213
+ },
214
+ "models": { "aux": "haiku", "impl": "sonnet", "review": "opus" },
215
+ "limits": { "maxTaskSteps": 8, "maxReviewRounds": 3 }
216
+ }
217
+ ```
218
+
219
+ **Precedence:** `flow.config.json` › task runner (`justfile` / `Makefile` / `Taskfile`) ›
220
+ autodetection. A project that already declares how it is built is never second-guessed.
221
+
222
+ ## 🧱 Supported stacks
223
+
224
+ | Stack | Detected by | Verification |
225
+ |---|---|---|
226
+ | 🐍 Python | `pyproject.toml`, uv / poetry | pytest · ruff · mypy |
227
+ | 🟨 Node / TS | `package.json`, pnpm / npm / yarn / bun | vitest or jest · eslint · tsc |
228
+ | 🦀 Rust | `Cargo.toml` | cargo test · clippy · check |
229
+ | 🐹 Go | `go.mod` | go test · vet |
230
+ | 🎨 **Frontend** *(Next, Vite, Astro, SvelteKit, Nuxt, Remix)* | dependencies | **rendered verification** — unit tests alone don't catch "the tests pass but the UI is broken" |
231
+ | ☁️ Serverless / infra | `serverless.yml`, `sst.config.ts`, `*.tf` | `plan` / `validate` — **never deploy** |
232
+ | 📦 Monorepo | sub-projects one or two levels down, no root manifest | reports each sub-project and its own commands — **it never picks one for you**, even when there is only one candidate |
233
+
234
+ > **A resolved command is an inference until something runs it.** `rein verify` executes each one
235
+ > and reports what happened, distinguishing *"the binary is missing"* (a **setup** problem) from
236
+ > *"the suite ran and failed"* (a **code** problem) — conflating them sends you to the wrong file.
237
+ > The loop runs it at Prepare: a broken gate found there costs nothing, the same one found at
238
+ > review costs a whole run.
239
+
240
+ Optional tools (`serena`, `codegraph`, `graphify`, `openspec`) are **probed, never
241
+ required**: if one is absent the flow degrades, it does not break. `rein setup` reports
242
+ what is missing and installs it on request — and distinguishes *installed* from *usable*,
243
+ because graphify without an index and a just-registered MCP server are both present and
244
+ inert.
245
+
246
+ > **No retrieval speedup is claimed.** With codegraph present, the loop's implementers are
247
+ > taught `codegraph query` / `callers` / `callees` / `node` / `impact` (plus `sync` to
248
+ > refresh the index after their own edits) as the one owner of "what is this / who touches
249
+ > it / what breaks if I change it"; with codegraph absent, serena's `get_symbols_overview` /
250
+ > `find_symbol` / `find_referencing_symbols` cover the same ground as a fallback. Whether
251
+ > either reduces the turns an agent spends orienting is **unmeasured**, and the one control
252
+ > available points the other way. See [docs/decisions.md](docs/decisions.md) D2.
253
+
254
+ **One owner per question.** A tool is dropped from the prompts for having no *exclusive*
255
+ question — not for being bad:
256
+
257
+ ```mermaid
258
+ flowchart LR
259
+ 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>"]
260
+ Q2["❓ edit this symbol<br/>type errors, no build"] --> SE["✏️ serena<br/><i>replace_symbol_body</i><br/><i>get_diagnostics_for_file</i>"]
261
+ Q3["❓ docs · papers · images"] --> GR["📚 graphify<br/><i>/graphify skill</i><br/><i>outside the loop</i>"]
262
+
263
+ style CG fill:#1e4620,stroke:#4caf50,color:#fff
264
+ style SE fill:#1e3a5f,stroke:#4a90d9,color:#fff
265
+ style GR fill:#4a3a1e,stroke:#d9a94a,color:#fff
266
+ ```
267
+
268
+ Measured on this repo, same question, same index cost (~1.5s, no LLM, no API key for either):
269
+ asked *"where is it decided that a command is not invocable?"*, codegraph returns
270
+ `NOT_INVOCABLE_EXIT_CODES = (126,127)` with its file and line in **258 tokens**; the graph
271
+ tool it replaced returned **546 tokens of an unrelated example config**, because a JSON key
272
+ happened to match. Confident noise is worse for an agent than no answer — it cannot tell the
273
+ two apart, and it pays for the difference on every later turn.
274
+
275
+ ## 📊 Measure
276
+
277
+ ```bash
278
+ rein token-report && rein dashboard
279
+ ```
280
+
281
+ Reads Claude Code's own JSONL transcripts (including `cache_read`) and breaks a run down per
282
+ agent and **per model**. Every run is summarized into `~/.claude/rein/runs.jsonl`, so history
283
+ survives transcript rotation.
284
+
285
+ **On the word "savings":** this measures *consumption*. A saving needs a baseline. Mark one with
286
+ `rein baseline mark` and every later run in that project gets a signed delta. Without one, the
287
+ honest numbers are the three that predict cost — **turns/agent**, **ctx_max/turn**,
288
+ **% of tokens on Opus**.
289
+
290
+ ---
291
+
292
+ ## 🙃 Honest limitations
293
+
294
+ Things a README usually hides:
295
+
296
+ - **The reviewer is calibrated hard.** 4 of 6 runs here exhausted their 3 rounds. A three-task
297
+ change will often use them all.
298
+ - **A stalled agent burns wall-clock.** One run spent 3.4 hours almost entirely in silent API
299
+ retries.
300
+ - **`discover` was considered and rejected** — a per-run version of it was measured in the origin
301
+ project and did not move the needle. See [docs/decisions.md](docs/decisions.md).
302
+
303
+ ## 🗺️ Roadmap
304
+
305
+ | Phase | Scope | |
306
+ |---|---|---|
307
+ | 0 | Plugin plumbing · `token-report` · ledger · stack detection | ✅ [findings](docs/phase-0-findings.md) |
308
+ | 1 | Config-driven core loop · `tasks.md` adapter — **measured** | ✅ |
309
+ | 2 | Stack-aware verification policy | ✅ |
310
+ | 3 | Local dashboard · per-agent model config | ✅ |
311
+ | 4 | Compose real browser verification | ✅ |
312
+ | 5 | Docs · polish · a second real-world project | ⏳ |
313
+
314
+ ## 📄 License
315
+
316
+ MIT — see [LICENSE](LICENSE).
317
+
318
+ <div align="center">
319
+ <sub>Built with Claude Code, reviewed by an agent that wrote none of it.</sub>
320
+ </div>