CS-10900: Add Claude Code plugin for boxel-cli#4632
Conversation
Ships a first-class Claude Code plugin for @cardstack/boxel-cli, taking inspiration from the standalone repo's .claude/CLAUDE.md and packaging it per https://code.claude.com/docs/en/plugins. Plugin lives at packages/boxel-cli/plugin/ with a repo-root .claude-plugin/marketplace.json so external users can `/plugin marketplace add cardstack/boxel` and Cardstack engineers can `claude --plugin-dir packages/boxel-cli/plugin`. Seven skills under the /boxel-cli: namespace: - boxel-development, boxel-file-structure (ported from standalone) - realm-sync, realm-history, file-ops, search, profile (new wrappers) Hybrid generation: scripts/build-plugin.ts walks the Commander tree (extracted into src/build-program.ts so both the runtime entry point and the generator share one source of truth) and rewrites the <!-- generated:commands --> blocks in each SKILL.md. Curated narrative outside those markers is hand-authored. CI gates added in ci-lint.yaml: 1. Synopsis freshness — `pnpm build:plugin && git diff --exit-code`. 2. Synopsis-bump coupling — if any generated block changed, plugin.json version must also change in the same PR (otherwise marketplace consumers won't see the update; Claude caches by version string). Plugin and CLI version independently — prose-only updates bump only plugin.json; CLI bug fixes bump only package.json. Plugin distribution stays git-based via the marketplace, no separate npm publish. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the release model from the (now-removed) ticket plan doc into packages/boxel-cli/plugin/README.md so future maintainers can ship a new plugin version without digging through Linear: bump-decision table, the 4-step release flow, how users pick up updates, and how to add another plugin to the marketplace catalog. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e935183029
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
are you just duplicating the skills that we already have? if so can you use sym links--otherwise we maintain 2 sources of truth and they will ultimately start to diverge |
There was a problem hiding this comment.
Pull request overview
Adds a distributable Claude Code plugin for @cardstack/boxel-cli, including curated Boxel authoring guidance plus generated command synopses sourced from the CLI’s Commander program tree.
Changes:
- Refactors CLI program construction into a shared
buildBoxelProgram()builder used by both runtime entrypoint and plugin synopsis generator. - Introduces
pnpm build:plugingenerator to rewrite<!-- generated:commands -->blocks for selected skills from the Commander command tree. - Adds plugin packaging/metadata (plugin manifest, marketplace entry) and CI checks to enforce synopsis freshness + version bump coupling.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/boxel-cli/src/index.ts | Switches runtime entrypoint to build and parse the shared Commander program tree. |
| packages/boxel-cli/src/build-program.ts | New shared builder for the full CLI Commander tree (single source of truth). |
| packages/boxel-cli/scripts/build-plugin.ts | New generator that derives skill command synopses from Commander and rewrites SKILL.md generated blocks. |
| packages/boxel-cli/plugin/skills/search/SKILL.md | New skill doc for federated search, including generated command synopsis block. |
| packages/boxel-cli/plugin/skills/realm-sync/SKILL.md | New realm sync skill doc with generated synopses for sync/push/pull/create/list. |
| packages/boxel-cli/plugin/skills/realm-history/SKILL.md | New realm history/indexing control skill doc with generated synopses. |
| packages/boxel-cli/plugin/skills/profile/SKILL.md | New profile management skill doc with generated synopsis for boxel profile. |
| packages/boxel-cli/plugin/skills/file-ops/SKILL.md | New single-file operations skill doc with generated synopses for boxel file *. |
| packages/boxel-cli/plugin/skills/boxel-file-structure/SKILL.md | New file layout/naming guidance skill doc (hand-authored prose). |
| packages/boxel-cli/plugin/skills/boxel-development/SKILL.md | New large Boxel authoring guide skill doc (hand-authored content). |
| packages/boxel-cli/plugin/README.md | Plugin install/usage/versioning/release documentation. |
| packages/boxel-cli/plugin/.claude-plugin/plugin.json | Plugin manifest for Claude Code marketplace distribution. |
| packages/boxel-cli/package.json | Adds build:plugin script to run the synopsis generator. |
| .github/workflows/ci-lint.yaml | Adds CI gates for synopsis freshness and plugin version bump coupling. |
| .claude-plugin/marketplace.json | Adds repository-level marketplace catalog pointing to the plugin directory. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Replaces the hand-copied 90KB monolithic boxel-development SKILL.md with a generator (`pnpm build:skills` in packages/boxel-cli/) that pulls from cardstack/boxel-skills at a pinned tag (v0.0.22), splits aggregator SkillSets into a lean SKILL.md + references/, and emits standalone SkillPlusMarkdown leaves as single-file plugin skills. Allowlist: boxel-development, boxel-design. Wires two CI checks into ci-lint.yaml that mirror the existing build-plugin synopsis pattern: drift detection (rebuild → diff) and version-bump coupling (changed boxel-skills content → plugin.json bump). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Good catch — fixed in db73171. We weren't going to symlink because boxel-skills lives in its own repo ( Instead,
To pick up upstream changes: bump |
- build-skills.ts now runs generated markdown through Prettier before writing, so CI's clean regen matches the committed copy. Fixes the failing `Verify boxel-skills sync` lint step (Prettier had been applied locally — via on-save / pre-commit format — but not by the generator, so freshness drifted). - Harden the two `Verify plugin version bumped …` CI gates: fetch base/head SHAs explicitly (default-depth checkout meant `git diff` against the PR base SHA was non-deterministic) and drop the trailing `|| true` so a real diff failure surfaces instead of silently passing as "no change". - Replace the synopsis-change grep with a per-file extract-and-compare across the `<!-- generated:commands:start -->` / `:end -->` markers, so description-only edits inside the generated block don't slip past the version-bump check. - Remove a stray ``` in `boxel-file-structure/SKILL.md` that was breaking the rendered `### JSON Structure Rules` table. - Bump plugin.json to 0.1.1 to satisfy the boxel-skills-content gate (Prettier-canonicalised regen produced real text diffs). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Ships a first-class Claude Code plugin for
@cardstack/boxel-cli, packaging the kind of guidance the standalonecardstack/boxel-clirepo carries in its.claude/CLAUDE.mdso it's distributable via marketplace.packages/boxel-cli/plugin/with manifest.claude-plugin/plugin.json..claude-plugin/marketplace.jsonlists the plugin via relative path; external users/plugin marketplace add cardstack/boxelthen/plugin install boxel-cli.claude --plugin-dir packages/boxel-cli/plugin./boxel-cli:namespace:boxel-development—.gtsauthoring (ported from standalone, ~90KB of evergreen Boxel patterns)boxel-file-structure— file/directory naming +adoptsFromrules (ported from standalone)realm-sync,realm-history,file-ops,search,profile— new wrappers around the monorepo CLI's namespaced commands (incl. CS-10627file touch)How "generated from the code" works
scripts/build-plugin.tswalks the Commander tree and rewrites the<!-- generated:commands -->block inside each SKILL.md. The Commander tree is extracted intosrc/build-program.tsso both the runtime entry point (src/index.ts) and the generator share one source of truth. Curated narrative outside the markers is hand-authored.Two CI gates in
ci-lint.yaml:pnpm build:plugin && git diff --exit-code. Fails if commands changed without regenerating skills.plugin.jsonversionmust also be in the diff. Without a version bump, Claude's marketplace cache won't surface the update.Versioning
Plugin and CLI version independently:
plugin.jsononly.package.jsononly.The plugin is not npm-published. The marketplace clones it from
cardstack/boxeldirectly.npm install -g @cardstack/boxel-cliremains the prerequisite for users — Pattern A in plugins-reference (matches howpyright-lspand other npm-backed plugins work).Test plan
cd packages/boxel-cli && pnpm build:plugin→ no diff (idempotent)pnpm lintinpackages/boxel-clipasses (eslint + tsc)pnpm test:unitinpackages/boxel-clipasses (158 tests)pnpm buildinpackages/boxel-cliproduces a workingdist/index.jsclaude --plugin-dir packages/boxel-cli/pluginfrom repo root:/helplists/boxel-cli:*skills/boxel-cli:realm-syncagainst a local realm-server)pnpm build:plugin, confirmgit diffshows the synopsis updateplugin.json🤖 Generated with Claude Code