Skip to content
A jackal-headed conductor standing before a hall of agent workstations, each screen showing its own status: code optimization at 65 percent, a critical logic failure, data gathering stalled, self-improvement required.
14 skills · 5 agentsClaude Code pluginApache-2.0

The more you use it, the better it gets.

Your most expensive model just renamed a variable. In the same chat, it judged an authentication boundary. You didn't install a tool — you hired a manager. He interviews you, turns the plan into tickets on a board, and hands each one to a fresh agent on a tier matched to how hard it actually is — then runs a retrospective on the team and edits himself.

0 runtime dependenciesevery gate ships with its testsnever writes into your ~/.claudeGitHub · latest release

The thesis

It adapts to your repo. Every initiative leaves it fitting better.

Most agent setups start from zero every time you open them. Tyran ends every closed initiative with a retrospective that reads the journal, the decision ledger and the agents’ own reports, and then changes Tyran — never your product code. Here is what that looks like from the outside.

  1. Initiative 1

    It reads the repo instead of asking you to describe it

    Tyran scans your repo, infers your validation commands, your commit style, your deployment policy. Asks once.

    • validation commands
    • commit style
    • deployment policy
    validate: npm run typecheck && node --testdeploy class: preview auto, prod gated
  2. Initiative 5

    It knows where this repo burns people

    It knows your shared-file hot zones, your flaky tests, your review taste. Its retro has already deleted two of its own rules that weren’t earning their keep.

    • shared-file hot zones
    • flaky tests
    • review taste
    • always re-run the browser check
    hot zone: locales/*.json - append only, merge seriallyrule retired: never earned a catch in 4 initiatives
  3. Initiative 20

    It has written its own tooling for your recurring work

    It has written repo-specific skills for your recurring work, tuned its own agent prompts to your stack, and its cost profile routes every subtask to the cheapest model that can do the job. You mostly just approve gates.

    • repo-specific skills
    • tuned agent prompts
    • cheapest model that can do the job
    skill: migration + backfill, the way this repo does itroute: reviewer -> mid tier, security -> floor held

What of that is shipped, exactly

The three stages above are an illustration of the trajectory — the README’s own “what compounding looks like” block, not a log of a real repository. The loop underneath them is not an illustration, so here is where it stands.

Shipped: the tyran:retro agent and its anti-bloat filter — four questions, a hard cap of three edits per retrospective, and a stated preference for deleting rules over adding them — plus a Stop hook that refuses one turn when an initiative’s tickets are all merged with no retrospective recorded since the last merge. A retro that changes nothing is a correct outcome, and declining it entirely is a correct outcome; you are never blocked twice either way.

Not shipped: the update delta-review that reconciles a new core version with what your repo has already learned. The three-layer layout it needs is real — .tyran/ exists and the plugin’s own files never write into it — but the agent that does the reconciling does not exist yet. The self-improvement page carries the whole loop, its guardrails, and where each one stops.

The second pillar

A prompt asks. A hook refuses.

“Always show your test output” in a system prompt is a request, and a request is something a model can be too helpful to honour. In Tyran it is a process that runs at SubagentStop and exits with a denial. Below is the report, and below that is the exact text the agent gets back — not a summary of it.

the agent’s reportillustrative input
tyran:implementer - final reportRefactored the earnings pipeline into a single query andremoved the N+1 in the holdings loop.Ran the suite - everything is green. Typecheck is clean.Ready to merge.

53 / 55

Real reports from this project’s own agents that clear the gate. Both misses turned out not to be reports at all — one was a leaked prompt fragment, the other the platform’s weekly-limit notice.

1 turn

The cost ceiling. stop_hook_active is the anti-loop fuse: an agent is never bounced twice for the same report, because a gate that can bounce forever gets deleted by whoever is watching it.

SubagentStop → REFUSEDhooks/scripts/evidence-gate.mjs
REFUSED by the tyran evidence gate: this report carries no raw command output.The evidence contract is mechanical, not stylistic. "tests are green" isnot evidence; the unedited output of a command you actually ran is. Add atleast one line of it. Any ONE of these forms is enough:  exit code      EXIT=<code>        or  "exit code <code>", "exit status <code>"  test counter   <N> passed         or  "<N> failed", "# pass <N>", "ok <N>"  labelled count Tests: <N>         or  "Suites: <N>", "checks = <N>"If there was genuinely nothing to measure - a scouting pass, an analysis,an answer to a question - say so, with a reason, on a line that starts atthe FIRST COLUMN and is not inside a code block:EVIDENCE: none-required <why there was nothing to run>Replace the angle brackets with your own words; a line that is still allplaceholder does not count as a reason. That line is not a formalityeither: every use of it is recorded in the initiative journal, soexemptions are counted rather than assumed.What this gate does NOT do: it cannot tell real output from inventedoutput. It blocks silence, not forgery.

The limit, stated by the gate itself

This gate blocks silence, not forgery. An agent that invents the text 232 passed / 0 failed walks straight through it. The gate raises the price of a lie — it has to be deliberately fabricated rather than simply waved away — and it does not remove it. Nor is the criterion really “raw command output”: mechanically it is a digit next to one of seven test-runner keywords, so a build log with no exit code is refused and a sentence containing 6 / 6 passed is not.The evidence gate page carries the numbers in both directions.

And one gate whose whole job is to make it learn

The retrospective is the step most easily skipped: it happens after the merge, when the interesting part is over. So it is not a sentence in a skill either. When an initiative’s tickets are all merged with nothing recorded since, the Stop hook refuses exactly one turn and names what is owed — including how to decline.

Stop → REFUSED (once)hooks/scripts/retro-gate.mjs
tyran: initiative "earnings-recap" has all 7 of its tickets merged and no retrospective recorded since the last merge.Run it before you finish: spawn the `tyran:retro` agent over this initiative. It reads the ledger, the notes and the agents reports, and improves Tyran itself — never product code.This is the only loop through which Tyran learns from an initiative instead of repeating it, and it is the step most easily skipped, which is why it is a gate rather than a sentence in a skill.Deciding NOT to run one is a legitimate answer — a retro that finds nothing worth changing is a correct outcome, and so is judging the work too small to be worth one. Record that decision in the journal as a `retro.entry` with kind "skipped" and the reason, and this will not ask again. You will not be blocked twice either way.

Hooks fail open by design, and the hook runtime page says what the deadline actually promises. Path classes, the deployment class and where the secrets gate stops are on the policy gate page.

The rest of it

Six mechanisms, five of them running

Each card says which. The limits are not fine print — a control whose boundary is not stated gets read as a guarantee, and this project treats that as the failure it is.

shipped

Survives restarts and compaction

Execution state lives in an append-only journal inside your repo, and a session hook re-injects it after every compaction or resume. The team forgets where it was; the journal does not.

STATE.md and PROGRESS.md are generated from it, and --check compares them. Journal reference

shipped

A gate on the irreversible step

Every commit and push is scanned for secrets before it happens, and the gate assembles the payload itself and verifies the scanner covered all of it. --no-verify and force-pushes are refused; at the strictest autonomy class, so is a push to your production branch.

Not a firewall. It also does not stop an agent from raising its own autonomy class - that file is GATED, not KERNEL. Measured, not supposed. Policy gate

shipped

Cost modes that resolve from config, not habit

Model names appear in exactly ONE file. Skills, agents and policies are written in role names, so a model deprecation is a one-line edit. Security review and arbitration have a floor that no cost profile or risk flag can push them below.

A missing alias throws rather than falling back to the session default: routing that silently does nothing looks exactly like routing that works. Roster and routing

shipped

A reviewer that never grades its own homework

The reviewer agent is a different agent from the one that wrote the code, and it is granted no editing tools at all - it cannot patch what it is grading.

It keeps Bash in order to run the tests, and Bash can write. This raises the price of self-approval; it does not make it impossible. The four agents

shipped

Parallelism that does not corrupt itself

A worktree per agent, a lease per worktree, and a merge order that is sequential rather than hopeful. Lease events land in the journal, so a lease released by a non-holder shows up in STATE.md.

Detection, not prevention: nothing physically stops a second agent from entering a held worktree. Architecture

designed

Updates that do not delete what it learned

Three layers: the immutable core plugin, your repo data in .tyran/, and locally evolved skills. The layout is real - .tyran/ exists and the plugin never writes into it.

The delta-review agent that reconciles a new core version with what your repo has learned does not exist yet. This card is the one on the page that is a promise. Self-improvement

Install

Two commands to install it, two more to be running

Requires Claude Code. Zero runtime dependencies, Apache-2.0, and it never writes into your ~/.claude.

  1. Registers this repository as a plugin marketplace inside Claude Code.

  2. Installs the plugin: the conductor, the four agents, and the hooks.

  3. Scans the repo, writes .tyran/config.yaml annotating every value with the fact that produced it, and asks you only about what it could not establish.

  4. Then just describe what you want done. Also: /tyran:status, /tyran:doctor, /tyran:retro.

Or do not type any of it

Paste this into Claude Code and let it do the install, the restart prompt and the first setup pass with you.

Install the Tyran plugin in this repository and set it up for me.

1. Run: claude plugin marketplace add jjanczur/tyran
2. Run: claude plugin install tyran@tyran
3. Tell me to restart Claude Code, so the hooks and agents load.
4. After the restart, run /tyran:setup. It scans this repo and writes
   .tyran/config.yaml. Walk me through what it inferred - especially the
   validation commands and the deployment autonomy class - before we commit it.

Docs: https://jjanczur.github.io/tyran/getting-started/