A host-neutral SDLC toolkit for coding agents.
Free, MIT, no account, no server, no telemetry.
Coding agents are good at writing code and bad at remembering how your team ships it. Bravros supplies the missing half: a set of 35 workflow skills that give the agent a repeatable lifecycle, and a small Go kernel for the handful of operations a prompt must never be trusted to improvise — atomic locks, human-presence gates, and preserve-before-delete.
Skills are authored in this public repository and ship embedded in the binary, so installing is one signed download and refreshing them needs no network at all. There is no dashboard, no licence check, and nothing to log into.
The binary carries the skills and templates inside it. One download, no clone, no GitHub token, no account — and every byte is minisign-verified before it lands. See Verify the trust chain.
bash -c "$(curl -fsSL https://install.bravros.dev)"The installer downloads and verifies the binary, puts it in ~/.claude/bin, adds that directory
to your PATH, writes an uninstaller next to it, and then hands off to bravros setup — the
component wizard, which is where every question is asked.
The older piped form still works and still reaches the wizard:
curl -fsSL https://install.bravros.dev | shBoth are supported on purpose. Under curl … | sh the pipe is stdin, so nothing in the script
could ever prompt; bash -c "$(…)" uses command substitution, which leaves stdin attached to
your terminal. The advertised form is therefore bash -c "$(…)", and the script additionally
runs its own body with /dev/tty bound as stdin when stdin is not a terminal, so the bookmarked
pipe keeps working. On a CI runner with no controllable terminal both forms fall through non-interactively,
install the binary, and print the command to finish setup by hand.
Or with Homebrew:
brew install bravros/tap/bravrosA Homebrew-managed install is detected: the script aborts instead of shadowing it, because
two bravros binaries on PATH means brew upgrade moves one and the installer moves the
other, and which one runs depends on PATH order you never see.
Install WSL, then run the Linux one-liner above inside it. WSL is a first-class tier; native Windows is not.
Native Windows (supported, but a documented degraded tier)
irm https://install.bravros.dev/install.ps1 | iexPrerequisite / known issue. This one-liner depends on
install.bravros.devrouting/install.ps1to the release asset. That route is an outstanding infrastructure task and is not confirmed working — if it 404s, downloadinstall.ps1from the latest release and run it locally. The asset itself ships correctly on every release and is covered bychecksums.txt.
install.ps1 is a near line-by-line mirror of install.sh — same trust chain, same install
layout (%USERPROFILE%\.claude\bin, mirroring the POSIX ~/.claude/bin), same hand-off to
bravros setup. It targets PowerShell 5.1, which ships in the box. A scoop- or winget-managed
install is detected and refused rather than shadowed, exactly like Homebrew on POSIX.
What is specifically worse than the POSIX path — the three known items, not a vague warning:
- The SessionStart hook has no desktop-app guard. On macOS and Linux the hook is
sh -c 'case "$__CFBundleIdentifier" in com.anthropic.*) exit 0;; esac; exec $HOME/.claude/bin/bravros …'so it is a no-op inside the Claude desktop app.cmd.execannot parse a shellcase, and the__CFBundleIdentifiercondition is macOS-only, so the Windows hook is the bare command%USERPROFILE%\.claude\bin\bravros.exe …with no guard (cli/internal/managed/settings_windows.go). bravros updateleaves a.old-*file behind, and has a crash window POSIX does not. On POSIX,rename(2)atomically replaces the running executable and the process keeps its unlinked inode — there is never an instant with no binary on disk. Windows locks a running image against replacement, so the update must rename the current binary aside first, install over the freed name, and then fail to delete the sideline (a running image cannot delete its own file). The leftoverbravros.exe.old-<rand>is swept on a later run, and a crash between the two renames is a real, if narrow, window (cli/internal/selfupdate/binary.go).- minisign is bootstrapped by download. POSIX gets minisign from your package manager. On
Windows the installer fetches a pinned
minisign.exefrom jedisct1's official win64 release and checks it against a SHA-256 pinned in the script before using it. It fails closed — a stale pin aborts rather than degrading to no verification — but it is one more download than the POSIX path needs, and the pin must be bumped on each minisign release.
Releases publish 6 archives — .tar.gz for macOS and Linux, .zip for Windows. The asset
names stay machine-shaped so that the installer, GoReleaser and the Homebrew formula can all
compute them; the friendly names below are for humans only.
| You have | Download |
|---|---|
| Mac (M series) | bravros-darwin-arm64.tar.gz |
| Mac (Intel) | bravros-darwin-amd64.tar.gz |
| Linux | bravros-linux-amd64.tar.gz |
| Linux (ARM) | bravros-linux-arm64.tar.gz — newly supported |
| Windows | bravros-windows-amd64.zip |
| Windows (ARM) | bravros-windows-arm64.zip |
All six live under
releases/latest/download/, alongside
install.sh, install.ps1, checksums.txt and checksums.txt.minisig. Extract the binary to
~/.claude/bin (%USERPROFILE%\.claude\bin on Windows), then run bravros setup.
bravros setup is the wizard the installer hands off to. It writes into ~/.claude from the
payload embedded in the binary — no network, no source checkout — and asks you which of four
components you want:
| Component | Goes to | What it is |
|---|---|---|
cli |
~/.claude/bin |
The binary itself. Required; the installer already placed it. |
claude-skills |
~/.claude/skills |
The agent skills, at scope core (default, 18 skills) or all (35). |
claude-templates |
~/.claude/templates |
Git hooks and project templates used by bravros init and the commit-msg gate. |
claude-settings |
~/.claude/settings.json |
The managed settings block (the SessionStart hook), deep-merged into any existing file. |
There is one selection axis — components — and no plugin-category picker. core is the default
skill scope on purpose: an always-on skill list has a context budget, and blowing it silently
hides your least-used skills. --skills=all opts into the long tail. The picker previews each
choice live (an "enter now installs:" line shows exactly what and where), and the run ends with
a result table — component, CHANGED / ALREADY CORRECT / SKIPPED, destination, reason — so a
run that skipped everything can never read as success; emptying the selection needs an explicit
confirmation.
Non-interactive forms, for CI and for dotfile scripts:
bravros setup --all --yes # everything, skills scope=all
bravros setup --components=claude-skills,claude-settings --yes # a subset
bravros setup --skills=all --yes # every skill, default components
BRAVROS_COMPONENTS=claude-skills bravros setup --yes # same, via the environmentRe-running setup is idempotent and never destructively overwrites: a file that already
exists and differs is left exactly as it is, and the payload's version is written beside it as
<name>.new and reported. settings.json is deep-merged entry by entry, never replaced. Your
choice is recorded in ~/.claude/state/setup.json, which is what the SessionStart refresh reads
later. A plugin-managed Claude Code install is detected and warned about — bravros never
writes into a directory a plugin host owns.
Setup also reconciles the # >>> bravros-managed-global >>> block in your global CLAUDE.md
against the toolkit's own copy — no clone needed, since both the source block and the merge
script ship embedded in the binary — updating the managed section while leaving everything you
wrote outside it untouched.
Then, once per repository:
bravros initThat detects your stack, writes .bravros/config.json, and installs the commit-msg and
pre-push hooks under .bravros/hooks/ via core.hooksPath. No global state, nothing outside
the repo.
Bravros updates itself:
| What it does | Network? | |
|---|---|---|
bravros selfupdate |
Runs from the SessionStart hook, at most once every 24h. If a newer release exists and has cleared a ~6h canary window, it downloads it, verifies the minisign signature, atomically swaps the binary — keeping the outgoing one as bravros.prev for one-generation rollback — and re-runs itself from the new binary to refresh components. Prints exactly one line: 🔄 bravros vX → vY (auto). |
Yes, only when a swap happens |
bravros update |
You run it by hand: same download-verify-swap, on demand. --force reinstalls even when already current. |
Yes |
The installer scripts are version-aware the same way: bash -c "$(curl …)" resolves the latest
tag and prints already current (vX.Y.Z) — no download needed or updating vX.Y.Z → vA.B.C,
then still hands off to the idempotent bravros setup as the repair path.
bravros update refuses when a package manager owns the binary and names the right command
instead (brew upgrade bravros); brew/scoop installs are likewise never auto-swapped by
selfupdate, only notified. Turn either off with BRAVROS_NO_UPDATE_CHECK=1, or set
"auto_update": false in setup.json to keep selfupdate notify-only. Skills ship inside the
binary, so they can never drift from the CLI — a skill fix merged upstream reaches every machine
within a day, zero-touch.
Gemini CLI has its own extension system:
gemini extensions install https://github.com/bravros/bravros --auto-updateThe Claude Code plugin marketplace lane is retired — curl | sh (or Homebrew) is the only
supported install path for Claude Code now. If you installed via /plugin install bravros
before, bravros setup detects it, prints the exact removal command
(/plugin marketplace remove bravros-marketplace), and migrates the machine to the installer
model.
Never run both for the same skills — the CLI detects a plugin-managed install and refuses to write there, but pointing two updaters at one tree is a conflict, not redundancy.
/recon ➔ /orchestrate ➔ /pr ➔ /finish
/recon the checkout total is wrong for orders with a coupon/recon takes a symptom, a screenshot, a stack trace, or a feature idea and produces one
dossier folder — .planning/P-NNNN-<slug>/ — carrying the brief, the constraints that must not
change, the closed decisions, the traps, and phased tasks with per-phase verify commands.
If it's a defect, /recon hands the hunt to /scout, which queries the code graph, traces the
real execution path, and certifies the cause with runtime proof before anything is written
down. No certification, no diagnosis — it reports UNCERTIFIED rather than shipping a guess.
/orchestrate .planning/P-0001-coupon-total//orchestrate executes that folder: it dispatches phases to subagents by complexity marker,
verifies each phase against its own Verify: command, and commits as it goes. /pr opens the
pull request; /finish merges it and records the outcome.
Nothing about the loop is mandatory. /quick exists for a two-line fix, and /backlog for an
idea you are not ready to act on.
Ship a change end to end
/recon |
Turn a bug report, screenshot, or feature idea into a reviewed dossier with phases and acceptance criteria |
/scout |
Find the culprit and certify it with runtime proof — never edits code |
/orchestrate |
Execute a dossier phase by phase, verifying each one before moving on |
/quick |
Small contained fix, no ceremony |
/commit /ship /push |
Formatted commits, enforced by hook rather than hope |
/pr /pr-review /address-pr /local-review |
Open, review, and answer review feedback |
/finish /promote /after-merge |
Merge, release to production behind a human gate, and run the post-deploy checklist |
Keep a repo healthy
/backlog |
Park ideas with enough structure to judge later |
/triage-sweep |
Drain a stale issue and backlog queue, verifying every close against live code |
/batch-merge-prs /prune-merged |
Land a queue of PRs, then clean up the branches |
/doctor-plus /verify-install |
Health-check the toolkit and the workspace |
/context |
Generate or audit CLAUDE.md / AGENTS.md from the actual code |
/worktree |
Isolated worktrees with real provisioning |
Understand a codebase
/graphify-this-project |
Build a queryable knowledge graph of the code, committed and refreshed on merge |
/graphify-status |
Report label coverage across every graph on the machine |
/interview-me |
Stress-test a plan round by round until nothing is silently assumed |
/advise-project-approach |
Stack and architecture advice grounded in real comparables |
Add the category plugins for the rest, or ignore them. bravros --help lists the kernel verbs.
Most of the toolkit is prose, because a 2026 model sequences work better than a step list does. The Go binary exists only for the things a prompt genuinely cannot do:
| Category | Verbs | Why it must be code |
|---|---|---|
| Format & identity | commit, nextid |
Commit format is enforced by a hook, not a suggestion. IDs are reserved atomically across worktrees. |
| Human presence | promote, destructive, pr-review |
The session must be unable to mint its own authority. Tokens come from a separate terminal you control. |
| Atomicity | merge-lock |
Two sessions must not merge at once. |
| Preserve before delete | discard, trash, clean-untracked |
Content git has never seen is copied to .trash/ before anything removes it. |
| Provisioning | worktree, branch, config, init, hooks |
Real filesystem and git work. |
| Distribution | setup, update, selfupdate, deploy, install |
Installer machinery: the component wizard, the signed self-replace, and the embedded-payload refresh. |
| Secrets | secrets set, secrets sa-token |
Keyring and op:// resolution — values never touch a prompt. |
If a rule can be enforced by code, it lives in the binary. If it can't, it's stated once as a hard constraint in a skill and nowhere else.
The agent cannot authorize its own dangerous actions. That's the design, not a policy note.
- Production merges need you.
mainis protected by GitHub branch rules and apre-pushhook that refusesrefs/heads/main. That pair is the control that actually holds, because branch protection lives on a server the agent does not run on. Layered on top,bravros promote unlockrefuses to mint a token when it detects an agent session, so a session cannot casually self-authorize. Know the limit: the token is an unsigned JSON file on disk — a guardrail against accidents and drive-by self-approval, not a cryptographic barrier. Branch protection is what stands between an agent and production; the token is what stops it happening by mistake. - Deletion preserves first.
discard,trash, andclean-untrackedcopy into.trash/before removing anything, and are reversible. Permanently destroying content that git has never seen requires a single-use token, again minted out of band. - Commit hygiene is enforced, not requested. The
commit-msghook rejects malformed subjects and strips AI attribution trailers. A skill that says "never do X" without a mechanism behind it is labelled as lore, not presented as protection. - Secrets stay out of context.
secretsandsa-tokenresolve from your keyring or 1Password at the point of use; values are never pasted into a prompt or committed. - Installers are the highest-risk code path, so they behave accordingly: settings files are merged, never overwritten, and a backup is written before any change.
Bravros makes no network calls to us, because there is no "us" to call. There is no server, no account, no licence check, no dashboard.
- ❌ No analytics, no crash reporting, no usage or command tracking
- ❌ No file paths, file contents, or prompts leave your machine
- ❌ No third-party SDKs in the binary — grep it yourself
- ✅ The only outbound traffic is GitHub releases: fetching a release archive when you run
bravros update, and one "is there a newer version" check at most once a day (off withBRAVROS_NO_UPDATE_CHECK=1). Skills come from the binary you already have, so refreshing them is a local file copy. All of it is watchable on the wire.
Verify it the same way you would verify anyone's claim — run the CLI behind mitmproxy, Charles, or Wireshark and watch the wire.
Every release is signed with minisign. install.sh, install.ps1 and bravros update all check
that signature before anything is written to disk, against a public key pinned in the script and
compiled into the binary. To verify by hand:
PUBKEY="RWQqHlahq4RjNnCasO/8yMsgtLGfdHejILKMxxpsulIs1rII6IgMO26G"
curl -LO https://github.com/bravros/bravros/releases/latest/download/checksums.txt
curl -LO https://github.com/bravros/bravros/releases/latest/download/checksums.txt.minisig
minisign -Vm checksums.txt -P "$PUBKEY"
# expected: Signature and comment signature verified
# Trusted comment: Bravros release v2.9.0The same key is published at bravros.dev/security. Because the
source is public, you can also just build it yourself: cd cli && go build .
| Path | What it is |
|---|---|
skills/ |
The 35 skills — source of truth. Each is a SKILL.md plus references/ loaded on demand. 18 carry core: true. |
cli/ |
The Go kernel. cli/internal/payload/ holds the synced copy of skills/ + templates/ that gets embedded into the binary. |
plugins/ |
Generated per-category plugin trees. Do not edit — tools/skillgen rewrites them. |
tools/skillgen |
Generates the per-host always-on files and lints skills for host-specific tokens. |
tools/cataloggen |
Builds docs/catalog/catalog.json from skill frontmatter. |
.claude-plugin/ |
Claude Code marketplace + plugin manifests. |
gemini-extension.json |
Gemini CLI extension manifest. |
AGENTS.md, CLAUDE.md, GEMINI.md, .cursorrules |
Generated per-host contracts. Edit the source, not these. |
install.sh, install.ps1, .goreleaser.yml |
Signed release and install path — POSIX and native Windows. |
Skills are authored host-neutral: no harness-specific tool names, no absolute paths. CI fails the build if one slips in, which is the only reason the same skill runs unchanged on four hosts.
MIT — see LICENSE. Contributions welcome via issues and pull requests; the skill catalog is curated, so open an issue before a large addition.
