This repo is the Claude Code plugin cw: six skills, five agents, three
hooks, three rule files, one test runner, and CI. It implements a
/cw:design -> /cw:build -> /cw:ship pipeline — research-grounded
planning, delegated implementation with one atomic commit per task, and a
verified, gated release — plus /cw:compound to feed lessons back into your
own project's rules. See WORKFLOW.md for the full pipeline narrative and
rules/orchestration.md for the model-routing table.
- Claude Code >= 2.1.269 — the version this plugin was built and tested
against (plugin agent-frontmatter parsing,
claude plugin eval). - git — for the workflow's own commits and branch checks.
- jq — used by every hook. Without it,
protect-branches.shandprotect-secrets.sheach print a warning to stderr and stand down (exit 0, no enforcement) rather than block your session. - A session in auto mode or
acceptEditsfor/cw:build— a plugin agent cannot grant itself a permission mode, so the implementer subagents need the session already in one of these modes to write without a prompt per edit.
Three ways to load this plugin, in order of how much you intend to edit it.
ln -s /path/to/your/checkout "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills/cw"Claude Code loads any folder under a skills directory that has a
.claude-plugin/plugin.json as a plugin named cw@skills-dir — no
marketplace, no install step. SKILL.md edits apply immediately; reload
agents and hooks with /reload-plugins.
This is the least robust path: Claude Code's auto-update has been reported to
silently remove symlinks under the config dir
(issue #50052). If
that bites you, fall back to a real directory instead of a symlink — move
your checkout itself under <config dir>/skills/cw, and symlink back from
wherever you actually edit (your normal projects directory, an IDE workspace,
etc.) to that real location.
claude plugin marketplace add victorkzam/claude-code-setup
claude plugin install cw@claude-code-setupThis installs a copy into
the plugin cache at ~/.claude/plugins/cache/claude-code-setup/cw/<version>/ (the
version directory changes on every claude plugin update cw@claude-code-setup),
independent of any local checkout.
claude --plugin-dir /path/to/your/checkoutLoads the plugin for that session only.
| Command | What it does | Claude may invoke it on its own? |
|---|---|---|
/cw:design <description> |
Research-grounded design; ends in one approved plan file | Yes — description-triggered |
/cw:build <slug> [continue [<task-id>]] |
Orchestrates implementation via subagents, one commit per task | No — manual only |
/cw:ship [title] |
Verifies the commit series, runs the gate, pushes, opens the PR | No — manual only |
/cw:compound [range] |
Captures lessons from a shipped change into CLAUDE.md/rules | No — manual only |
/cw:search [--quick|--deep] <query> |
Multi-source web research with citations | Yes — description-triggered |
/cw:google-workspace |
Google Docs/Drive routes and dead ends playbook | Yes — description-triggered |
/cw:build, /cw:ship, and /cw:compound are marked
disable-model-invocation: true deliberately — they change files, branches,
or open PRs, so they only run when you type the command.
| Agent | Model | Role |
|---|---|---|
cw:researcher |
sonnet | Web research, read-only |
cw:implementer |
sonnet (opus per-task for hard work) | Writes code, makes the task's commit |
cw:reviewer |
opus | Reviews an implementer's diff, read-only |
cw:design-reviewer |
opus | Doc/codebase fidelity review of a design draft |
cw:direction-reviewer |
opus, effort xhigh | Premise/direction review, once per design |
/cw:design also spawns the built-in Explore agent with model: haiku on
each call; the plugin ships no agent by that name — its agents load under the
cw: prefix. To keep every session's exploration on haiku, add a user-scope
override at ~/.claude/agents/Explore.md; it replaces the built-in prompt
with yours, so keep it short and read-only:
---
name: Explore
description: Fast, read-only codebase exploration. Locates files, symbols and patterns; reports paths and line numbers.
model: haiku
tools: Read, Glob, Grep
---
Locate what the request names with Glob and Grep, read only the ranges you
need to confirm a finding, and report file paths with line numbers. Do not
modify anything.A profile's CLAUDE.md is deliberately short — an identity line and two
imports for the process rules this plugin ships:
# Your profile
Profile: acme
@<checkout>/rules/workflow.md
@<checkout>/rules/orchestration.mdStack preferences (language conventions, framework choices) belong in your
project CLAUDE.md files, not in this profile file — this one is workflow
process, not stack opinion.
The import path depends on how you installed:
- (a) in place / (c) trial — import from your checkout directly:
@<checkout>/rules/workflow.md. - (b) marketplace — print the installed path with
claude plugin list --json | jq -r '.[] | select(.id=="cw@claude-code-setup") | .installPath'and import@<that path>/rules/workflow.md; the path changes on every update, so re-check it after updating, or keep a separate throwaway clone just for stable import paths.
This plugin also ships rules/browser.md; import it the same way (optional)
when you want Claude in Chrome browser-control conventions in your profile.
Also set plansDirectory: docs/plans in your settings so /cw:design's plan
mode writes the plan file into the project instead of the default location.
Run more than one Claude Code identity (work vs. personal, or one per client)
with CLAUDE_CONFIG_DIR:
alias claude-acme='CLAUDE_CONFIG_DIR=$HOME/.claude-acme claude'An alias survives GUI launchers better than a one-off shell export. List the
mapping between project paths and config dirs in ~/.claude-profiles, one
per line, <folder prefix>|<config dir>, # comments allowed:
~/work/acme|~/.claude-acme
~/side-projects|~/.claude-personal
The profile-check.sh SessionStart hook reads this file and reports a
wrong profile: ... notice if the active config dir doesn't match the
mapped one for your current directory, and a missing import: ... notice
for any @import line in CLAUDE.md whose target doesn't exist.
Use settings.example.json as a starting point, not a drop-in replacement —
copy it to settings.json and adapt it. It sets the top-level model,
defaultMode: "auto", effortLevel: "high", plansDirectory: "docs/plans", a
short generic permissions.deny/allow/ask set, autoMode.allow: ["$defaults"], and enabledPlugins for the official TypeScript, Python, and
Swift LSP plugins from the claude-plugins-official marketplace. It carries no
hooks key — this plugin registers its own hooks, and a plugin hook and a
settings hook with the same command both fire, so don't add them again in
settings.json.
What to adapt: the permissions.allow/deny lists for your own
workflow, the model alias mappings in rules/orchestration.md if you have
different tier preferences, and the identity line in your profile
CLAUDE.md. What to keep as-is: the workflow rules in
rules/workflow.md, the checkpoint semantics, and the hooks.
claude plugin disable cw@skills-dir # install path (a)
claude plugin disable cw@claude-code-setup # install path (b)Turns all three hooks off at once. This is also the answer for a repo that
pushes to main by convention — protect-branches.sh has no opt-out
environment variable by design, so disabling the plugin is the supported
escape hatch, not a bypass flag on the hook itself.
protect-branches.sh reads the text of each Bash command, splits it on shell
separators, strips quotes and backslashes so nested sh -c/bash -c/eval
strings and a backslash-escaped git are inspected too, and tracks
cd/pushd and git switch/checkout earlier in the same command. It
blocks a git push whose destination is main/master (an explicit
refspec, the current branch, or an upstream on main), plain force pushes
(--force, -f, +ref), and --all/--mirror; lease pushes
(--force-with-lease, --force-if-includes) to a feature branch pass. When
a cd or branch change earlier in the command can't be resolved from the
text (a variable, cd -, a path checkout), a bare git push after it is
blocked with a hint to use an explicit refspec. A (...), $(...), or
backtick-quoted subshell is its own scope for that tracking, restored when
it closes, so a cd or checkout inside one can't leak into a push outside
it; a plain checkout inside the scope leaves the branch unknown on close
instead of silently reverting.
It is a guardrail against the agent's own accidental pushes, not a sandbox: a
command held in a variable, xargs-fed refspecs, wrappers and aliases not
named git, git -c k="v w" before push, and gh api calls are out of scope,
and a line of prose that spells out a push to the default branch inside a
command is blocked as if it were the command itself — keep such text in a file
instead.
If you previously installed this project's files directly into ~/.claude
rather than as a plugin, the old manifest put five skills (build,
compound, design, search, ship), six agents, five hooks and
rules/orchestration.md there. To migrate:
- Delete the user-scope copies of the five skills, the five hooks and
rules/orchestration.md, and remove the fivehooksentries fromsettings.json— a plugin hook and a settings hook that share the same command both fire, so leaving the old entries in place double-runs them. Three of the old hooks (design-scope-guard.sh,orchestrator-delegate-guard.sh,syntax-check.sh) have no plugin replacement: 1.0.0 retires them on purpose. - Delete the five agents the plugin now ships under the
cw:prefix, but keepagents/Explore.mdif you had it: a user-scope agent namedExploreoverrides the built-in one and keeps its ownmodel: haiku, and this plugin ships no agent by that name (/cw:designpins haiku per call regardless). - Replace any workflow rules pasted into your profile
CLAUDE.mdwith the two imports shown above, and remove any other stray copies of the old layout.
Verify with claude plugin list (one cw entry), by checking that the
skills/, agents/ and hooks/ folders under your config dir hold none of
the old files (apart from agents/Explore.md if you kept it), and, inside a
session, with /hooks: each event lists the plugin's hook once, with no copy
from settings.json.
The --deep flag hands off to the bundled /deep-research workflow, which
needs dynamic workflows enabled (a paid-plan feature; disableWorkflows
turns it off). Without that, /cw:search falls back to its default
multi-source mode.
- (a) in place —
git pullin your checkout; a symlinked install picks it up on the next/reload-plugins, a real-directory install picks it up immediately. Remove the symlink (or directory) to uninstall. - (b) marketplace —
claude plugin update cw@claude-code-setupto pull the latest version;claude plugin uninstall cw@claude-code-setupto remove it. - (c) trial — nothing persists; just stop passing
--plugin-dir.
bash tests/run.sh allRuns hook behavior, file-size budgets, a cross-file phrase-duplication
check, the settings.example.json/tests/settings-keys.txt cross-check,
and a per-commit trailer check on main..HEAD (skipped, and reported as
such, only when neither main nor origin/main resolves).
Optionally set CW_SCAN_PATTERNS=<your private pattern file> to also scan
the tracked tree for private strings you've defined — this is empty by
default and off unless you set it. .gitattributes marks docs/plans/** as
linguist-generated, so design documents are collapsed by default in GitHub
diffs and excluded from language statistics.
First release as a Claude Code plugin. Converts the prior clone-and-use,
conversationally-installed configuration into a proper plugin (cw): a
plugin manifest and marketplace entry, lean skill and agent prompts, hooks
registered through hooks/hooks.json (including a new profile-check.sh
SessionStart hook), a single tests/run.sh test runner replacing the old
per-script tests, and CI running the same checks on every push and PR.