Escapement is an agentic workflow system built on top of OpenSpec, adding:
- Adversarial overlays on OpenSpec's discovery step (riskiest-assumption, pre-mortem, red/blue team, walking-skeleton sections injected as internal prompts — not visible in the output docs).
- A bridge to Beads so OpenSpec's
tasks.mdbecomes a real task graph (bd create --spec-id ...) that agents can execute against. - A molecule formula (
mol-feature) that orchestrates the full brainstorm → discovery → skeleton → build → retro lifecycle with two human gates. - Hooks, rules, and skills that enforce the workflow at the tool-call level: TDD-first, named-agent teams, outcome-verification, OpenSpec init checks, spec-ID linkage, never-suppress discipline, Serena-first navigation. Claude Code and Codex are supported adapters over the same workflow core (see Hosts).
This does not replace OpenSpec — it uses it. The /discovery skill calls openspec init, openspec instructions, and openspec status under the hood. The proposal.md / design.md / specs/*.md files written are standard OpenSpec artifacts. Engineers comfortable with bare OpenSpec can read the changes a teammate produced through this workflow with no extra context.
⚠️ This is a snapshot of one working setup, not a product. Read, adapt, cherry-pick. The opinions are strong.
Escapement is named for the clock mechanism that turns stored energy into measured motion. It restrains runaway movement, gives the oscillator enough impulse to continue, and advances the train one tick at a time. This repo applies that model to agentic work: OpenSpec, Beads, hooks, test oracles, verification, and wakeups convert model effort into controlled, outcome-verified progress.
See docs/NAMING.md for the naming rationale.
you say "build X"
│
▼
┌───────────────────────────┐
│ mol-feature (beads) │ root epic + 9 step tasks (2 are gates)
└──────────┬────────────────┘
│ step: discovery
▼
┌───────────────────────────┐
│ /discovery skill │ adversarial overlay on OpenSpec CLI
│ └─ writes ──────────────┼──▶ openspec/changes/{name}/
│ │ ├─ proposal.md ← standard OpenSpec
│ │ ├─ design.md ← + adversarial sections
│ │ ├─ specs/*.md ← requirement IDs
│ │ └─ tasks.md
└──────────┬────────────────┘
│ step: work-breakdown
▼
┌───────────────────────────┐
│ /work-breakdown skill │ reads openspec, writes beads
│ └─ creates ─────────────┼──▶ bd spec issues (--acceptance fields)
│ │ bd task issues (--spec-id links)
└──────────┬────────────────┘
│ step: execute-skeleton → review → execute-full
▼
parallel named agents implement tasks,
reading --acceptance via --spec-id
The paths below are the source and Claude Code adapter paths. The host mapping shows the equivalent Codex surfaces.
| Layer | Files | What it buys you |
|---|---|---|
| 1. Formulas | beads/formulas/*.json |
10-step workflow definition for bd mol pour |
| 2. Skills | claude/skills/*/ |
The "how" for each step — discovery, work-breakdown, execution, oracle review |
| 3. Commands | claude/commands/*.md |
Slash-command shims (/discovery, /work-breakdown, /brainstorm, /review) |
| 4. Rules | claude/rules/*.md |
Global discipline — TDD, agent teams, outcome ownership, never-suppress, Serena-first |
| 5. Hooks | claude/hooks/*.py |
Tool-call-level enforcement (see below) |
| 6. Bootstrap | scripts/project-bootstrap.sh |
SessionStart hook auto-inits openspec/beads/serena per repo |
Each layer adds value without requiring the ones above. You can install just the skills, or skills + formulas without hooks. Start small.
Escapement is host-neutral at the core — beads, OpenSpec, test-oracle discipline, and outcome verification don't depend on which agent runs them. The host-specific surfaces are generated from one neutral manifest (agent-surfaces/manifest.json) by tools/render_agent_surfaces.py, and a --check mode fails CI if they drift, so the two hosts stay in sync:
| Surface | Claude Code | Codex |
|---|---|---|
| Instructions | CLAUDE.md |
AGENTS.md (generated) |
| Project hooks | Escapement Claude plugin | Escapement Codex plugin |
| Skills | claude/skills/ |
.agents/skills/ |
| Plugin packaging | .claude-plugin/plugin.json |
plugins/escapement/.codex-plugin/ (generated) |
The portable core runs on both: Escapement-owned task-state and landing-policy
context and the verified test-oracle and outcome gates are packaged in each
host's plugin and fixture-tested against that host's payload shape. For Codex,
the plugin is the sole hook owner; the generated repo .codex/hooks.json is
intentionally empty so the same hook cannot fire once from the checkout and
again from the installed plugin. The write/edit TDD gate remains Claude
Code-specific because its Serena tool matching is not portable to Codex.
The adapters expose different native capabilities. Per the agent-surface-parity spec, Claude Code-specific features — multi-agent TeamCreate teams and ScheduleWakeup continuation — are excluded from Codex surfaces rather than faked: a Codex hook is marked blocking only when a fixture proves it works against the current Codex payload. New shared behavior is added to the manifest first, then rendered to whichever host surface can actually enforce it.
| Tool | Install | Verify |
|---|---|---|
openspec |
brew install openspec (or npm i -g @fission-ai/openspec) |
openspec --version |
bd (beads) |
github.com/steveyegge/beads | bd --version |
direnv |
brew install direnv |
direnv version |
python3 |
usually present | python3 --version (3.9+) |
jq |
brew install jq |
jq --version |
git, bash |
usually present | — |
Install either supported host: Claude Code or Codex. The Claude steps below
configure Claude Code machine-wide. Codex uses the Escapement plugin for hooks
and packaged skills while still reading a checkout's generated AGENTS.md.
Serena MCP is optional but the navigation
hooks are silent unless .serena/memories exists in a project.
codex plugin marketplace add https://github.com/alexander-vyh/escapement
codex plugin add escapement@escapementFor later upgrades, update the checkout and run the authoritative updater:
git pull --ff-only
./scripts/codex-plugin-update.shThe updater refreshes the plugin, then backs up and replaces only exact known
Escapement legacy versions of
~/.agents/skills/beads-execution/SKILL.md. It refuses to overwrite an
unrecognized or customized user-authored skill, and verifies the effective
installed source before reporting success.
First install the native plugin from inside Claude Code:
/plugin marketplace add alexander-vyh/escapement
/plugin install escapement@escapement
Then clone the repository and run the authoritative updater:
mkdir -p "$HOME/src"
git clone https://github.com/alexander-vyh/escapement "$HOME/src/escapement"
cd "$HOME/src/escapement"
./scripts/plugin-update.shThe plugin is the sole owner of Claude workflow surfaces: hooks, skills,
agents, commands, rules, bootstrap, and harness code. The updater refreshes the
versioned plugin cache, preserves the configured model and enabled state,
removes recognized legacy Escapement symlinks, prunes duplicate settings hooks,
and maintains the stable ~/.claude/harness/{bin,schemas} wrappers. It refuses
to replace unknown user-owned files or unrelated symlinks.
For later upgrades, land or pull the desired revision and rerun:
git pull --ff-only
./scripts/plugin-update.shRestart Claude Code after an upgrade. Already-running processes may retain the old versioned plugin root.
./INSTALL.shINSTALL.sh remains only for assets the native plugin cannot install:
~/.claude/bin, Beads formulas, and ~/.beads/mol-status.sh. Those auxiliaries
point into a branch-safe pinned checkout by default. The script delegates
workflow convergence to scripts/plugin-update.sh first, so a later
INSTALL.sh --update cannot restore legacy pin-owned hooks, skills, commands,
agents, bootstrap, or harness code. --dev changes only the auxiliary links.
After installing:
- Open Claude Code in a fresh git repo anywhere on disk.
- On SessionStart, the bootstrap script runs (idempotent, fail-open):
direnv allowon any.envrcopenspec init --tools claudeifopenspec/is missingbd init --prefix <repo-name>if.beads/is missing- Prompts for Serena onboarding (interactive)
- Say: "let's build a small feature to validate the setup — add a /status slash command"
- Claude should respond by pouring
mol-featureand walking you through: brainstorm → discovery → review → breakdown → skeleton → build → retro.
If that flow happens end-to-end, everything is wired correctly.
Nine steps, two human gates, four phases (Design / Validate / Build / Learn):
brainstorm ──▶ discovery ──▶ [GATE: review-discovery] ──▶ work-breakdown
│
▼
execute-skeleton ──▶ [GATE: review-skeleton]
│
▼
execute-full ──▶ ceremony-retro ──▶ outcome-check
Each step's description tells Claude what to do — often "run /discovery" or "dispatch named agents via TeamCreate". The formula is the script; the skills are the subroutines.
build ← front-door router; pours the right molecule
└─ brainstorming ← "should we build this at all?" pre-filter
└─ discovery ← adversarial wrapper on openspec CLI
└─ work-breakdown ← openspec → beads spec+task issues
└─ beads-execution ← dispatches agents for bd ready
├─ behavioral-test-oracle-review ← brief before each code change
├─ dispatching-parallel-agents
└─ subagent-driven-development
Grouped by what they protect:
OpenSpec workflow
openspec_init_guard.py— blocksopenspeccommands whenopenspec/doesn't existdesign_doc_location_guard.py— warns when design docs go todocs/plans/instead ofopenspec/changes/discovery-gate.py— blocksbd createof features/epics without a design docdiscovery-nudge.py— nudges/discoverywhen a prompt looks like feature workdiscovery-close-gate.py— onbd close, surfaces proof-of-delivery + anti-metricsspec_id_enforcement.py— blocksbd create --type taskundermol-featurewithout--spec-idmol_status_check.py— SessionStart, surfaces active molecules
TDD + test oracle discipline
tdd-gate.py— requires test file modification before implementationtest_oracle_brief_gate.py— requires.agent/runtime/test-oracle-brief.mdfor behavioral code changestest_reminder.py— PostToolUse nudge to run tests after editsimplementation_echo_test_gate.py— rejects tests that echo the implementationoracle_downgrade_warning_gate.py— warns on test-oracle weakening in diffsoutcome_assertion_gate.py— ongh pr create, blocks tests with only structural assertions
Outcome verification + shirking
validate_no_shirking.py— blocks "pre-existing failure" evasion at commit/PR/Stopreview_gate.py— soft gate onbd closeif no review agent was dispatchedreview_nudge.py— UserPromptSubmit, nudges/reviewon review-intent prompts
Agent discipline
enforce_named_agents.py— blocks anonymous agents and multi-agent dispatch withoutTeamCreatecontext_burn_detector.py— nudges agent dispatch after excessive inline researchsession_cleanup.py— SessionStart, cleans /tmp state from the above
Serena navigation discipline (silent unless .serena/memories exists)
serena_preference_gate.py— blocks full-file Read on code when Serena is availableserena_preference_injection.py— UserPromptSubmit, steers toward Serena symbol toolsserena_onboarding_check.sh— SessionStart, nudges Serena onboarding when missing
Each hook's docstring at the top of the file is authoritative — read it before editing.
The rules/ directory encodes strong opinions:
planning-discipline.md—mol-featureon any non-trivial worktdd-enforcement.md— failing test FIRST in any test-capable repoagent-teams-default.md—TeamCreate+ named agents for anything multi-stepoutcome-ownership.md— done = verified end-to-end, not "my change compiles"molecule-awareness.md— surface active molecules on every session startworktree-discipline.md— the session-injectedescapement-worktree createtransactionnever-suppress.md— no# noqa, no--no-verify, no test downgrades — fix the underlying issueserena-first.md— symbol tools over full-file Read when Serena is onboarded
Read the rules BEFORE installing. Edit to match your philosophy. These are not universally applicable — the TDD and never-suppress rules in particular will feel restrictive if your project has no test infrastructure or relies on legacy suppression patterns.
Skills produce guidance. Hooks produce enforcement. If you install skills without hooks, Claude can and will drift from the workflow. If you install hooks without skills, the hooks will block things without offering a path forward.
Install both, or neither.
The bootstrap script runs in any git repo by default. To constrain machine-wide bootstrap to known roots, set ESCAPEMENT_BOOTSTRAP_ROOTS to a colon-separated allowlist, for example:
ESCAPEMENT_BOOTSTRAP_ROOTS="$HOME/src:$HOME/work"Some maintenance utilities still default to scanning ~/GitHub/ unless their own root variables are set, such as BEADS_BACKUP_ROOTS for beads backup discovery.
Deliberately excluded from this bundle:
~/.claude/settings.json(personal auth + permissions) — only thehooksblock is templated~/.claude/projects/*/memory/(per-project memory)- General-utility hooks unrelated to the workflow (statusline, transcript backup, IDE wrappers, context injection)
~/.beads/databases
./INSTALL.sh --uninstallRemoves all symlinks. Your .backup-<timestamp> files are left alone — rename them back manually to restore your previous config.
The substance comes from elsewhere; this repo is the glue.
- OpenSpec — the structured change-management framework this workflow runs on top of. The discovery skill is an opinionated wrapper, not a replacement.
- Beads — graph-based task tracker designed for AI agents, with molecule formulas as a workflow templating layer.
- Serena — LSP-backed semantic code navigation; the Serena rule + hooks make it the default during the build phase.
- Walking-skeleton thinking (Steven Gong et al.) — riskiest assumption first, 1–3 tasks, 30–60 min each.
- Manager Tools, Radical Candor, Playing to Win, Lencioni, Grove, Brené Brown — the rules' flavor on outcome ownership, feedback, and psychological safety.
The glue — molecule formulas, skill overlays, hook enforcement, settings template — is my own iteration, not a product. Expect to modify before adopting.
Escapement is licensed under the GNU General Public License v3.0 or later
(GPL-3.0-or-later). See LICENSE for the full text. You may
redistribute and/or modify it under the terms of the GPL as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.