Skip to content

feat(plugin): release cw 1.0.0 as a Claude Code plugin - #3

Merged
victorkzam merged 24 commits into
mainfrom
feat/cw-plugin
Sep 22, 2026
Merged

victorkzam merged 24 commits into
mainfrom
feat/cw-plugin

Conversation

@victorkzam

@victorkzam victorkzam commented Sep 21, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Converts the clone-and-use configuration into a Claude Code plugin, cw 1.0.0: a plugin manifest and marketplace entry, six skills (design, build, ship, compound, search, google-workspace), five agents under the cw: prefix, and hooks registered through hooks/hooks.json, including a new profile-check.sh SessionStart hook.
  • Leans every prompt for Claude 5: one home per rule in rules/, a model and effort matrix for the agents, a single design document per feature, and a task-sequential build with a counter-model review gate.
  • Replaces the per-script tests and the installer with one runner, tests/run.sh (hooks, size, dedupe, scan, trailers, all), and runs the same checks in CI on ubuntu and on macOS bash 3.2.
  • Pre-release fix-ups from the validation rounds (fixups-1-0-0): the commit-trailer rule now says exactly one trailer line and no other attribution or session line, the build and ship skills repeat that shape, and tests/run.sh trailers checks it per commit on main..HEAD. CI checks out full history so the check runs on pull requests.
  • Hardening from the merge-readiness panel (hardening-1-0-0, six reproduced guard escapes): protect-branches.sh now normalises the command once (continuation lines joined, quotes and backslashes stripped, split on &&, ||, ;, |, &, parentheses, backticks and newlines), so nested sh -c, bash -c, eval and backtick strings and an escaped \git are inspected; it tracks cd, pushd and git switch/checkout earlier in the same command and resolves a refspec-less push against that state, the -C directory, or the cwd, including an upstream on the default branch under push.default=upstream; it refuses --all/--mirror alongside plain force pushes, lets --force-with-lease and --force-if-includes through to feature branches, and stays under a second on 100k-character commands (the old per-character tokenizer timed out and failed open). Its scope is stated in the header, the README and the design.
  • Alongside: the secrets hook covers .p12, .netrc, id_dsa, id_ecdsa and Terraform state; profile-check.sh prints {} when jq fails and tolerates CRLF in .claude-profiles; the SessionStart matcher includes compact; CI validates the plugin manifest as well as the marketplace; the README's marketplace route names the real cache path and the claude plugin list --json field that prints it; the ship skill passes the PR body through a file; the implementer agent names the exit report the build gate parses.
  • A rules/browser.md recovery runbook for Claude in Chrome: diagnose and repair the extension link without a human, with operator specifics left to the profile.

Why one PR: the plugin files exist only on this branch, and every fix-up was found by validating the branch itself, so they land with the release rather than after it.

Test Plan

  • bash tests/run.sh all: hooks 108/108 (nested interpreters, escaped git, chained cd and branch changes, subshell-scoped cd, --all/--mirror, lease variants, upstream on the default branch, -C checkouts, 100k-character timing, secrets patterns, profile-check error paths), size, dedupe, settings-keys, trailers (24 commits), scan, all PASS, under bash 5 and the system bash 3.2
  • shellcheck -x hooks/*.sh tests/run.sh clean on the current release and on 0.9.0 (the Ubuntu CI version)
  • claude plugin validate . and claude plugin validate .claude-plugin/plugin.json pass
  • Every plan task subject (cw-plugin, fixups-1-0-0, hardening-1-0-0) appears exactly once in main..HEAD; every commit carries exactly one trailer line
  • Merge-readiness panel (four fresh-context reviewers: guard hooks, install route, publication hygiene, docs-versus-code): install route PASS, docs PASS, hygiene finding fixed as docs(hardening-1-0-0): drop session residue; the hooks lens found a regression against the pre-hardening guard (a cd inside a subshell, $( ) or backticks was tracked as if it persisted, so a later bare push resolved in the wrong repository) plus two minor shapes (a cd path with a space, a git -C <dir> checkout applied to the cwd push), fixed as fix(hooks): scope subshell cd and -C checkouts in the branch guard with thirty harness cases, re-verified against the pre-hardening guard on the same payloads, and passed by a fresh counter-model reviewer after one fix round (nested scopes, a stray ) in prose, spaced redirection operands, comment tails, path spellings). Accepted risks, logged for the next round: all-caps GIT PUSH (git subcommands are case-sensitive) and an order-blind paren balance count (a prose string holding a stray ) followed by a stray ( scores as balanced)
  • Automated validation rounds in throwaway repos with a local bare origin: /cw:build produced one atomic commit per task through cw:implementer and cw:reviewer, /cw:ship stopped at the PR step, a push to the default branch was refused by the hook
  • CI green on ubuntu and macOS for the hardening commits (pull-request run, including the trailer check on origin/main..HEAD)
  • Hands-on check in a fresh interactive session: /cw: commands in the slash menu, profile notice rendering, a short /cw:design walk-through
  • After merge: claude plugin marketplace add plus claude plugin install cw@claude-code-setup from a clean config dir, and the README's installPath route followed as printed

Design Reference

  • docs/plans/cw-plugin/
  • docs/plans/fixups-1-0-0.md
  • docs/plans/hardening-1-0-0.md

🤖 Generated with Claude Code

https://claude.ai/code/session_01STufi6776QVKvuDcJv4RPM

victorkzam and others added 24 commits September 16, 2026 15:42
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…iles

Split the shipped policy into two impersonal rule files that a profile's
CLAUDE.md imports: workflow.md carries the branch, commit, design-document
and research/context-hygiene rules, orchestration.md carries model routing,
verification and the review-loop anti-ratchet guidance.

Each rule cluster now lives in exactly one file so the dedupe check can
enforce it mechanically. Identity and stack preferences do not ship (they
belong in a profile or project CLAUDE.md), the plans-dir promotion
machinery and emphatic capitals are gone, and the commands are namespaced
under /cw:.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…space playbook

Rewrite the five workflow skills around one plan file per feature instead of
an artifact set: /cw:design drafts it in plan mode and moves it to
docs/plans/<slug>.md on approval, naming the un-ignore fix when the
destination is ignored; /cw:build reads its `## Task` blocks (with the
folder-layout fallback), supports `continue [<task-id>]`, and keeps the
ground-truth gate, the other-model review and the three-iteration fix loop
without any guard hook, sentinel or disallowed-tools. /cw:ship gains the
tests/run.sh gate convention, /cw:search points --deep at the bundled
deep-research skill.

Add /cw:google-workspace as a skill so the connector capability matrix, upload
routes and landmines are model-invocable, and tests/fixtures/two-task-plan.md
as the minimal two-task plan the load test drives.

Co-Authored-By: Claude <noreply@anthropic.com>
…e example

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
A validation round produced a commit with two co-author lines: the
rule's one plus a harness session-attribution line naming the model.
Sharpen the rule to claim precedence explicitly so the harness
reminder cannot add a second trailer.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Carry the one-trailer-line wording from rules/workflow.md into every
commit-producing or commit-checking instruction in the build and ship
skills, without repeating the trailer text itself.

Co-Authored-By: Claude <noreply@anthropic.com>
Adds a trailers subcommand that reads the expected trailer from
rules/workflow.md and checks every non-merge commit in main..HEAD for
exactly one matching line and no session line, so a duplicate or
model-named co-author trailer is caught mechanically instead of relying
on self-report. Wired into the all gate and given a full-depth CI
checkout so origin/main resolves on pull requests.

Co-Authored-By: Claude <noreply@anthropic.com>
Ubuntu CI installs shellcheck 0.9.0, which reports the body of a function
invoked only through trap as unreachable (SC2317). Newer releases report
the same situation as SC2329, which the directive already disabled, so the
local gate on 0.11.0 stayed green. Widening the directive keeps both
versions quiet; the function itself is unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Diagnose and repair the extension link without a human: desktop-app manifest
takes precedence in the extension's probe order, so quit both apps, kill the
desktop helper, move its manifest aside, relaunch the right Chrome profile,
re-read tab context. Names the two residual causes an agent must hand back.
Operator-specific details (which sites sit behind a login, the authorisation,
the secret store, the resolver override, the memo path) live in the profile.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
… exit report

Co-Authored-By: Claude <noreply@anthropic.com>
…t list

Co-Authored-By: Claude <noreply@anthropic.com>
…source

Co-Authored-By: Claude <noreply@anthropic.com>
…harness coverage

Co-Authored-By: Claude <noreply@anthropic.com>
The plan named the design session id and a machine-local temp path as the
source of two out-of-repo gate aids. The aids are described without them.

Co-Authored-By: Claude <noreply@anthropic.com>
A merge-readiness panel found three fail-open shapes in the branch guard,
regressions against the pre-hardening hook: a cd or plain checkout inside a
(...)/$(...)/backtick subshell leaked into a bare push outside it (rule S),
a cd whose quoted argument contained a space collapsed to a second
positional the hook silently ignored (rule C), and a `git -C <dir>
switch/checkout` targeting a different repository was invisible to a later
push resolving that same directory (rule G). All three now fail closed
(blocked, with the existing cannot-determine hint where the text truly
can't resolve) instead of falling through. Extends README and the design
draft's branch-guard description to match, and adds harness coverage for
each rule plus the $(...)/backtick spellings of the subshell cases.

Co-Authored-By: Claude <noreply@anthropic.com>
…he settings example

The intro said two rule files when rules/browser.md brought the count to
three; the profile-CLAUDE.md section didn't mention importing it; and the
settings.example.json section didn't note it also sets the top-level model.

Co-Authored-By: Claude <noreply@anthropic.com>
@victorkzam
victorkzam merged commit 2e56128 into main Sep 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant