senior-dev
A disciplined senior developer, with a second reviewer over its shoulder, for every Claude Code coding session.

senior-dev turns an ordinary coding session into a run with rails: it classifies
the task, insists on the right chain of installed skills, reviews the work with
Claude and a read-only Codex pass, refuses to merge unreviewed or
undocumented changes, and finishes by proving the repo is clean. It orchestrates
skills you already have (superpowers, the codex plugin, /code-review where
installed); it duplicates none of them.
It fills a gap no other plugin does: routing across your whole installed skill
inventory, a cross-model review fired as a named phase gate, a documentation
gate that blocks completion the way a red test does, and a zero-leftovers
close-out check.
What a run looks like
Every run opens the same way: the conductor settles which skills drive the
phases and how the task is classified, before a line of code is touched.
1. Every run opens by asking which skills drive it.
The four sources — your own skills, superpowers, a combination, or a
find-skills search — resolve which skill fills each fixed phase. Your choice
is saved per-repo in .senior-dev/skills.json, private by default.
2. The gate blocks an unreviewed push, and says exactly why.
Worktree commits need recorded green tests during implement/debug;
merge/push/PR needs approved reviews, verification, and a complete docs gate.
A blocked action names the exact missing items and hands you two ways forward —
resume and clear the gates, or bypass (logged):

3. Finish proves the repo is clean, with evidence, not assertions.
The hygiene sweep catches real leftovers — here it finds a stray scratch file,
removes it, and confirms a clean tree before archiving the session:

What it adds
- Conductor skill (
senior-dev:conductor) — classifies every coding task
(feature / bug-fix / refactor / quick-fix / docs-only / investigation) and
routes it through a mandatory chain of installed skills.
- Skill-source choice — every run opens by choosing who fills the process
phases: your own skills, superpowers, a combination, or a
find-skills
search. Saved per-repo, private by default. (See below.)
- SessionStart bootstrap — in any git repo, announces the conductor and
resumes in-flight sessions. Silent outside git repos.
- Commit/integration gate (PreToolUse) — worktree commits need recorded
green tests during implement/debug; merge/push/PR needs approved reviews,
verification, and a complete docs gate. Classification is command-aware
(heredoc/quote stripping, env-prefix and global-flag handling), so quoted
prose mentioning git is not false-blocked and flag-inserted forms are still
caught.
- Stop gate — a session claiming "done" with open gate items gets the
checklist back, once per distinct state (never loops).
- Codex phase reviews — read-only Codex passes through the codex plugin's
task lane at the phase's configured effort (
/codex:adversarial-review stays
available), a JSON verdict contract, a 3-cycle cap, and a post-review
write-detection guard. scripts/review-run.mjs runs these passes (and a
headless Claude pass for the Codex app, --skill claude-headless) as one
detached process with a timeout, and exits 0 (verdict), 2 (usage), 3 (degrade:
timeout, auth or reviewer failure) or 4 (the reviewer wrote to the repo).
It needs the claude CLI installed and logged in for the Claude lane.
Plan mode plus a tool allowlist (Claude lane) and Codex's read-only default
(no --write) are the primary protection; the allowlisted git diff /
git show / git log still accept write-capable options such as
--output=<path>, so this is not a strict guarantee. The
status/HEAD/diff/tree write check detects writes to tracked or untracked,
non-ignored paths after the fact (exit 4) but cannot see ignored paths.
Use --timeout for long reviews.
- Docs gate — spec, plan, handover, affected docs.
- Hygiene sweep — evidence-based zero-leftovers close.
All hooks fail open: a broken hook never blocks normal work. Gates arm only
while a session is active. /senior-dev:bypass <reason> is the logged escape
hatch, and a session genuinely parked on external work can stand the stop gate
down with state-cli waiting --on "<what>".
Where the gates hold
Claude Code is the richest host: the PreToolUse gate stops a gated action
before it even reaches git, the stop gate challenges premature "done", and the
SessionStart bootstrap auto-engages the conductor. Cowork doesn't fire Claude
Code plugin hooks (verified 2026-07). Codex and the ChatGPT app fire the
SessionStart bootstrap (seen in a 2026-09 Codex session log) but not the commit
gate: it matches a tool named Bash, and Codex runs shell commands through a
tool named exec. Whether the stop gate fires there is not yet verified. With
the universal guard installed, the
commit/merge/push gates hold in all of them, enforced by git itself. Without
the guard, non-Claude-Code hosts run the conductor and state tracking in
advisory mode only.
Choosing a skill source
Every run opens by asking which skills fill the process phases:
- own — your project's own skills
- superpowers (default) — the canonical chain
- combo — superpowers plus your project's skills where they exist
- suggest — search skills.sh via
find-skills and pick
Your choice is saved per-repo in .senior-dev/skills.json (private by default;
run state-cli skills-config share to commit it for your team). A missing
process skill is never a dead end: the conductor gives you the exact install
command (and offers to run it) for a chain plugin, or find-skills candidates
for a domain skill — nothing installs without your yes.
Models
Every phase has a floor: a Claude tier for subagent dispatch and a Codex
effort for its review pass. Defaults (Balanced): implement sonnet; review
sonnet + Codex medium; debug opus; finish opus + Codex high; adjudicate
fable. Brainstorm, plan, worktree, verify, docs and investigate run on the
controller. The conductor may raise a tier on a named complexity signal and
records why; it never lowers. status reports the tiers a run used.
{
"version": 3,
"source": "superpowers",
"models": {
"steps": { "review": { "claude": "sonnet", "codex": "medium" } },
"lanes": { "feature": { "finish": { "claude": "fable", "codex": "xhigh" } } }
}
}
A split verdict (one reviewer approves, the other rejects) goes to an
adjudicator on the configured adjudicate tier (fable by default) with only
the disputed concerns. Upheld concerns enter the fix loop. Overruled ones come
to you as one yes or no; your yes is recorded and is the only thing that clears
the block.
Test runner
Optional, per repo, in .senior-dev/skills.json (schema v4). The conductor
asks once, the first time a lane that changes code starts (not docs-only or
investigation):
"tests": {
"full": "npm test -- --reporter=junit --outputFile=.senior-dev/junit.xml",
"related": "npx vitest related --run {files}",
"one": "npx vitest run {file} --reporter=junit --outputFile=.senior-dev/junit.xml",
"report": ".senior-dev/junit.xml",
"setup": "ln -s \"$SENIOR_DEV_MAIN/node_modules\" node_modules",
"build": "npm run build"
}
Only full is required. state-cli test records each run with the tree it
covered. The gate wants one green full run; after that, later changes need
only their affected tests, checked at push / PR creation. A failure outside
your diff can be proven pre-existing (test --preexisting <id>, needs one
and report), and then the operator can /senior-dev:ship <reason> past it.
A test id is classname > name; {file} and {name} are its two halves.
For vitest, one runs the test's whole file ({file}): vitest's -t matches
the space-joined full name, not the report's suite > test, so -t {name}
misses tests inside a describe.
The proof is strict: it refuses an id shared by two tests, a failure from a
different file on base, and a full run that passed no tests (a command that
never ran the suite - with node --test, pass a glob, not a directory), and
a proof counts only for the full run it was made against. Once a failure is
proven, scoped runs that are red only on proven failures print counts as green: they satisfy the commit gate, and with ship armed an --affected
run of that kind covers the push (a --one run never does).
A test that fails, passes and fails again stops the loop with CONTRADICTION
until the operator says which behaviour is right. Declining the runner
(set-tests --none) keeps the 0.3.1 tests-green behaviour. Known ceilings
are in the design spec.
Universal enforcement (the guard)
The gates don't have to live only in Claude Code. On first run in a repo the
conductor offers to install the universal guard: real git hooks
(pre-commit, pre-push, pre-merge-commit) that run the same gate checks
from a self-contained bundle in .senior-dev/guard/. Existing hooks are
preserved and chained, never clobbered. With the guard installed, an
unreviewed push is blocked in Cowork, in OpenAI Codex, and in a plain
terminal — same message, same rules. /senior-dev:guard installs, checks, or
removes it; uninstall restores whatever hooks were there before.
One honest gap: gh pr create has no client-side git hook, so PR creation is
enforced only under Claude Code.
Install
From the terminal — copy, paste, run:
claude plugin marketplace add nzshrimper/nzshrimper-senior-dev
claude plugin install senior-dev@nzshrimper-senior-dev
# restart Claude Code to load hooks
Or without the terminal: in Claude Code, run /plugin, add the marketplace
nzshrimper/nzshrimper-senior-dev, then find senior-dev under Discover and
click Install. Restart Claude Code to load the hooks either way.
Install in Codex or the ChatGPT app
Build the local marketplace folder from a clone of this repo, then add it:
node scripts/build-codex-package.mjs # writes dist/codex-marketplace
codex plugin marketplace add ./dist/codex-marketplace # the ./ matters: a bare path is read as a GitHub repo
codex plugin add senior-dev@nzshrimper-senior-dev
In the ChatGPT app, add the dist/codex-marketplace folder as a local plugin marketplace
(the build also prints a codex:// link that opens it), then install
senior-dev. The package carries the conductor plus one skill per command
(start, status, bypass, ship, finish, guard, skills), since the
Codex format has no slash commands. Install the universal guard in each repo:
it is what enforces the gates there (see "Where the gates hold"). The package
is a copy: after an update, rebuild and reinstall. The build only ever writes
outside the repo or under its dist/, and only empties a folder that is its
own previous build.
Maintainer update flow: edit source, bump the version in
.claude-plugin/plugin.json, both fields of .claude-plugin/marketplace.json
and .codex-plugin/plugin.json (a test checks they agree), then
claude plugin marketplace update nzshrimper-senior-dev and