Getting started
Install
Section titled “Install”One command, then one restart, then one paste. That is the whole of it, and the restart is the only part no script can do — Claude Code loads plugins at startup and nothing inside a session can make the app reload itself.
curl -fsSL https://raw.githubusercontent.com/jjanczur/tyran/main/install.sh | shIt checks Node, installs the plugin, installs the secrets scanner the write gate needs, and then prints the prompt to paste after you restart. That last prompt runs setup, proves the install works, and opens the dashboard in your browser — because everything before that point is files on disk, and the board is where any of it becomes something you can look at.
You do not need to know what a gate, a tier or an autonomy class is to use this. Setup works out what it can from the repository and asks you at most one question in ordinary words. Everything it decides is written down with the reason, and all of it is editable later from the dashboard’s Settings tab rather than by hand.
Install, step by step
Section titled “Install, step by step”Paste this into Claude Code and let it install itself. /plugin is a
slash command a human has to type, so this asks for the same steps through
the claude CLI instead, which Claude Code can run on its own — followed by
the restart those steps require, and a walkthrough of what setup inferred
before it is trusted:
Install the Tyran plugin in this repository and set it up for me.
1. Run: claude plugin marketplace add jjanczur/tyran2. Run: claude plugin install tyran@tyran3. Tell me to restart Claude Code, so the hooks and agents load.4. After the restart, run /tyran:setup, then /tyran:doctor. Setup writes the two files under .tyran/ that Tyran needs - the config, and the autonomy policy the write gate reads - and doctor proves the install actually works. Walk me through what setup inferred - especially the validation commands and the deployment autonomy class - before we commit it.
Docs: https://jjanczur.github.io/tyran/getting-started/Or type the same three steps yourself:
-
/plugin marketplace add jjanczur/tyran
-
/plugin install tyran@tyran
-
/tyran:hello
/tyran:hello confirms three things: the plugin loaded, skills are namespaced
under /tyran:*, and ${CLAUDE_PLUGIN_ROOT} resolves to the installed copy.
Requirements: Claude Code ≥ 2.1. No Node dependencies, no build step — Tyran’s scripts are plain Node ≥ 22, bundled with the plugin; you don’t run npm at any point.
Command-line use (outside Claude Code)
Section titled “Command-line use (outside Claude Code)”Published on npm as @jjanczur/tyran
— scoped, not the bare name tyran, which carries an unpublish tombstone from
2021-03-30 that npm’s abuse policy blocks anyone from reusing, permanently. The
command stays tyran either way; only the registry name is scoped, the same
pattern as @angular/cli giving you ng.
bin/tyran.mjs exposes the same scripts the plugin’s hooks and skills already
call — doctor, scan-repo, tiers, journal, schema, knowledge,
board, cost, answer, overnight, statusline, stop-check,
scan-control-chars, desc-budget — for a shell or a CI job with no Claude
Code session. Zero dependencies; --help lists them.
npx @jjanczur/tyran doctor --hooks # is any gate installed but unable to fire?npx @jjanczur/tyran scan-repo --dir . # what this repo looks like, with provenancenpx @jjanczur/tyran answer render # the sheet of questions waiting on youExit codes propagate to the digit, so a CI step reddens exactly when the underlying script does.
First run
Section titled “First run”/tyran:setupSetup scans your repo deterministically (languages, package manager,
validation commands, CI, merge history), infers your deployment autonomy
class — the safest class is always the default and P3 is never inferred
— writes .tyran/config.yaml with every field annotated
value · source · confidence, and asks you one batch of questions, only
about fields it could not establish.
It also installs the autonomy policy under .tyran/policies/, from the
shipped template, before it writes the config. That file is what the write
gate reads, and a .tyran/ without one refuses every write in the
repository — so it is not a separate step you can be left holding. It is
only ever created, never overwritten: a policy you have tightened by hand
survives every later run of setup. Editing it afterwards is human-only, by
design.
It also offers to install a /tyran shortcut into .claude/skills/tyran/,
so you can type /tyran instead of /tyran:run. That file is a few lines
that hand straight over to the plugin, so updates keep reaching the playbook.
It lands in your repo and will show up in your next commit, which is why
setup asks first.
Your first initiative
Section titled “Your first initiative”/tyran add rate limiting to the public APITyran interviews you briefly (only questions that change the plan), triages the task (S/M/L/XL × risk), plans, and drives scout → implementer → reviewer with an enforced evidence contract. You will be stopped only at gates: plan acceptance, irreversible operations, product decisions.
Tyran replies in your language; its artifacts (code, commits, state files) are in English.
The other four commands
Section titled “The other four commands”| Command | What it does |
|---|---|
/tyran:status | Where the work is, read from the journal. Names the agents that have not reported yet — the most useful line and the easiest to miss. |
/tyran:doctor | Whether Tyran itself is healthy here: gates that cannot fire, journal-vs-projection drift, orphaned leases, config that fails its schema. |
/tyran:retro | Learn from a finished initiative. Usually you do not type this — see below. |
/tyran:hello | Installation smoke test. |
Stopping a run
Section titled “Stopping a run”echo "wrong branch — hold everything" > .tyran/STOPThe conductor checks before every spawn and every merge, halts, and reports where it got to. Delete the file to resume. It needs no session, so it works from a phone at 3am, and it is the one check in the plugin that fails closed.
The retrospective runs itself
Section titled “The retrospective runs itself”When every ticket in an initiative is merged and no retrospective has been
recorded since the last merge, a Stop hook refuses one turn and says
which initiative is owed one. Deciding not to run one is a legitimate
answer — record it and the gate is satisfied. You are never blocked twice,
whatever you choose.
This exists because the retro is the step most easily skipped: it happens after the work is done, after the merge, when the interesting part is over. It is also the only mechanism by which Tyran gets better at your repo rather than repeating itself.
Updating
Section titled “Updating”claude plugin update tyran@tyranThen restart Claude Code — hooks and agents are read when a session starts, so an update that is not restarted into is an update you are not running.
The plugin is installed per scope, not per repository (claude plugin list shows yours; --scope user is the default). At user scope one update
reaches every repo you use Tyran in.
An update does not touch your .tyran/ directory. That is your repository’s
data — config, knowledge, journals, and the autonomy policy — and it is
deliberately outside the plugin so a version change cannot rewrite the
boundary you set. Re-running /tyran:setup after an update is safe and
optional: it re-scans and rewrites config.yaml, and it never overwrites an
existing .tyran/policies/autonomy.yaml.
If a repo was set up before the policy was installed automatically — the
symptom is every write being refused with “has a .tyran/ directory but no
.tyran/policies/autonomy.yaml” — this repairs it and changes nothing else:
node "${CLAUDE_PLUGIN_ROOT}/scripts/scan-repo.mjs" --dir . --ensure-policyUninstall / rollback
Section titled “Uninstall / rollback”claude plugin disable tyran/plugin uninstall tyran@tyranYour .tyran/ directory is plain data in your repo — it survives
uninstall/reinstall and any plugin version change.