Skip to content
devmaxxxPublic

About

Bonliva dev workflow commands and MCP integrations for Claude Code

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

bond

From ticket to merged PR, without leaving Claude Code.

A Claude Code plugin of dev-workflow commands, skills, agents and guard hooks. Each command asks one question up front, then runs to the end, in any GitHub repo.

version license Claude Code plugin tests

Quick start · Workflow · Commands · Per-repo profile · Companion plugins · Reference


Why bond

  • One question, then done. A command collects every decision its arguments leave open — target, scope, each push, PR, merge or tracker write — in one question, then runs without stopping.
  • Works in any repo. A per-repo profile settles the base branch, trunk or git-flow, Jira or no tracker, drafts and reviewers. Nothing is hardcoded.
  • Spec to PR, test first. /implement writes a plan, has a fresh context review it, writes failing tests, builds (through subagents when superpowers is installed), and maps every acceptance criterion to the test that proves it.
  • Fresh eyes on every PR. A background agent that did not write the code reviews it once for code and security issues, fixes what it confirms and pushes.
  • Guardrails built in. Hooks block AI signatures in commits, PRs and docs, keep secrets out of prompts and tracked files, and stop pushes from the wrong gh account.
  • See what runs. The optional cockpit shows the implement flow, each agent, cache health and rate limits beside the transcript.

Quick start

# In Claude Code
/plugin marketplace add devmaxxx/bond
/plugin install bond@devmaxxx

Then, in any GitHub repo:

/bond:branch add csv export --worktree     # a fresh branch in a ready worktree
/bond:implement add a CSV export to the reports page
/bond:ship-pr                              # review, browser-test, mark ready
/bond:merge-pr                             # squash-merge once green

Every command is namespaced /bond:<name>; /bond:help lists them.

The workflow

flowchart LR
    A["/branch or /start"] --> B["/implement"]
    B --> C["PR opened"]
    C --> D["/ship-pr"]
    D --> E["/merge-pr"]
    C -. red CI .-> F["/fix-ci"]
    D -. behind base .-> G["/rebase"]
    F --> D
    G --> D
Loading

/implement runs six phases, shown live in the cockpit. You can pause, stop, resume or rerun any phase:

Setup → Plan → Build → Verify → Review → Ship + PR

The build is inline TDD: one red→green slice per behaviour, typecheck and single test files as it goes, the full suite once in Verify, and one commit at the end — so the repo's commit hook runs once. --subagents switches to one implementer and one reviewer per task, and --thorough adds a plan-review agent; both are slower.

/implement --spec <path> with no ticket key is spec-only: no Jira, no upfront question, no browser, and library APIs checked against what is installed before any web lookup. The spec and the repo are the whole input.

--review-plan stops for approval after the plan, --checkpoints after every phase, and --resume picks a stopped run back up.

Commands

Every command except /help opens with one question carrying each decision its arguments leave open — target, scope, and every push, PR, merge or tracker write it will make — and none when the arguments settle it all; after the answer it runs to the end. The rule is Commands ask first in shared/standing-rules.md, and tests/commands-ask-first.test.mjs fails a command that lacks the step.

Start work

Command What it does
/branch Start a branch — checked out or in a ready worktree — cut from the base trunk or git-flow picks
/start Check out a fresh typed branch — creating the Jira issue first where there is a tracker
/worktree open a worktree for a branch, ticket or PR (env files + deps), close it, prune merged and stale ones

Build

Command What it does
/implement Fetch (or create) a Jira ticket — or take a free-text task or a --spec file where there is no tracker — then branch, plan (reviewed in a fresh context), tests first, code, and map every acceptance criterion to its test, each phase through its superpowers skill when that plugin is installed; --review-plan / --checkpoints stop for approval, --resume continues
/implement-batch Implement many tickets (Jira version/epic/JQL, GitHub milestone) in parallel worktrees, scheduled so no two touch the same files
/investigate Investigate a deployed failure to a proven root cause and write the investigation doc

Ship and review

Command What it does
/open-pr Open a PR for the current branch on GitHub
/ship-pr After implement: browser-test the PR, tick its test plan, mark ready, loop review → fix → CI
/review-pr Senior-reviewer PR review as one comment: fresh base merge, vertical + horizontal, claims checked against read-only prod data
/merge-pr Merge one PR (the current branch's or a named one) once green: push first, squash-merge, remove its branch and worktree

Keep PRs green

Command What it does
/fix-ci Fix a failed pipeline from its URL (Woodpecker, GitHub Actions), a PR, or --mine: diagnose, fix, push, watch the re-run
/rebase Rebase (or merge, for a shared branch) onto the base, resolve conflicts, re-test, push with --force-with-lease
/sweep-pr Sweep open PRs: retarget the base, rebase, restart infra CI once, squash-merge the green ones under --merge, clean up

Everything else

Command What it does
/jira Create, edit, assign, comment on, or transition a Jira issue (assigned to you by default)
/linkedin Write a LinkedIn post or article from the source, facts and numbers checked, with an optional cover-image prompt
/linkedin-draft Put an approved post or article into LinkedIn's composer or article editor through Chrome — a draft, never published
/disk-analyze Analyze disk usage: runaway logs, deleted-but-open files, caches; clean the safe ones
/help List all bond plugin commands with their descriptions

Project profile

shared/project-profile.md resolves, per repo, the base branch, the branch model (trunk, or gitflow with feature work off develop and hotfixes off the production branch), whether there is a Jira tracker at all, whether PRs open as drafts, and who the reviewers are. A repo can state its own answers in .bond/project.json; otherwise they are inferred from the origin remote. Without a manifest the tracker resolves to none, and /implement takes a free-text task, cuts a <type>/<description> branch and opens a PR with no ## Jira section.

Every command reads that profile rather than assuming a base branch or a tracker:

  • CI-flexible — /ship-pr and /fix-ci work against GitHub Actions and Woodpecker alike; the profile's Resolve PR coordinates and PR details and CI status procedures normalise the checks to one vocabulary, so no command branches on a raw status string.
  • Tracker-flexible — /implement and /start take free text or a --spec file where there is no Jira.
  • Guarded, not faked — /jira genuinely needs Jira. It says the prerequisite is missing and stops, rather than pretending to work.
// .bond/project.json — every field optional
{
  "tracker": "jira",
  "jiraSite": "example.atlassian.net",
  "baseBranch": "main",
  "branchModel": "gitflow",
  "draft": true,
  "reviewers": ["octocat"]
}

Companion plugins

Optional plugins from the same marketplace. Each builds on bond.

bond-cockpit — flow, agents and cache, live

plugins/bond-cockpit/ is a mod: a plugin of function hooks (hooks/hooks.json → modules) that runs inside Claude Code rather than as spawned node processes, so it needs a build with plugin hook modules. It is opt-in and depends on bond:

// ~/.claude/settings.json
{ "enabledPlugins": { "bond-cockpit@devmaxxx": true } }
Everything the cockpit shows
  • Status line — the /bond:implement flow while a run reports progress: feat/x ▰▰▰▱▱▱▱▱▱▱ 3/10 · Build, ⏸ before the phase while it is stopped; empty with no run and once every phase is done. The cache hit rate and countdown live in the strip and the pane, not here.
  • Pane — docks to the right of the transcript in the fullscreen layout from 110 columns, inline above the prompt otherwise; it opens only on /bond-cockpit. Three tabs, main first and in front (ctrl+x tab cycles them; /bond-cockpit job or session opens one). main keeps only what matters now: the task, then a few lines from each other tab under a heading that opens it (press it, or j / s in the pane) — under job, what runs now and agents working with a workflow's finished/started count; under session, the cache hit and countdown, the main model with its own tokens and requests, and the 5h and context gauges (other limits only once they turn yellow or red). job has the full Job card, then the Cache card. session has the Session card. The Job card: the prompt being worked on, its elapsed time (took … once done), what runs now — the tool in flight with what it works on and for how long, approve? when the permission check asked, thinking, or waiting for you — the tool count with failures and the last tool, a workflow gauge of the run's finished over started agents with the script's name and run id, a flow gauge and phase list while a /bond:implement run reports progress (⏸ and the reason at a checkpoint), and two lines per agent loop (subagent, teammate or workflow agent): its name and model from the spawn, calls and run time, then its latest tool and last test, typecheck or lint counts — red when any failed, with a warning when it ran git push or gh pr create. Working ones first, quiet after two minutes without a call, gone five minutes after finishing. The main tab's agents row adds the red and pushed counts. Press an agent's name (ctrl+x into the pane, arrows, Enter) and an agent tab opens: its state, run, model, its last 12 calls with their ages, and a message line that sends it a note the way SendMessage does — to check on it or change what it does next. The Cache card wears the entry's state on its border and header (● warm, ◐ expiring, ○ expired): the hit rate beside one bar split into read / wrote / new tokens, then a TTL meter with the countdown, and advice only once there is something to do. Session stays grey: hit rate with a sparkline of the last 20 requests coloured by hit, cost relative to no cache with the input tokens saved after the write surcharge, and prefix rebuilds (requests under 50% hit) with how long ago the last one was; then a models section, every model that answered this session, subagents included, with its requests and tokens and the main thread's marked; then a usage section of aligned gauges for the 5h and weekly rate-limit windows with time to reset and for the context fill, coloured at 75% and 90%. Its badge adds the session's cost. Bars stretch to the pane's width. /bond-cockpit opens it.
  • Strip under the prompt — the main card, always there below the hint line without opening a pane. /bond-cockpit collapse folds it to one line (state, flow, cache, 5h and context, cost), hide takes it away, expand / show bring it back; the mode is kept across sessions, and there is no close.
  • Band above the prompt — on every tab. While a /bond:implement run reports progress: its line (branch, phase bar, count and the current phase, yellow with ⏸ and the reason while a checkpoint waits or after a stop; gone once every phase is done) and its buttons (ctrl+x tab to focus): ⏸ pause (p, stops at the next phase boundary), ■ stop (x, aborts the turn now), ▶ resume (r, once it stands still) and ↻ rerun <phase>; the job tab's phase list has a ↻ beside every phase reached, which runs /bond:implement --resume <branch> --from "<phase>". While the strip is hidden, a show cockpit button (c) brings it back.
  • plugins tab — profiles and every plugin and user skill, each with what it adds to every request (its skills' listing plus its MCP tools) and how often it was used (Skill and plugin MCP calls, all sessions). A press toggles one in this checkout's .claude/settings.local.json; ▶ <profile> applies a profile (full, the default with everything on; minimal, job-search, dev, frontend, design, architecture, review, work, authoring), ✎ edits one (toggles then change the profile, kept across sessions), reset hands everything back to the user settings, and reload plugins puts /reload-plugins in the prompt. bond-cockpit itself never goes off. /bond-cockpit profile [<name>|reset] lists or applies one, and the model calls the same through the mcp__bond-cockpit__profile tool, which the routing-plugins skill uses to pick a profile per session.
  • settings tab — built-in features that cost context: git and PR instructions, the Artifact tool, bundled skills and workflows, claude.ai skills, plugins and connectors, auto memory, workflows, a skill description cap (full, 160, 80 chars), and each MCP server (deniedMcpServers), each with its measured tokens and a toggle written to the same local file.

No request reports its cache TTL, so cacheTtl (default auto) infers it on every request: a subscription past a rate-limit window is in overage and drops to 5m; otherwise the last model switch's report; otherwise 1h on a subscription and 5m on an API key. 5m or 1h fixes it. The card badge says overage, set or API when the TTL came from one of those.

bond-oss — open-source library companion

plugins/bond-oss/ creates, audits, demos and releases npm libraries on one stack (pnpm, tsdown, Vitest, @antfu/eslint-config, ESM-only) and publishes them through npm trusted publishing (OIDC, no token). Its skills — oss-lib-stack, npm-publishing, oss-release-flow, oss-demos — carry the traps the libraries already hit; templates/ holds the files a new lib starts from. Personal names (GitHub owner, license holder, npm user) live in ~/.config/bond/oss.json, never in the plugin.

// ~/.claude/settings.json (or a library's .claude/settings.local.json)
{ "enabledPlugins": { "bond-oss@devmaxxx": true } }
Command Purpose
/bond-oss:new-lib Free-name check, scaffold from templates/ts-lib, GitHub repo, CI + release workflows, README, examples, first PR
/bond-oss:audit Check a lib against the stack and its alternatives; fix license, package, CI, README and examples drift in one PR
/bond-oss:demo Examples run in CI, a GitHub Pages or Expo demo, GIFs recorded by committed scripts
/bond-oss:release Milestone, release PR, merge on green, tag, one watched run, npm + GitHub release verified; bootstraps trusted publishing on a first release

bond-beauty-crm — beauty-crm only

plugins/bond-beauty-crm/ drives beauty-crm's own task flow (pnpm tasks), which bond's Jira/gh commands do not know. Enable it in the beauty-crm clone only:

// beauty-crm/.claude/settings.local.json
{ "enabledPlugins": { "bond-beauty-crm@devmaxxx": true } }
Command Purpose
/bond-beauty-crm:batch Close several milestone tasks that share files in one PR: claim, claim --join, done each, one pr
/bond-beauty-crm:implement Start a task: claim its card, ask every question before the first edit (shared/questions-first.md), build, done, pr

Skills

  • readable-code-structure — splits long functions into small named ones and replaces awkward/clever control flow (search loops, N+1 in loops, nested ternaries, flag params) with plain expressions. Triggers on clean-up/refactor/"make this readable" requests and during review. Also carries the two mechanical rules that share its trigger exactly: brace every control body (one-liners and guard clauses included), and collapse repeated passes over one collection. Bundled under skills/readable-code-structure/.
  • comment-hygiene — comments the why, deletes comments that restate the code, strips ticket IDs, and handles tool directives / TODOs / dead code / license headers. Triggers on writing or reviewing comments and on clean-up/"remove comments" requests. Bundled under skills/comment-hygiene/.
  • testing-behavior — writes tests that pin the caller's contract, not the current implementation; refuses change-detector tests and tautologies, and stops to ask before enshrining suspicious behaviour. Triggers when adding, editing, or reviewing tests. Bundled under skills/testing-behavior/.
  • vertical-horizontal-review — enforces a two-pass code review: vertical (trace one feature through every layer) + horizontal (sweep every sibling of the kinds the change touches for drift). Project-agnostic. Triggers on "review this change/diff/branch/PR". Bundled under skills/vertical-horizontal-review/.
  • code-review — two vendored review corpora behind one skill. stacks/: per-language and per-framework review guides (TypeScript, React, Vue, Angular, Svelte, NestJS, Python, Django, FastAPI, Go, Rust, Java, Kotlin, Swift, Dart, C#, PHP, Ruby, C/C++, Zig, Qt, CSS) plus cross-cutting ones (N+1, concurrency, error handling, performance, architecture), from awesome-skills/code-review-skill (MIT). security/: OWASP-derived references per vulnerability class with the rule for when a pattern is a finding (CC BY-SA 4.0). The pr-review and track reviewer agents and vertical-horizontal-review run the stack checklists; security-review reads the security references. Not Claude Code's built-in /code-review. Both directories are unchanged apart from SKILL.md renamed GUIDE.md; refresh them from upstream rather than editing them. Bundled under skills/code-review/.
  • sharp-edges, differential-review, variant-analysis, insecure-defaults — Trail of Bits' security review skills. security-review triages a diff with differential-review (risk per file, git log -S on removed checks, callers of risky files), probes each verifier, parser, decoder and security flag with sharp-edges (zero, empty, malformed, oversized input, each footgun reproduced), judges config fallbacks with insecure-defaults, and hunts every surviving finding's variants with variant-analysis; the track reviewer runs sharp-edges as its footgun lens. Vendored from trailofbits/skills under CC BY-SA 4.0 — each directory carries its LICENSE and a NOTICE.md naming the upstream commit and what changed; the first three are unchanged, and insecure-defaults pairs upstream's reference corpus with a SKILL.md bond wrote, because upstream ships it as a Workflow pipeline. Refresh them from upstream rather than editing them. Bundled under skills/.
  • pr-review-comment — the vertical-horizontal review written up as one PR comment a human merges on: a fresh merge of the base, a one-line verdict first, operational claims backed by read-only prod or staging numbers (peak rates against the code's limits, source and window named), checks for queued work (idempotency, concurrency strategy, retries, what covered the gap), write-path completeness, rollback, stale description claims, a severity per finding, and open questions. Used by /review-pr. Bundled under skills/pr-review-comment/.
  • pr-template — enforces the one shared PR title + description format (Summary / Jira / Test plan) and the reviewer rules on every pull request, sourced from shared/pr-template.md. Triggers on "open/create/draft a PR" and manual gh pr create calls. Bundled under skills/pr-template/.
  • photo-jpeg-exiftool — converts a photo to JPEG, resizes it or matches its colour profile with sips, and reads, copies or strips its metadata with exiftool, all on this machine, never through a website. It copies tags only from the source file of the same shot and never invents a camera, a date or GPS. Disabled for the model (disable-model-invocation: true): it never triggers on its own and costs no context; run it by hand with /bond:photo-jpeg-exiftool. Bundled under skills/photo-jpeg-exiftool/.
  • authorship-conventions — naming and attribution for every git artefact: Conventional Branch <type>/<description>, Conventional Commits subject, prose why body, one human owner, zero AI signatures (no Co-Authored-By naming a tool, no Claude-Session:, no "generated with") in commits, PR bodies/comments or docs — plus the rename trap: renaming a branch after its PR is open closes the PR. Under TRACKER=jira the <prefix>/<KEY> branch shape bond imposes wins; everywhere else the spec wins. Backed by the check-commit / check-doc hooks. Triggers on checkout -b, "commit", "amend", "open a PR", "write the ADR/plan/README". Also decides which of the two gh accounts pushes — the active one is machine-global, so another session may have moved it since. Bundled under skills/authorship-conventions/.
  • routing-model-and-effort — picks a (model, effort) pair per task phase: opus/medium by default, high for a change over five files, across modules or untested, fable for planning only on the hard predicates, opus for every build unless a model is named, a fresh bond:effort-<tier> subagent whenever the pair differs from the session, and recon — search, callers, a docs lookup, one check run — spawned on haiku. Triggers when a task will change files or needs a plan, and when a model or effort comes up. Bundled under skills/routing-model-and-effort/.
  • routing-plugins — keeps the full profile (everything on) by default and, when the user asks to trim context or /context shows the listing heavy, picks one narrower profile from the repo and the task (job-search, authoring, work, review, architecture, design, frontend, dev, minimal), asks once, and applies it through the cockpit's profile tool to .claude/settings.local.json; profiles and why each plugin is in or out in references/profiles.md. Bundled under skills/routing-plugins/.
  • routing-code-review — routes the /code-review level off the diff: high by default, medium/low when the diff is small, single-module, tested and risk-free, a question for max, and ultra only recommended (the user launches and pays for it); --fix for our own diff, --comment/--post on the user's word. Triggers when a review is about to be launched. Bundled under skills/routing-code-review/.
  • linkedin-writing — voice and format for LinkedIn posts and articles: facts from the repo, numbers checked against the vendor's docs, attribution left to the author, plain text for posts, one cover-image prompt with its technical description, and how to fill LinkedIn's editors in Chrome without publishing. Used by /linkedin and /linkedin-draft. Bundled under skills/linkedin-writing/.

Agents

  • effort-low / effort-medium / effort-high / effort-xhigh / effort-max — one agent per reasoning effort level; the caller passes model at call time. effort-high, effort-xhigh and effort-max fall back to model: opus when the caller omits it; effort-low and effort-medium fall back to the session default subagent model, so a cheap tier is not silently run on the most expensive model. Used by the routing-model-and-effort skill because effort is only settable through an agent definition. Bundled under agents/.
  • test-runner — runs one test, typecheck or lint command on haiku at low effort and returns only the failures: the runner's own counts on line 1, then at most 40 path:line: message lines and … N more. A command that cannot start comes back as the first 5 lines of stderr. Hand it every check whose full output would otherwise land in the main context. Bundled under agents/.
  • ci-diagnose — reads one failed pipeline (Woodpecker or GitHub Actions URL) on sonnet at medium effort and returns per failed step its class — flaky, infra, code, or pre-existing on the base — a file:line cause and at most 5 log lines. Read-only; /fix-ci acts on it. Bundled under agents/.
  • pr-watch — watches one PR until it can merge, on opus at medium effort: polls its CI every ~5 minutes, sorts each red check as /fix-ci does, fixes and pushes a cause the branch's own code made in the worktree it is given, and loops on the re-run until green, until only pre-existing, infra or human-owned causes are left, or until its rounds or deadline run out. Never merges, approves, force-pushes or reruns a cause twice. The standing rule «Waiting goes to an agent» sends every wait on a PR's CI through it. Bundled under agents/.
  • pr-audit — audits a PR that was just opened, on opus at high effort, in a context that did not write it: one pass of the code and security review pair over the PR's head, the verified findings fixed and pushed once — no second round, no browser run, no test-plan ticking — then removes the worktree. Never merges, approves, marks ready or moves the ticket. Bundled under agents/.
  • pr-status — reads one PR once on haiku at low effort, state, mergeable, the CI verdict with one root-cause line per failed check, the review decision, and every unhandled inline thread, review body and conversation comment with its id (minus the ids the caller already handled). Read-only — never replies, resolves, reruns or polls. /ship-pr reads each settled round and its final state through it. Bundled under agents/.
  • pr-review — reviews one open PR's diff on opus at high effort: reads each hunk with its callers, verifies every finding before reporting it, and returns at most 15 ranked findings with file:line and the input that breaks it. Read-only — never edits, pushes or comments. Paired with security-review through shared/pr-review-flow.md; /ship-pr runs the pair right after the PR is opened, before the browser check. Bundled under agents/.
  • security-review — reviews a diff, PR or path for security defects on opus at high effort: access control and IDOR, injection, auth and sessions (verifiers fail closed on malformed input), footgun APIs and insecure defaults, SSRF, XSS, secrets, races on money, data exposure, and an audit when a lockfile changed — triaged, probed and variant-hunted with the vendored Trail of Bits skills. Verifies each finding and returns at most 15 with file:line, the attack and the fix. Read-only. Always runs paired with pr-review through shared/pr-review-flow.md (/ship-pr, /sweep-pr, /merge-pr, /review-pr, pr-audit), alongside Claude Code's built-in /security-review run headless at the PR head with no setting sources; a critical or high finding from any of the three blocks. Bundled under agents/.

Integrations

MCP servers

Under TRACKER=jira, bond calls one MCP server by the name bond-atlassian (the official Atlassian remote server, https://mcp.atlassian.com/v1/mcp, OAuth). bond does not install it: add it to the project's local scope under that name with claude mcp add, so its tools appear as mcp__bond-atlassian__*. Repos with no Jira need no MCP server — gh covers GitHub.

Browser access

Anything in this plugin that needs a browser — reading a Jira attachment or opening a failing page in /investigate — uses claude-in-chrome whenever it is available. It drives the user's real Chrome through the browser extension, so the SSO sessions are already there and no profile, LaunchAgent or debug port has to be stood up first. Load the tools with ToolSearch (select:mcp__claude-in-chrome__tabs_context_mcp,…) before using them.

If it is not available, skip the step and say so rather than asking the user to sign in — never enter credentials on their behalf.

Reference

How bond works under the hood.

Standing rules

What every session is told, and how

SessionStart prints shared/standing-rules.md into every session — the rules that used to live in a personal ~/.claude/CLAUDE.md, so the plugin carries them instead of the machine. A plugin has no declarative way to ship always-on instructions (skills and agents load on demand, and there is no auto-loaded plugin CLAUDE.md), so a hook is the mechanism.

Set BOND_USER_NAME to the name replies should open with; it falls back to git config user.name, and the greeting rule is dropped when neither resolves. The name is never committed — this repo is public.

shared/permissions-readonly.json is a read-only allowlist — the git reads (status, log, diff, show, branch, rev-parse), ls, wc, jq, head, tail, pnpm exec repograph, pnpm tasks report, pnpm tasks blockers and node --test: the calls that look at a tree without changing it. A plugin cannot apply permissions, so bond cannot switch them on for you — copy the permissions.allow entries into a project's .claude/settings.json (or the uncommitted .claude/settings.local.json). Until then every one of those calls is approved by hand, one at a time.

Hooks

Every hook and the rule it enforces
  • SessionStart runs hooks/standing-rules.mjs: the standing rules above. Registered with no matcher, so it fires on every start reason — startup, resume, clear, compact and fork alike. That is deliberate: rules that do not survive a compaction quietly stop applying halfway through a long session, and a matcher that failed to parse would drop them silently.

  • SessionStart and UserPromptSubmit run hooks/branch-guard.mjs: the branch the session opened on is recorded under <tmp>/bond/<session_id>.branch, and the first prompt submitted after the working tree has moved to another branch gets one line of context naming both branches and suggesting /clear. Once per recorded baseline — a session that carries two branches pays the first one on every turn of the second, but a reminder repeated every turn costs the tokens it is trying to save, so it is said once and re-armed by the next SessionStart (resume and compact reuse the session id, and the drift after one of those deserves a second word). A detached HEAD, a directory that is no git tree or an unwritable tmp means no nudge, never a blocked prompt. The rule is decide in that file, unit-tested in tests/branch-guard.test.mjs.

  • SessionStart runs hooks/node-guard.mjs: a tree that pins node in .nvmrc (or .node-version) gets one line of context when the shell its Bash calls land in runs another version — both versions and the PATH="$(nvm which <pin> | xargs dirname):$PATH" prefix every pnpm/node command then needs. Each Bash call is a fresh shell that does not carry nvm's PATH, so the prefix is per command rather than per session; met mid-session instead of at the start, the same fact costs a failed command per call (ERR_UNKNOWN_FILE_EXTENSION on every TypeScript entry point). A shorter pin covers the releases under it — 24 is satisfied by 24.16.0, 24.1 is not — while an alias only nvm could resolve (lts/*) and a tree with neither file say nothing. nvm is never invoked: the line names the prefix, it does not run it. The rule is check in that file, unit-tested in tests/node-guard.test.mjs.

  • SessionStart runs hooks/context-mode-guard.mjs: when a running context-mode server (any …/context-mode/<version>/start.mjs) was started on another node major than this session, one line names both majors, the plugin root and the heal — only in a session below node 22.5, since from 22.5 context-mode opens its database through node:sqlite and the swap cannot reach it. context-mode keeps one active better_sqlite3.node per plugin version, shared by every session, and each session's hooks overwrite it with the build for their own node, so a server below 22.5 that opens its database after another session's swap fails every ctx_* call with "compiled against a different Node.js version" — and repositories pinning 16 to 24 make that the normal case. The heal is the plugin's own hooks/ensure-deps.mjs ensureNativeCompat, which copies the cached build back without a rebuild (npm rebuild better-sqlite3 where a version no longer ships it). The binary each server runs comes from one lsof call on macOS and /proc/<pid>/exe on Linux; a path that carries no version (/usr/local/bin/node) counts as unknown and says nothing. The rule is check in that file, unit-tested in tests/context-mode-guard.test.mjs.

  • PostToolUse runs prettier on any file edited via Edit, Write, or MultiEdit (no-op when prettier is not available in the project), then hooks/check-doc.mjs scans a just-written *.md|mdx|txt for AI signatures and reports the lines back.

  • PreToolUse on Bash runs hooks/check-commit.mjs: a git commit / gh pr … whose message carries an AI signature (Co-Authored-By naming a tool, Claude-Session:, "generated with") or a non-Conventional-Commits subject is blocked with the reasons. Patterns live in hooks/ai-breadcrumbs.mjs; see the authorship-conventions skill. It runs on agent-base-kit, vendored as hooks/vendor/agent-base-kit.mjs (bond has no package.json), so it fails closed: a payload it cannot read or a check that throws blocks the command rather than letting it run unchecked. scripts/vendor-agent-base-kit.sh <version> refreshes the copy from npm.

  • PreToolUse on Bash runs hooks/check-pr.mjs: a PR whose title or body misses the shared Summary / Test plan shape, is not opened as a draft where the repo asks for one ("draft": true in .bond/project.json), or carries an AI signature is blocked with the reasons. See the pr-template skill and shared/pr-template.md. The rule lives in hooks/pr-template.mjs: it recognises the PR command only where the shell would run one — not inside a heredoc body, a quoted string or a comment — and treats only the configured Jira project keys as ticket ids, so UTF-8 and SHA-256 are prose; it demands a ## Jira section only where .bond/project.json says "tracker": "jira".

  • PreToolUse on Bash runs hooks/bash-budget.mjs: context only, never a decision — the command always runs. Ten calls in a row that each carry a single command get one line naming the three cheaper forms — chain the next ones with && or ;, issue them in one message, or hand the loop to a subagent; measured over thirty days in one repo, 6481 Bash calls averaging 1.6 KB of output, where the price is not that output but the whole conversation being re-read on every one of them. Four shapes whose output has no bound get one line naming the bounded form — git log without -n/--oneline, cat of one whole file, ls -R or find without -maxdepth, a test run without --reporter. At most one line per call and the batch nudge wins; the row is counted in <tmp>/bond/<session_id>.bash-singles, whose own mtime says whether the previous call came from a turn of its own — a counter written under a second ago means both calls were dispatched in one message, which is already the batching asked for, so that call does not lengthen the row. An unwritable tmp costs the batch nudge, never the call. Separators are read where the shell would run them, so "a && b" and a heredoc body carrying && are each one command. The rule is judge in that file, unit-tested in tests/bash-budget.test.mjs.

  • PreToolUse on the subagent dispatch — Agent, or Task where the harness still names it that — runs hooks/recon-router.mjs: context only, never a decision — the agent is dispatched either way. A prompt handed to the unnamed or the general-purpose agent that asks where something lives, what or who calls it, which file holds it or how it is wired gets one line naming who answers it cheaply — repo-scout where the working tree has one under .claude/agents/, otherwise Explore with a breadth, either on model: "haiku". The general-purpose agent pays that search in full and returns everything it read; the other two return the conclusion. A dispatch to a reader (Explore, repo-scout, caveman:cavecrew-investigator) that names no model gets one line asking for haiku; one that names a model has made the choice. So has a prompt that builds — one carrying implement, add, write, refactor, fix, update, create, migrate or edit as a word — since the agent that writes the code reads it on the way there. The rule is route in that file, unit-tested in tests/recon-router.test.mjs.

  • PreToolUse on Bash runs hooks/gh-account-guard.mjs: a git push or a gh write (PR, issue, release, label, run, gh api with a write method) that would go out under the wrong GitHub account is blocked with the command that would not — a per-command GH_TOKEN=$(gh auth token -u <account>), or for an SSH remote whose key belongs to the other account an HTTPS push with that token plus the git fetch that refreshes origin/<branch>. Never gh auth switch: the active account is machine-global. Configured by BOND_GH_ACCOUNTS (owner=account,…) and BOND_GH_SSH_ACCOUNT; with neither set it blocks nothing. Unit-tested in tests/gh-account-guard.test.mjs.

  • UserPromptSubmit, and PreToolUse on Bash / Write / Edit / MultiEdit / NotebookEdit, run hooks/secrets-guard.mjs: a prompt carrying a live-looking secret — GitHub, Atlassian (API and access tokens), Figma, Slack (tokens and webhook URLs), OpenAI/Anthropic, AWS (key IDs and secret keys), PEM and PGP private keys, Telegram bot tokens, database URIs with an inline password (Postgres, MySQL, MongoDB, Redis, AMQP), JWTs — is blocked before it is stored in the session, naming the kind and never the value and without echoing the prompt back (suppressOriginalPrompt); #allow-secret sends it anyway. A tool call that would write a literal secret into a file git tracks, a commit, a gh body (inline, or in the --body-file / -F file it sends) or a curl line is blocked, unless the file already held that secret; a gitignored file, a lone echo / printf / cat into a gitignored .env*, claude mcp add outside project scope, a $VAR reference, a placeholder and a localhost dev URI pass. It runs on the vendored agent-base-kit, which fails the tool-call check closed (a payload it cannot read blocks the call) and the prompt check open (a fault lets the prompt through). Unit-tested in tests/secrets-guard.test.mjs.

  • SessionStart, PreCompact and SessionEnd run hooks/session-memory.mjs: save (PreCompact, SessionEnd) reads the transcript and keeps the last five prompts, each cut to one line, the files the session edited and its branch in ~/.claude/bond/sessions/<repo>-<path>.json; restore (SessionStart) prints that note to the next session in the same directory — on startup or resume only, never after a compaction or a clear (the summary already carries it), never to the session that wrote it, and not once it is a week old. Small on purpose, because whatever SessionStart prints is re-read on every turn: five prompts of at most 160 characters, and a file list cut, with a "+N more" tail, so it never takes the note past 1 KB. An empty session does not overwrite a real one's note. The rules are digest and render, unit-tested in tests/session-memory.test.mjs. Adapted from everything-claude-code's memory-persistence hooks.

  • SessionStart (on a resume) and UserPromptSubmit run hooks/resume-work.mjs: when the last turn was cut off by a usage limit, an API failure (lost connection, sleep, expired login) or a full disk (No space left on device / ENOSPC in the turn's last tool output), one line names the cause and tells the model to continue the task where it stopped — re-check state, skip finished steps, do not re-ask. A turn stopped with Esc is not resumed, and a disk still under the floor asks for space first. Each pause is announced once per session. The rules are findPause and advise, unit-tested in tests/resume-work.test.mjs.

  • SessionStart and UserPromptSubmit run hooks/disk-guard.mjs async: under 5 GiB free on the home volume (BOND_DISK_MIN_FREE_GB), it runs scripts/disk-analyze.sh clean on the caches that rebuild themselves — pnpm, npm, yarn, uv, pip, go, gradle, Xcode DerivedData; never the Trash or the Chrome debug profile — at most once an hour across sessions, and reports what it freed on the next turn. Still low after that, it points at /bond:disk-analyze. The rule is report, unit-tested in tests/disk-guard.test.mjs.

  • PreToolUse on every tool runs hooks/suggest-compact.mjs: context only. At the 50th call since the last compaction, and every 25th after, one line suggests /compact if a phase just ended — auto-compaction fires wherever the window fills, a chosen one keeps what the next phase needs. PreCompact resets the count in <tmp>/bond/<session_id>.tool-calls. The rule is judge, unit-tested in tests/suggest-compact.test.mjs. Adapted from everything-claude-code's strategic-compact hook.

Tests

The hook rules are unit-tested with the Node test runner — no dependencies, no install step. Covered: the two matchers the commit and PR hooks decide on — whether a command really runs git commit or gh pr, and whether a call really opens a pull request — along with the AI-signature patterns they share with check-doc.mjs; the ticket-key rule; the standing-rules rendering; and the context hooks through their decision functions, decide (branch-guard), judge (bash-budget, suggest-compact), digest/render (session-memory), route (recon-router), check (node-guard, context-mode-guard), findPause/advise (resume-work) and report (disk-guard), each with its wrapper driven over stdin as well. Every SKILL.md is held to its size limit and to the references/ files it links, and check-commit.mjs is driven end to end over stdin:

node --test 'tests/**/*.test.mjs'

bond-cockpit is tested by Claude Code's own plugin runner — the cache view directly, and the status line, strip, band and pane on the terminal and desktop surfaces:

claude plugin validate plugins/bond-cockpit && claude plugin test plugins/bond-cockpit

Layout

Repository tree
bond/
├── .claude-plugin/
│   ├── plugin.json         # plugin manifest
│   └── marketplace.json    # marketplace entry (single-plugin repo)
├── commands/               # slash commands
├── skills/                 # each SKILL.md ≤ 3 KB; the detail sits in <skill>/references/
│   ├── readable-code-structure/  # small named functions, plain control flow, braces, one pass
│   ├── comment-hygiene/    # comment the why, delete the what
│   ├── testing-behavior/   # test the contract, not the implementation
│   ├── vertical-horizontal-review/  # two-pass review: depth + sibling sweep
│   ├── code-review/         # vendored stack guides (MIT) + OWASP security references (CC BY-SA 4.0)
│   ├── sharp-edges/         # vendored Trail of Bits: footgun APIs, malformed-input probes (CC BY-SA 4.0)
│   ├── differential-review/ # vendored Trail of Bits: risk triage, blame, blast radius (CC BY-SA 4.0)
│   ├── variant-analysis/    # vendored Trail of Bits: the same root cause elsewhere (CC BY-SA 4.0)
│   ├── insecure-defaults/   # Trail of Bits' corpus + bond's SKILL.md: fail-open config (CC BY-SA 4.0)
│   ├── pr-review-comment/   # that review as one PR comment, backed by prod data
│   ├── pr-template/         # one shared PR title + description + reviewers
│   ├── photo-jpeg-exiftool/  # JPEG via sips, metadata via exiftool, local only
│   ├── authorship-conventions/  # branch/commit/PR/doc naming, attribution, gh account
│   ├── routing-model-and-effort/  # (model, effort) pair per task phase
│   ├── routing-plugins/           # plugin and skill profile per session
│   └── routing-code-review/  # /code-review level, target and flags per diff
├── agents/
│   ├── docs-explorer.md     # look up official docs before using a third-party API
│   ├── test-runner.md       # run one check, return only the failures
│   ├── pr-status.md         # one PR's CI, review and unhandled comments, compact
│   ├── pr-review.md         # one PR's diff reviewed, verified findings ranked
│   ├── security-review.md   # security defects in a diff, PR or path, verified
│   ├── pr-audit.md          # a new PR audited in a fresh context: one review pass, fixes pushed
│   ├── ci-diagnose.md       # one failed pipeline: class, cause, short excerpt
│   └── effort-{low,medium,high,xhigh,max}.md  # one agent per effort level
├── shared/
│   ├── implement-flow.md   # shared procedures used by /implement
│   ├── superpowers.md      # which superpowers skill each implement phase runs
│   ├── merge-conflicts.md  # detect, rebase or merge, resolve, prove — ship-pr, rebase, sweep-pr
│   ├── project-profile.md  # per-repo host, base, tracker, reviewers
│   ├── standing-rules.md   # always-on rules, printed by the SessionStart hook
│   ├── pr-review-flow.md   # code review + bond's and Claude Code's security reviews, in parallel
│   ├── pr-template.md      # single source of truth for PR title + description
│   └── permissions-readonly.json  # read-only allowlist to copy into a project
├── scripts/
│   ├── disk-analyze.sh     # disk usage report behind /disk-analyze
│   └── vendor-agent-base-kit.sh  # refresh hooks/vendor/agent-base-kit.mjs from npm
├── hooks/
│   ├── hooks.json
│   ├── format-file.sh      # PostToolUse: prettier on the edited file
│   ├── shell.mjs           # is this command really *running* X?
│   ├── standing-rules.mjs  # SessionStart: print the always-on rules
│   ├── render-rules.mjs    # what the session actually reads
│   ├── branch-guard.mjs    # SessionStart + UserPromptSubmit: the branch moved under this session
│   ├── bash-budget.mjs     # PreToolUse: a row of one-command calls, output with no bound
│   ├── recon-router.mjs    # PreToolUse: who answers a "where is X" prompt cheaply
│   ├── node-guard.mjs      # SessionStart: the shell node is not the version .nvmrc pins
│   ├── resume-work.mjs     # SessionStart (resume) + UserPromptSubmit: continue a turn a limit, API error or full disk cut off
│   ├── disk-guard.mjs      # SessionStart + UserPromptSubmit (async): under 5 GiB free, clean rebuildable caches
│   ├── context-mode-guard.mjs # SessionStart: another session's context-mode server runs another node major
│   ├── session-memory.mjs  # PreCompact/SessionEnd save, SessionStart restore: last session's note
│   ├── suggest-compact.mjs # PreToolUse: a /compact reminder at 50 calls and every 25 after
│   ├── ai-breadcrumbs.mjs  # shared AI-signature patterns
│   ├── check-commit.mjs    # PreToolUse: block git commit / gh pr with a signature
│   ├── gh-account-guard.mjs  # PreToolUse: block a push or gh write from the wrong account
│   ├── vendor/agent-base-kit.mjs  # hook runner (PreToolUse fails closed, prompt and Stop open), vendored from npm
│   ├── pr-template.mjs     # the PR rule: command matcher, ticket keys, sections
│   ├── check-pr.mjs        # PreToolUse: block a PR that breaks the shared template
│   └── check-doc.mjs       # PostToolUse: flag a written md/txt with a signature
├── tests/
│   ├── pr-template.test.mjs  # node --test 'tests/**/*.test.mjs'
│   ├── render-rules.test.mjs
│   ├── branch-guard.test.mjs
│   ├── bash-budget.test.mjs
│   ├── recon-router.test.mjs
│   ├── node-guard.test.mjs
│   ├── resume-work.test.mjs
│   ├── disk-guard.test.mjs
│   ├── context-mode-guard.test.mjs
│   ├── skill-size.test.mjs
│   ├── shell.test.mjs
├── plugins/bond-cockpit/   # implement-flow status line, strip + pane mod (function hooks)
├── plugins/bond-oss/       # open-source library create/audit/demo/release (enable globally)
│   └── .claude-plugin/plugin.json  # depends on bond
├── LICENSE
└── README.md

Contributing

Run the plugin from a local checkout:

Add this directory as a local marketplace:

/plugin marketplace add /path/to/bond
/plugin install bond@devmaxxx

Run node --test 'tests/**/*.test.mjs' before a PR. Releases bump plugin.json and marketplace.json and tag through the repo's /release command.

License

MIT — see LICENSE — except the vendored Trail of Bits skills under skills/sharp-edges/, skills/differential-review/, skills/variant-analysis/ and skills/insecure-defaults/, which stay CC BY-SA 4.0 under their own LICENSE.

About

Bonliva dev workflow commands and MCP integrations for Claude Code

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages