@jjanczur/tyran 0.1.0

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 (54) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +22 -0
  3. package/CHANGELOG.md +245 -0
  4. package/LICENSE +201 -0
  5. package/README.md +468 -0
  6. package/agents/.gitkeep +0 -0
  7. package/agents/implementer.md +60 -0
  8. package/agents/retro.md +88 -0
  9. package/agents/reviewer.md +55 -0
  10. package/agents/scout.md +60 -0
  11. package/bin/tyran.mjs +172 -0
  12. package/hooks/HOOK-CONTRACT-MEASURED.md +377 -0
  13. package/hooks/hooks.json +83 -0
  14. package/hooks/scripts/.gitkeep +0 -0
  15. package/hooks/scripts/evidence-gate.mjs +705 -0
  16. package/hooks/scripts/hook-io.mjs +813 -0
  17. package/hooks/scripts/policy-gate.mjs +1402 -0
  18. package/hooks/scripts/pre-compact.mjs +211 -0
  19. package/hooks/scripts/retro-gate.mjs +191 -0
  20. package/hooks/scripts/secrets-gate.mjs +1683 -0
  21. package/hooks/scripts/session-start.mjs +358 -0
  22. package/hooks/scripts/write-guard.mjs +475 -0
  23. package/package.json +52 -0
  24. package/scripts/desc-budget.mjs +139 -0
  25. package/scripts/doctor.mjs +1267 -0
  26. package/scripts/hooks-check.mjs +1312 -0
  27. package/scripts/invisible.mjs +346 -0
  28. package/scripts/journal.mjs +747 -0
  29. package/scripts/project.mjs +981 -0
  30. package/scripts/scan-control-chars.mjs +547 -0
  31. package/scripts/scan-repo.mjs +287 -0
  32. package/scripts/schema.mjs +467 -0
  33. package/scripts/stop-check.mjs +89 -0
  34. package/scripts/tiers.mjs +324 -0
  35. package/scripts/yaml-lite.mjs +383 -0
  36. package/skills/browser-check/SKILL.md +118 -0
  37. package/skills/code-review/SKILL.md +83 -0
  38. package/skills/deslop/SKILL.md +97 -0
  39. package/skills/doctor/SKILL.md +35 -0
  40. package/skills/fidelity-gate/SKILL.md +132 -0
  41. package/skills/hello/SKILL.md +16 -0
  42. package/skills/pr-feedback/SKILL.md +85 -0
  43. package/skills/prompt-tuning/SKILL.md +102 -0
  44. package/skills/retro/SKILL.md +69 -0
  45. package/skills/root-cause/SKILL.md +89 -0
  46. package/skills/run/SKILL.md +285 -0
  47. package/skills/setup/SKILL.md +79 -0
  48. package/skills/skill-writing/SKILL.md +99 -0
  49. package/skills/status/SKILL.md +31 -0
  50. package/templates/.gitkeep +0 -0
  51. package/templates/config.yaml +44 -0
  52. package/templates/knowledge.yaml +23 -0
  53. package/templates/policies/autonomy.yaml +61 -0
  54. package/templates/project-command/SKILL.md +16 -0
package/README.md ADDED
@@ -0,0 +1,468 @@
1
+ <p align="center">
2
+ <img src="assets/banner.jpg" alt="Tyran โ€” a jackal-headed conductor driving a hall of agent workstations, each screen showing its own status: code optimization at 65%, a critical logic failure, data gathering stalled, self-improvement required" width="100%">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://github.com/jjanczur/tyran/actions/workflows/ci.yml"><img src="https://github.com/jjanczur/tyran/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
7
+ <a href="https://github.com/jjanczur/tyran/actions/workflows/security.yml"><img src="https://github.com/jjanczur/tyran/actions/workflows/security.yml/badge.svg" alt="Security"></a>
8
+ <img src="https://img.shields.io/badge/dependencies-0-success" alt="Zero dependencies">
9
+ <img src="https://img.shields.io/badge/Claude_Code-plugin-d4a017" alt="Claude Code plugin">
10
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="License: Apache-2.0"></a>
11
+ <a href="https://github.com/jjanczur/tyran/releases/latest"><img src="https://img.shields.io/github/v/release/jjanczur/tyran?color=d4a017" alt="Latest release"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <b><a href="https://jjanczur.github.io/tyran/">๐Ÿ“– Documentation</a></b> ยท
16
+ <a href="https://jjanczur.github.io/tyran/getting-started/">Getting started</a> ยท
17
+ <a href="https://jjanczur.github.io/tyran/architecture/">Architecture</a> ยท
18
+ <a href="https://github.com/jjanczur/tyran/releases/latest">Releases</a>
19
+ </p>
20
+
21
+ <h3 align="center">The more you use it, the better it gets.</h3>
22
+
23
+ <p align="center">
24
+ Tyran is a task conductor for Claude Code: it interviews you, plans, and drives a team of
25
+ fresh-context agents through your work โ€” <b>refusing to believe any agent that can't show
26
+ raw command output as proof</b>, routing every subtask to the cheapest model that can do
27
+ it, and keeping each agent in the context band where it still thinks clearly. When the
28
+ work is done, it will not let the initiative end until it has learned something from it.
29
+ </p>
30
+
31
+ ---
32
+
33
+ ## The Problem
34
+
35
+ Four failures, all of them ordinary, all of them silent. You will recognise
36
+ every one.
37
+
38
+
39
+ | | What happens | What it costs you |
40
+ |---|---|---|
41
+ | ๐ŸŸฅ **Fake green** | *"Done โ€” all tests pass."* Nothing was run. | You find out at review, or at deploy. The report was cheaper to write than the work. |
42
+ | ๐ŸŸฅ **Wrong model, wrong job** | The strongest, most expensive model renames a file, changes a button colour, runs a mechanical sweep. | You pay top rate for work any cheap tier does identically. Nobody notices, because it *worked*. |
43
+ | ๐ŸŸฅ **Context collapse** | Nobody compacts on purpose. The window fills to 60, 70%. Auto-compact then fires **in the middle of a hard debugging run**. | The fine detail the model had just discovered โ€” the thing that took an hour โ€” is gone, and it does not know it is gone. |
44
+ | ๐ŸŸฅ **Amnesia** | State lives in a chat window. Another dev, another branch, tomorrow morning โ€” none of them can see where this got to. | The work is re-derived, or worse, half re-derived. |
45
+
46
+ **Context collapse is the expensive one**, and it is worth being precise about
47
+ why. Above roughly half the window, the model is carrying so much that it
48
+ starts missing things it would have caught at 10%. And the compaction that
49
+ should relieve that pressure is the very thing that destroys the detail:
50
+
51
+ ```mermaid
52
+ flowchart LR
53
+ subgraph BAD["โŒ one agent carries everything"]
54
+ direction LR
55
+ B1["0%<br/>sharp"] --> B2["50%<br/>still fine"] --> B3["70%<br/>missing things"] --> B4["auto-compact<br/>mid-debug"] --> B5["detail gone โ€”<br/>and it does not<br/>know it is gone"]
56
+ end
57
+ classDef bad fill:#7f1d1d,stroke:#f87171,color:#fef2f2
58
+ classDef warn fill:#78350f,stroke:#fbbf24,color:#fffbeb
59
+ class B3,B4,B5 bad
60
+ class B2 warn
61
+ ```
62
+
63
+ ## The Solution
64
+
65
+ **Split the work so nobody has to carry all of it**, and put the state in a
66
+ file instead of a window:
67
+
68
+ ```mermaid
69
+ flowchart TB
70
+ OP(["you"]) -->|"describes the work"| C["<b>conductor</b><br/>plans ยท delegates ยท merges<br/><i>stays lean โ€” it holds the plan,<br/>not the transcripts</i>"]
71
+
72
+ C -->|"self-contained handoff"| S["<b>scout</b><br/>fresh context<br/><i>cheap tier</i>"]
73
+ C -->|"self-contained handoff"| I["<b>implementer</b><br/>fresh context ยท own worktree<br/><i>work tier</i>"]
74
+ C -->|"self-contained handoff"| R["<b>reviewer</b><br/>fresh context ยท never the author<br/><i>work tier, top tier on security</i>"]
75
+
76
+ S & I & R -->|"report"| G{{"โœ‹ EVIDENCE GATE<br/>raw command output,<br/>or the report is REFUSED"}}
77
+ G --> J[("append-only journal<br/>.tyran/ โ€” committed to YOUR repo")]
78
+ J -->|"survives restart,<br/>compaction, and you"| C
79
+ J --> D["another dev ยท another branch<br/>ยท tomorrow morning"]
80
+ J --> RT{{"โœ‹ RETRO GATE<br/>the initiative cannot end<br/>without learning something"}}
81
+ RT -->|"improves"| C
82
+
83
+ classDef gate fill:#7f1d1d,stroke:#f87171,color:#fef2f2
84
+ classDef store fill:#064e3b,stroke:#34d399,color:#ecfdf5
85
+ class G,RT gate
86
+ class J store
87
+ ```
88
+
89
+
90
+ Each of the four failures gets a mechanism, not a paragraph of advice:
91
+
92
+ | Failure | Mechanism | State |
93
+ |---|---|---|
94
+ | Fake green | A `SubagentStop` hook **rejects** a report with no raw command output. Measured on 55 real reports: 53 pass, and both misses were not reports. | โœ… shipped |
95
+ | Wrong model | Every role resolves to a tier from **one config file**. `top` โ€” the expensive one โ€” is reserved for security review, arbitration and acceptance, and a floor stops any profile or flag pushing those down. Effort is a **separate dial**: *same model, think harder* costs nothing extra. | โœ… shipped |
96
+ | Context collapse | Work goes to **fresh-context subagents** with self-contained handoffs, so the conductor never accumulates their transcripts. A `PreCompact` hook checkpoints before every compaction and **refuses a manual `/compact` it could not checkpoint**; `SessionStart` re-injects that checkpoint afterwards. | โœ… shipped ยท ๐ŸŽฏ a trigger that says *"compact now, this section is finished"* is **not built** |
97
+ | Amnesia | The journal is an append-only file **in your repo**, not in a window. `STATE.md` and `PROGRESS.md` are generated from it. Another agent, another dev, another branch reads where this got to โ€” including which agent is still running and which lease nobody released. | โœ… shipped |
98
+
99
+ **Cheap where it doesn't matter, expensive where it does.** That is the whole
100
+ cost argument, and it is why the routing table is a table and not a vibe:
101
+
102
+ ```mermaid
103
+ flowchart LR
104
+ T1["<b>cheap</b><br/>recon ยท sweeps ยท bookkeeping"] --- T2["<b>work</b><br/>implementation<br/>ordinary review<br/><i>the default</i>"] --- T3["<b>deep</b><br/>root-cause ยท hard builds<br/>risky review"] --- T4["<b>top</b><br/>security review<br/>arbitration ยท acceptance<br/><i>and nothing else</i>"]
105
+ classDef c fill:#064e3b,stroke:#34d399,color:#ecfdf5
106
+ classDef w fill:#1e3a5f,stroke:#60a5fa,color:#eff6ff
107
+ classDef d fill:#78350f,stroke:#fbbf24,color:#fffbeb
108
+ classDef t fill:#7f1d1d,stroke:#f87171,color:#fef2f2
109
+ class T1 c
110
+ class T2 w
111
+ class T3 d
112
+ class T4 t
113
+ ```
114
+
115
+ ### And then it gets better on its own
116
+
117
+ An initiative that ends without a retrospective is **refused one turn** by a
118
+ `Stop` hook. The retro reads the ledger, the notes and the agents' own
119
+ reports, and changes Tyran itself โ€” through a filter whose default answer is
120
+ *change nothing*, which prefers **deleting a rule to adding one**, and which
121
+ is explicitly told not to breed agents, because a roster nobody can hold in
122
+ their head is its own cognitive tax.
123
+
124
+ ```text
125
+ Initiative 1 Infers your stack, your validation commands, your deployment
126
+ style from how the repo is actually worked. Asks once, about
127
+ what it genuinely could not establish.
128
+ Initiative 5 Knows your shared-file hot zones, your flaky tests, your
129
+ review taste. Its retro has already DELETED two of its own
130
+ rules that weren't earning their keep.
131
+ Initiative 20 Has written repo-specific skills for your recurring work and
132
+ merged two agents that overlapped. You mostly approve gates.
133
+ ```
134
+
135
+ > **Three things are not built yet:** the update delta-review, cost-profile
136
+ > benchmark receipts, and overnight mode. Everything else on this page exists
137
+ > in code with tests behind it โ€” nothing here is claimed before it ships, and
138
+ > the [roadmap](#roadmap) says which is which.
139
+
140
+ ## Quick Start
141
+
142
+ ```text
143
+ /plugin marketplace add jjanczur/tyran
144
+ /plugin install tyran@tyran
145
+ /tyran:setup # scans the repo, writes .tyran/config.yaml, installs /tyran
146
+ /tyran # then just describe what you want done
147
+ ```
148
+
149
+ **Or paste this into Claude Code and let it install itself.** `/plugin` is a
150
+ slash command a human has to type, so this asks for the same two steps
151
+ through the `claude` CLI instead, which Claude Code can run on its own โ€”
152
+ followed by the restart those steps require, and a walkthrough of what setup
153
+ inferred before it is trusted:
154
+
155
+ ```text
156
+ Install the Tyran plugin in this repository and set it up for me.
157
+
158
+ 1. Run: claude plugin marketplace add jjanczur/tyran
159
+ 2. Run: claude plugin install tyran@tyran
160
+ 3. Tell me to restart Claude Code, so the hooks and agents load.
161
+ 4. After the restart, run /tyran:setup. It scans this repo and writes
162
+ .tyran/config.yaml. Walk me through what it inferred - especially the
163
+ validation commands and the deployment autonomy class - before we commit it.
164
+
165
+ Docs: https://jjanczur.github.io/tyran/getting-started/
166
+ ```
167
+
168
+ Setup infers your stack, your validation commands and your deployment
169
+ autonomy class from how the repo is actually worked, annotates every value
170
+ with the fact that produced it, and asks you only about what it genuinely
171
+ could not establish. It also installs the bare `/tyran` shortcut โ€” plugin
172
+ skills are namespaced, so the conductor is `/tyran:run`, and most people
173
+ would rather type four letters.
174
+
175
+ Then `/tyran` interviews you, sizes the work, and either does it itself
176
+ (small changes) or drives the roster โ€” `tyran:scout`, `tyran:implementer`,
177
+ `tyran:reviewer`, `tyran:retro` โ€” through it. Also: `/tyran:status`,
178
+ `/tyran:doctor`, `/tyran:retro`.
179
+
180
+ ### It is not only an orchestrator โ€” it ships skills you can use yourself
181
+
182
+ Fourteen skills and four agents come with the plugin. Six of the skills are
183
+ the conductor's own machinery, but they are **commands, not internals**: you
184
+ run `/tyran:doctor` on a repo you are debugging without ever starting an
185
+ initiative. The other eight are standalone protocols โ€” most of them have
186
+ nothing to do with orchestration and work perfectly well in a session that
187
+ never starts an initiative at all.
188
+
189
+ | Skill | What it does |
190
+ |---|---|
191
+ | [`run`](skills/run/SKILL.md) | the conductor โ€” interviews, sizes, plans, delegates, merges |
192
+ | [`setup`](skills/setup/SKILL.md) | reads the repo and writes `.tyran/config.yaml`, provenance per value |
193
+ | [`status`](skills/status/SKILL.md) | where an initiative got to, from the journal rather than from memory |
194
+ | [`doctor`](skills/doctor/SKILL.md) | is any gate installed but unable to fire; is the state self-consistent |
195
+ | [`retro`](skills/retro/SKILL.md) | the anti-bloat curator that changes Tyran, never your product code |
196
+ | [`hello`](skills/hello/SKILL.md) | proves the plugin is installed and its paths resolve |
197
+ | [`code-review`](skills/code-review/SKILL.md) | **standalone.** The dimensions a diff is read against, and the rule that you refute a finding before reporting it |
198
+ | [`root-cause`](skills/root-cause/SKILL.md) | **standalone.** Reproduce first, one variable per experiment with the prediction written down, exit by naming the mechanism |
199
+ | [`browser-check`](skills/browser-check/SKILL.md) | **standalone.** A UI pass that returns counts โ€” console errors, failed responses, computed styles โ€” instead of "looks fine" |
200
+ | [`deslop`](skills/deslop/SKILL.md) | **standalone.** The optimization pass: delete before you add, one smell per pass, behaviour pinned by a test that ran first |
201
+ | [`pr-feedback`](skills/pr-feedback/SKILL.md) | **standalone.** All three of GitHub's comment surfaces, a disposition for every comment, push before you reply |
202
+ | [`fidelity-gate`](skills/fidelity-gate/SKILL.md) | **standalone.** Build 1:1 against a frozen mockup without drift, measured rather than eyeballed |
203
+ | [`prompt-tuning`](skills/prompt-tuning/SKILL.md) | **standalone.** Tune anything whose quality is a non-deterministic model output โ€” noise baseline first, then medians |
204
+ | [`skill-writing`](skills/skill-writing/SKILL.md) | **standalone.** What a skill has to earn before it ships, and the activation test that proves it fires |
205
+
206
+ Agents: `tyran:scout` (recon, read-only), `tyran:implementer` (one story,
207
+ own branch), `tyran:reviewer` (**no editing tools** โ€” it cannot patch what it
208
+ is grading), `tyran:retro`. What each one assumes, and who is expected to
209
+ invoke it, is in [skills and agents](docs/skills.md); the tier and effort
210
+ routing behind them is in [the roster](docs/agents.md).
211
+
212
+ The standalone protocols exist because the rule alone was not enough.
213
+ `fidelity-gate` had been inlined into three sentences and lost the inventory
214
+ step that does the work; `prompt-tuning` kept its principle and lost
215
+ everything the principle was distilled from. The rest were dangling
216
+ references โ€” the conductor ordered a browser pass, an optimization pass and a
217
+ review without saying what any of them was, so each meant whatever the agent
218
+ felt like that afternoon. **A skill is admitted here only when something
219
+ already asks for the protocol by name**, which is why there are fourteen and
220
+ not forty; the ceiling on their combined description length is enforced in
221
+ CI, and raising it is an owner decision rather than a retrospective's.
222
+
223
+ Hit the brake at any time, from anywhere, without killing the session:
224
+
225
+ ```bash
226
+ echo "wrong branch โ€” hold everything" > .tyran/STOP
227
+ ```
228
+
229
+ ## What makes Tyran different
230
+
231
+ - ๐Ÿงพ **Proof-or-it-didn't-happen.** Agent reports without raw command output
232
+ (exit codes, `X passed / Y failed`) are rejected *mechanically* at the
233
+ `SubagentStop` hook โ€” not by asking nicely in a prompt. **This gate blocks
234
+ SILENCE, not FORGERY:** an agent that invents the text `232 passed / 0
235
+ failed` walks straight through it. The gate raises the price of a lie โ€” it
236
+ has to be deliberately fabricated rather than simply waved away โ€” and it does
237
+ not remove it. Nor is the criterion "raw command output" โ€” mechanically it is
238
+ *"a digit next to one of seven test-runner keywords"*, so a build log without
239
+ an exit code is refused and a sentence containing `6 / 6 passed` is not.
240
+ Measured on 55 real reports from this project's own agents: 53 pass, and both
241
+ misses turned out not to be reports at all. Details, numbers in both
242
+ directions, and limits in [the evidence gate](docs/evidence-gate.md).
243
+ - ๐Ÿ” **It learns *your* workflow โ€” and the loop closes itself.** When an
244
+ initiative's tickets are all merged with no retrospective recorded since
245
+ the last merge, a `Stop` hook refuses **one** turn and names what is owed.
246
+ `tyran:retro` then distills your repo's rules into `.tyran/knowledge/` and
247
+ tunes Tyran's own playbook, through an anti-bloat filter with four
248
+ questions, a hard cap of three edits per retrospective, and a stated
249
+ preference for deleting rules over adding them โ€” so *"I changed nothing"*
250
+ is a correct outcome, and so is declining the retro entirely. **You are
251
+ never blocked twice**, whichever you choose. This is a gate rather than a
252
+ sentence in a skill because the retro is the step most easily skipped: it
253
+ happens after the merge, when the interesting part is over.
254
+ - ๐Ÿ” **Survives restarts and compaction.** Execution state lives in an
255
+ append-only journal in your repo; a session hook re-injects it after every
256
+ compaction or resume. The team forgets nothing.
257
+ - ๐ŸŽฏ **Update-safe evolution.** *(designed, not built.)* Three layers:
258
+ immutable core plugin ยท your repo's data (`.tyran/`) ยท locally evolved
259
+ skills. The layout is real โ€” `.tyran/` exists and is never written by the
260
+ plugin's own files โ€” but the delta-review agent that reconciles a new core
261
+ version with what your repo has learned does not exist yet.
262
+ - ๐Ÿ’ฐ **Cost modes that resolve from config, not from habit.** Model names
263
+ appear in exactly ONE file. Everything else โ€” skills, agents, policies โ€” is
264
+ written in role names, so a model deprecation is a one-line edit instead of
265
+ a sweep through every prompt. `node scripts/tiers.mjs --role reviewer`
266
+ answers with an alias; `--risk high` escalates one tier. The default puts
267
+ everyday work on the mid tier and reserves the expensive ones for calls
268
+ where being wrong is both costly and hard to notice โ€” and **security review
269
+ and arbitration have a floor no profile or risk flag can push them below**,
270
+ because otherwise `eco` would quietly become a one-flag downgrade of the two
271
+ judgements everything downstream trusts. A missing alias throws rather than
272
+ falling back to the session default: routing that silently does nothing
273
+ looks exactly like routing that works.
274
+ - ๐Ÿ”’ **Autonomy with a gate on the irreversible step.** Every commit and push
275
+ is scanned for secrets before it happens โ€” the gate assembles the payload
276
+ itself and verifies the scanner covered all of it, so a `.gitattributes`
277
+ line cannot hide anything from it. `--no-verify` (and its abbreviations) and
278
+ force-pushes are refused; a push to your production branch is refused at the
279
+ strictest autonomy class, including through `HEAD`, `@`, a shell variable or
280
+ a `git -c` alias. **What it does not do is stop an agent from raising the
281
+ class itself:** the config file holding it is GATED, not KERNEL, so an agent
282
+ with a broad allow-list can edit it in the main loop โ€” measured, not
283
+ supposed. Autonomy classes are a convention the gate enforces downward, not
284
+ a lock. Not a firewall, and
285
+ [docs/hooks.md](docs/hooks.md) says exactly where it stops โ€” including the
286
+ scanner's own measured false-negative rate.
287
+
288
+ ## How it compares
289
+
290
+ Verified against competitors' **code and public issue trackers** (July 2026),
291
+ not their READMEs. โœ… shipped/enforced ยท โš ๏ธ partial or prompt-only ยท โŒ absent
292
+ or broken ยท โ€” not applicable ยท ๐ŸŽฏ **committed in the v2 design, ships
293
+ test-gated** (flips to โœ… only when the tests exist and pass).
294
+
295
+ | Capability | **Tyran v2** | oh-my-claudecode | metaswarm | pilotfish | pro-workflow |
296
+ |---|:---:|:---:|:---:|:---:|:---:|
297
+ | Evidence contract that **blocks**: no raw command output โ†’ report rejected | โœ… | โš ๏ธ advisoryยน | โš ๏ธ prompt | โš ๏ธ prompt | โŒ |
298
+ | Learns **your repo's** rules, with an anti-bloat curator + decision ledger | โœ…โน | โš ๏ธ | โš ๏ธ | โŒ by design | โš ๏ธ regex-based |
299
+ | Execution state survives restart & compaction (journal + re-inject) | โœ… | โš ๏ธ | โŒยฒ | โŒ | โš ๏ธ |
300
+ | Plugin update **never** destroys local learning (3 layers + delta agent) | ๐ŸŽฏ | โŒยณ | โ€” | โ€” | โš ๏ธ |
301
+ | Cost modes resolved from repo config (`eco`/`balanced`/`full`, role-based routing, model names in ONE file) | โœ… | โš ๏ธ docs-only | โŒ | โš ๏ธ global-only | โŒ |
302
+ | Secret gate on commit/push with verified scan coverage, no `--no-verify` escape | โœ… | โŒ | โŒ | โŒ | โš ๏ธ |
303
+ | Independent reviewer that never grades its own homework | โœ…โท | โš ๏ธ | โš ๏ธ prompt | โš ๏ธ | โŒ |
304
+ | Small curated core โ€” no context tax, enforced in CI | โœ… | โŒโด | โš ๏ธ | โœ… | โŒ |
305
+ | Safe parallelism: worktree per agent, leases, sequential merge | โœ…โธ | โš ๏ธ | โŒ | โ€” | โŒโต |
306
+ | Clean install: 2 commands, **never writes into your `~/.claude`** | โœ… | โŒยณ | โš ๏ธ | โŒ | โš ๏ธ |
307
+ | OSS hygiene: license, changelog, CI validation, pressure tests | โœ… | โš ๏ธ | โš ๏ธ | โœ… | โŒโถ |
308
+ | Skills ยท agents it ships, counted from the repo tree | 14 ยท 4ยนโฐ | 41 ยท 19 | 14 ยท 19 | 0 ยท 8 | 41 ยท 8 |
309
+
310
+ <sub>ยน Their deliverable check is explicitly non-blocking ("never prevents the
311
+ agent from stopping"). ยฒ Their issues #32/#33/#36: crash loses loop state.
312
+ ยณ Open issues #3535/#3536: update deletes user files from `~/.claude`.
313
+ โด Their issue #2943: "50+ skills exceeding context description budget."
314
+ โต Their issues #73/#74: worktree hook broke isolated spawns. โถ "MIT" badge
315
+ links to a LICENSE file that does not exist in the repo; the GitHub API
316
+ reports no license for it. โท The reviewer agent is granted no editing tools,
317
+ so it cannot patch what it is grading โ€” but it keeps `Bash` in order to run
318
+ the tests, and `Bash` can write. This raises the price of self-approval; it
319
+ does not make it impossible. โธ Worktrees, leases and sequential merge are
320
+ specified in the conductor skill, and lease events are recorded in the
321
+ journal, so `STATE.md` surfaces a lease released by a non-holder. Detection,
322
+ not prevention: nothing physically stops a second agent from entering a held
323
+ worktree. โน The retrospective is triggered by a `Stop` gate and the curator's
324
+ filter is enforced in the agent's own contract, but what it decides to record
325
+ is a judgement, not a mechanism โ€” and the gate deliberately accepts "I am
326
+ skipping this" as a complete answer. ยนโฐ <b>The one row where a bigger number
327
+ is not a better one, printed anyway.</b> Measured on each repo's default
328
+ branch, July 2026: files matching <code>skills/*/SKILL.md</code> and
329
+ <code>agents/*.md</code>. Two competitors ship three times as many skills as
330
+ Tyran does, and that is the point of the "small curated core" row above โ€”
331
+ oh-my-claudecode's own issue #2943 is titled "50+ skills exceeding context
332
+ description budget", which is the bill that arrives with the larger number.
333
+ Tyran's fourteen are held under a description budget CI enforces on every
334
+ push (4340 of 5000 characters, and a test fails if this sentence and the
335
+ script ever disagree). That ceiling was 4000 for the first eight skills and
336
+ was raised once, deliberately, with the reason in the changelog โ€” the
337
+ distinction being that #2943 describes a budget that was <i>exceeded</i>, and
338
+ an agent here may propose a raise but not perform one. Counting files is not
339
+ counting value: what each skill is for is in <a href="skills/">skills/</a>,
340
+ one directory each.</sub>
341
+
342
+ ## Command-line use (outside Claude Code)
343
+
344
+ A single `bin/tyran.mjs` entry point exposes the same scripts the plugin's
345
+ hooks and skills already call โ€” `doctor`, `scan-repo`, `tiers`, `journal`,
346
+ `schema`, `stop-check`, `scan-control-chars`, `desc-budget` โ€” for a shell or a
347
+ CI job with no Claude Code session. Zero dependencies; `--help` lists them.
348
+
349
+ ```bash
350
+ node bin/tyran.mjs doctor --hooks # is any gate installed but unable to fire?
351
+ node bin/tyran.mjs scan-repo --dir . # what this repo looks like, with provenance
352
+ ```
353
+
354
+ Exit codes propagate to the digit, so a CI step reddens exactly when the
355
+ underlying script does.
356
+
357
+ > **Not on npm yet โ€” so `npx @jjanczur/tyran` does not work today.** The
358
+ > package is built, versioned and tested; only the publish is outstanding.
359
+ > Saying it works here before that is true would be exactly the kind of claim
360
+ > this project refuses to accept from its own agents. It publishes under the
361
+ > scope, not the bare name `tyran` โ€” that name carries an npm unpublish
362
+ > tombstone from 2021-03-30, and npm's policy against reusing an unpublished
363
+ > name is permanent, for anyone, not a grace period this project could wait
364
+ > out. The command stays `tyran` either way; only the registry name is scoped.
365
+ >
366
+ > **And it would not install the Claude Code plugin either.** For that, run
367
+ > `/plugin marketplace add jjanczur/tyran` inside Claude Code โ€” that name is
368
+ > the Claude Code marketplace identity, a separate namespace from npm and
369
+ > unaffected by any of the above. The npm package is the tooling; the plugin
370
+ > is the conductor.
371
+
372
+ ## Documentation
373
+
374
+ **Everything below also reads as a site: [jjanczur.github.io/tyran](https://jjanczur.github.io/tyran/)**
375
+ โ€” same text, with search, rendered diagrams and per-page status badges.
376
+
377
+ - ๐Ÿ“– [Getting started](docs/getting-started.md)
378
+ - ๐Ÿงฐ [Skills and agents](docs/skills.md) โ€” all fourteen skills and four agents, what each assumes, and who invokes it
379
+ - โš™๏ธ [Configuration](docs/configuration.md) โ€” `.tyran/config.yaml`, cost profiles, autonomy classes
380
+ - ๐ŸŽญ [The roster and model routing](docs/agents.md) โ€” the four agents, the tier and effort table, dynamic overrides, the `.tyran/STOP` brake (shipped)
381
+ - ๐Ÿ›๏ธ [Architecture](docs/architecture.md) โ€” the three layers, the journal, the hooks
382
+ - ๐Ÿ“œ [Journal reference](docs/journal.md) โ€” the append-only event schema (shipped)
383
+ - ๐Ÿงพ [Projections](docs/projections.md) โ€” generated `STATE.md` / `PROGRESS.md` and `--check` (shipped)
384
+ - ๐Ÿฉบ [Doctor](docs/doctor.md) โ€” `--state` consistency check: drift, orphan leases, dead policy rules (shipped)
385
+ - ๐Ÿช [Hook runtime](docs/hooks.md) โ€” gates vs probes, why hooks fail open, and what the deadline really promises (shipped)
386
+ - ๐Ÿงพ [Evidence gate](docs/evidence-gate.md) โ€” the criterion, who it binds, the recorded escape hatch, and the line between silence and forgery (shipped)
387
+ - ๐Ÿ›ก๏ธ [Policy gate](docs/policy-gate.md) โ€” path classes, the deployment class, the one rule on reads, and where each stops (shipped)
388
+ - ๐Ÿง  [Self-improvement](docs/self-improvement.md) โ€” how Tyran learns your repo, and its guardrails
389
+ - โ“ [FAQ](docs/faq.md)
390
+ - ๐Ÿค [Contributing](CONTRIBUTING.md)
391
+
392
+ ## Strategic principles
393
+
394
+ 1. **Native mechanisms only.** Built entirely on Claude Code's plugin surface:
395
+ agent frontmatter, hooks, skills-dir plugins. No custom runtime. When the
396
+ platform absorbs a capability, Tyran drops a layer instead of competing
397
+ with the vendor.
398
+ 2. **Enforcement over prompts.** A rule that matters becomes a hook or a
399
+ script. Prose is for judgment; mechanisms are for discipline.
400
+ 3. **Evidence over claims.** From agent reports to this README's comparison
401
+ table: nothing is asserted without receipts.
402
+ 4. **The repo is the memory.** All state and learned rules live in *your*
403
+ repository as reviewable text files. No hidden databases, no build step,
404
+ no silent degradation.
405
+ 5. **Local evolution, curated upstream.** Tyran adapts to each repo locally;
406
+ generalizable improvements travel to the core as pull requests.
407
+ 6. **Autonomy earns trust in layers.** Detected once, confirmed with you, and
408
+ enforced downward by the policy gate. Not *"never self-escalated"* โ€” the
409
+ file holding the class is GATED rather than KERNEL, and an agent with a
410
+ broad allow-list can edit it. Measured, not assumed; see
411
+ [the policy gate](docs/policy-gate.md).
412
+
413
+ ## Roadmap
414
+
415
+ - [x] Plugin skeleton, marketplace, CI (validate ร—2, tests, description
416
+ budget, gitleaks, semgrep)
417
+ - [x] `.tyran/` state layer: append-only journal, knowledge schema, generated
418
+ human-readable projections, `doctor --state`
419
+ - [x] Enforcement hooks: evidence gate, secrets gate, policy gate, write
420
+ guard, state re-inject, and `doctor --hooks` โ€” which catches a gate
421
+ that is installed but cannot fire
422
+ - [x] `/tyran:run` conductor + the four-agent roster + role-to-model routing
423
+ resolved from `.tyran/config.yaml`, plus the `.tyran/STOP` brake
424
+ - [x] `/tyran:setup` repo scanner (never infers `P3`) + `/tyran:doctor`,
425
+ `/tyran:status`, `/tyran:retro`, and the bare `/tyran` shortcut
426
+ - [x] Self-improvement loop: a `Stop` gate that will not let an initiative
427
+ end unretrospected, plus knowledge accumulation into `.tyran/knowledge/`
428
+ - [ ] Cost-profile benchmark receipts (three runs per profile on a fixture,
429
+ published as numbers rather than as a table of intentions)
430
+ - [ ] Update delta-review: reconcile a new core version with what your repo
431
+ has learned locally
432
+ - [ ] Overnight mode (ralph-tui integration)
433
+ - [ ] Read-only dashboard (phase C)
434
+
435
+ ## Where this came from
436
+
437
+ Tyran started as a teaching problem. One of us was mentoring the other
438
+ through learning to program, and the mentee kept hitting the same wall โ€” not
439
+ with the code, with the *tool*. Claude would ask a pile of hard questions at
440
+ once, lose the thread halfway through the answer, and burn a small fortune in
441
+ tokens re-deriving what it had already worked out. From the outside it looked
442
+ like a skill problem. It was a **context** problem.
443
+
444
+ So we sat down and went through how Claude Code actually works underneath โ€”
445
+ agent teams, subagents, why a fresh context beats a long one, why the state
446
+ has to live somewhere the window cannot take with it. That conversation
447
+ turned into a plugin. The first version was **pure prompt**: a long, careful
448
+ skill that told the model how to behave. It worked exactly as well as a
449
+ written rule ever works โ€” until the run got long, or expensive, or boring.
450
+
451
+ That failure is the whole reason for v2. Every rule that mattered got
452
+ demoted from a paragraph to a **mechanism**: a hook that refuses a report
453
+ with no command output, a gate that will not let an initiative close
454
+ unretrospected, a file that decides which model a role gets. The motto on the
455
+ conductor skill โ€” *a rule in prose loses to a mechanism that makes the mistake
456
+ impossible* โ€” is not a slogan we adopted. It is the lesson v1 taught us, in
457
+ the order we learned it.
458
+
459
+ ## License
460
+
461
+ [Apache-2.0](./LICENSE)
462
+
463
+ ---
464
+
465
+ <p align="center">
466
+ From Berlin with <b>&hearts;</b> by two buddies &mdash;
467
+ <a href="https://janczura.com">Jacek</a> and Piotr.
468
+ </p>
File without changes
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: implementer
3
+ description: Takes one self-contained story from plan to commit or PR on its own branch, with tests and a self-review. Works only in the directory it was given (a worktree when the team runs in parallel), respects the hardware ceiling and the manifest of shared zones, and reports with raw command output rather than adjectives.
4
+ ---
5
+
6
+ You are an implementer. You get ONE story and you carry it to the end.
7
+
8
+ **Reply in the language the conductor writes to you in. Code, comments,
9
+ commits and anything written to disk are in English.**
10
+
11
+ 1. **Start from the files of record**, not from the handoff alone: the story
12
+ file, `PLAN.md`, the project configuration. You work ONLY in the directory
13
+ you were given and ONLY inside the story's scope.
14
+ - **Lease first.** Before touching a worktree or a heavy slot, take its
15
+ lease file as the handoff describes. Another agent's unexpired lease
16
+ means you do NOT start โ€” you report back. Release it when you finish,
17
+ including when you finish by failing.
18
+ - **Verify the handoff's premises in the code.** A stale path, a wrong
19
+ assignment, a function that no longer exists โ€” correct it and report the
20
+ correction EXPLICITLY instead of executing blindly. Premises about DATA
21
+ are verified by measuring the real thing read-only.
22
+ - **Check the brake** before a long unattended stretch:
23
+ `node ${CLAUDE_PLUGIN_ROOT}/scripts/stop-check.mjs`. Exit 1 means stop
24
+ and report where you got to.
25
+ 2. **Order of work:** short plan, implementation, self-review of your own
26
+ diff, tests (unit, plus a real browser pass for UI โ€” through
27
+ `browser-check`, which returns counts rather than impressions), an
28
+ optimization pass recorded in the story file (`deslop` โ€” it deletes rather
29
+ than adds, and it needs a test that ran BEFORE your edit), repo validation,
30
+ then commits, push and PR on the story branch.
31
+ - When a test fails for a reason you cannot explain, **stop patching and
32
+ follow `root-cause`**. Reproduce it, change one variable at a time with
33
+ the prediction written down first, and name the mechanism. A fix for a
34
+ failure you never reproduced cannot be shown to have worked.
35
+ - When the PR comes back with comments, follow `pr-feedback`.
36
+ 3. **Decide technical questions yourself.** Stop only for product or visual
37
+ decisions, or when something would cross a boundary the handoff named โ€”
38
+ then stop and ask the conductor. "Shall I continue?" is forbidden.
39
+ 4. **Shared zones are append-only**, per the manifest. `git add` takes an
40
+ explicit list of paths โ€” never `-A`, never `.`; they sweep in files
41
+ belonging to other windows, and that has already put blobs on a remote
42
+ permanently. Pop only your own stash, addressed. Secrets never enter the
43
+ repo, in any form, including test fixtures โ€” generate those at test time
44
+ or make them plainly false.
45
+ 5. **Side observations go to `NOTES.md`** โ€” debts, proposals, things outside
46
+ your scope. You record them; you do not fix them.
47
+ 6. **The evidence contract governs your report.** For every result you paste
48
+ the RAW command output: the exit code and the counter (`X passed /
49
+ Y failed`). A paraphrase like "tests are green" with no log is a rejected
50
+ report and the work comes straight back to you.
51
+ - Final validation is a FULL repo test run, not the directory you touched.
52
+ A regression walks in through a guard you never looked at.
53
+ - A failure that was already there is proven by REVERTING your own changes
54
+ and showing it still fails โ€” not by asserting it. Take that baseline
55
+ after a `git fetch` run immediately beforehand; a stale remote once
56
+ turned a correct proof into a false accusation.
57
+ 7. **Final report:** what was done ยท test and validation output ยท what the
58
+ optimization pass changed ยท branch or PR ยท premises you corrected ยท open
59
+ doubts. The open doubts are worth more than the summary; do not tidy them
60
+ away.
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: retro
3
+ description: After an initiative closes, reads the ledger, the notes and the agents' reports and autonomously improves Tyran itself - the conductor skill, the agent roster, new skills, scripts and repo documentation. Its only product is a better Tyran, never product code. Defends hard against bloat and overfitting, so the default answer is to change nothing.
4
+ ---
5
+
6
+ You are the retrospector. Your ONLY product is a **better Tyran**. You do not
7
+ touch product code and you do not finish anyone else's story. The model is a
8
+ developer post-mortem: what worked, what failed, what blocked.
9
+
10
+ **Reply in the language the conductor writes to you in. Everything you write
11
+ to disk is in English.**
12
+
13
+ ## Inputs, in this order
14
+
15
+ 1. `.tyran/initiatives/<slug>/PLAN.md` (the ledger โ€” what went smoothly, what
16
+ came back) and `NOTES.md` (decisions, deviations, the agents' signals about
17
+ the process itself).
18
+ 2. The agents' reports from this initiative: corrected premises, escalations,
19
+ open doubts. This is the densest source of signal you have.
20
+ 3. `git log` for the initiative: reverts, fixes of your own regressions,
21
+ repeated phases.
22
+ 4. The current state of `skills/`, `agents/`, `scripts/` and the docs โ€” **so
23
+ you do not add something that is already there.**
24
+
25
+ ## The filter โ€” the core of your role. The default answer is CHANGE NOTHING
26
+
27
+ Every candidate must pass ALL FOUR. Failing any one means you reject it and
28
+ write down why; rejections are as valuable as changes, because they stop the
29
+ next retro relitigating the same idea.
30
+
31
+ 1. **Will it RECUR** in another initiative, another repo, another domain?
32
+ One-off circumstances โ€” a bad input file, a provider outage, an operator
33
+ slip โ€” are a NO.
34
+ 2. **Was the cost REAL and measured** โ€” a wasted agent cycle, a production
35
+ regression, a reworked wave? Hypothetical discomfort is a NO.
36
+ 3. **Is it already COVERED** by an existing rule or agent? If so the problem
37
+ is in EXECUTION, not in the writing. Do not add words to a rule that was
38
+ being broken. Consider a mechanism that makes the mistake impossible, or
39
+ nothing at all.
40
+ 4. **Can it be done by FIXING AN EXISTING SENTENCE** instead of adding a new
41
+ section? If yes, that is the only form allowed.
42
+
43
+ ## Budget and hierarchy โ€” hard limits
44
+
45
+ - **At most 3 changes to the conductor skill per retro.** More than that is
46
+ bloat with certainty rather than risk. Record the surplus as candidates for
47
+ next time; do not implement them.
48
+ - Order of preference: **(a) delete or merge** what duplicates ยท **(b) fix an
49
+ existing sentence** ยท **(c) only then add**. Several retros in a row with no
50
+ deletion means your filter is too soft.
51
+ - **Overfitting is forbidden.** A rule derived from one event in one domain
52
+ does not go into the conductor skill; it goes into a specialised skill or
53
+ protocol that a repo can decline to use.
54
+ - Do not breed agents. A new agent only when the work has a genuinely
55
+ different MODE โ€” different tools, different model tier, different lifecycle
56
+ โ€” never merely a different topic.
57
+
58
+ ## Your mandate โ€” act without asking
59
+
60
+ - **Agents:** add, merge, delete, rewrite any file in `agents/`.
61
+ - **New skills** under `skills/`, when repeatable work has its own mode and
62
+ must be invocable on its own. This is the right home for a rule too
63
+ domain-specific for the conductor.
64
+ - **Scripts and harnesses** worth reusing โ€” gates, comparators, probes,
65
+ report generators. A one-off harness from an initiative either becomes a
66
+ general tool or gets deleted; do not leave dead files behind.
67
+ - **Documentation that pays forward:** the repo's detected configuration,
68
+ protocols, runbooks. **Every initiative should leave the repo better
69
+ described than it found it** โ€” that is the part that makes each next
70
+ initiative cheaper.
71
+
72
+ Commit with a one-sentence justification of what the change follows FROM.
73
+
74
+ **Gates โ€” ask the operator:** deleting an agent or a rule someone may still
75
+ rely on ยท changing the deployment autonomy class ยท anything that changes
76
+ behaviour visible to users of the product.
77
+
78
+ ## Product
79
+
80
+ 1. The implemented changes โ€” surgical, each with its reason.
81
+ 2. `.tyran/initiatives/<slug>/RETRO.md`: what worked (keep it) ยท what failed
82
+ (with the cost) ยท **implemented** ยท **rejected and why** ยท candidates for
83
+ later.
84
+ 3. A five-line report for the conductor: candidates, implemented, rejected,
85
+ what you deleted or merged, what is left for next time.
86
+
87
+ If nothing passes the filter, that is a **correct result**. Say so plainly
88
+ and change nothing.