Skip to content

CS-10900: Add Claude Code plugin for boxel-cli#4632

Open
FadhlanR wants to merge 2 commits intomainfrom
cs-10900-add-claude-code-plugin-for-boxel-cli
Open

CS-10900: Add Claude Code plugin for boxel-cli#4632
FadhlanR wants to merge 2 commits intomainfrom
cs-10900-add-claude-code-plugin-for-boxel-cli

Conversation

@FadhlanR
Copy link
Copy Markdown
Contributor

@FadhlanR FadhlanR commented May 4, 2026

Summary

Ships a first-class Claude Code plugin for @cardstack/boxel-cli, packaging the kind of guidance the standalone cardstack/boxel-cli repo carries in its .claude/CLAUDE.md so it's distributable via marketplace.

  • Plugin lives at packages/boxel-cli/plugin/ with manifest .claude-plugin/plugin.json.
  • Repo-root .claude-plugin/marketplace.json lists the plugin via relative path; external users /plugin marketplace add cardstack/boxel then /plugin install boxel-cli.
  • Cardstack engineers: claude --plugin-dir packages/boxel-cli/plugin.
  • 7 skills under the /boxel-cli: namespace:
    • boxel-development.gts authoring (ported from standalone, ~90KB of evergreen Boxel patterns)
    • boxel-file-structure — file/directory naming + adoptsFrom rules (ported from standalone)
    • realm-sync, realm-history, file-ops, search, profile — new wrappers around the monorepo CLI's namespaced commands (incl. CS-10627 file touch)

How "generated from the code" works

scripts/build-plugin.ts walks the Commander tree and rewrites the <!-- generated:commands --> block inside each SKILL.md. The Commander tree is extracted into src/build-program.ts so 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:

  1. Synopsis freshnesspnpm build:plugin && git diff --exit-code. Fails if commands changed without regenerating skills.
  2. Synopsis-bump coupling — if any generated block is in the diff, plugin.json version must also be in the diff. Without a version bump, Claude's marketplace cache won't surface the update.

Versioning

Plugin and CLI version independently:

  • Prose-only update → bump plugin.json only.
  • CLI command added/changed → bump both (synopsis must regenerate; CI enforces).
  • CLI internal refactor → bump package.json only.

The plugin is not npm-published. The marketplace clones it from cardstack/boxel directly. npm install -g @cardstack/boxel-cli remains the prerequisite for users — Pattern A in plugins-reference (matches how pyright-lsp and other npm-backed plugins work).

Test plan

  • cd packages/boxel-cli && pnpm build:plugin → no diff (idempotent)
  • pnpm lint in packages/boxel-cli passes (eslint + tsc)
  • pnpm test:unit in packages/boxel-cli passes (158 tests)
  • pnpm build in packages/boxel-cli produces a working dist/index.js
  • claude --plugin-dir packages/boxel-cli/plugin from repo root: /help lists /boxel-cli:* skills
  • Smoke-test one skill end-to-end (e.g., /boxel-cli:realm-sync against a local realm-server)
  • Pin a fake CLI command change locally, re-run pnpm build:plugin, confirm git diff shows the synopsis update
  • CI: synopsis-freshness gate fails on a PR that changes a Commander option without regenerating
  • CI: version-bump-coupling gate fails on a PR that changes a generated block without bumping plugin.json

🤖 Generated with Claude Code

FadhlanR and others added 2 commits May 4, 2026 18:48
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>
@FadhlanR FadhlanR marked this pull request as ready for review May 5, 2026 05:45
@FadhlanR FadhlanR requested a review from a team May 5, 2026 05:46
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +137 to +138
SYNOPSIS_CHANGED=$(git diff "$BASE" "$HEAD" -- 'packages/boxel-cli/plugin/skills/**/SKILL.md' \
| grep -E '^[+-](### `boxel |\*\*Arguments|\*\*Options|- `[-A-Za-z]+|- `<|- `\[)' || true)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail when synopsis diff cannot be computed

The synopsis/version coupling check masks git diff errors by appending || true inside the SYNOPSIS_CHANGED assignment, so if either SHA is unavailable (for example in shallow checkouts) the step silently treats it as “no synopsis changes” and exits successfully. This makes the guard non-deterministic and can allow generated skill updates to merge without the required plugin version bump.

Useful? React with 👍 / 👎.

HEAD="${{ github.event.pull_request.head.sha }}"
# Did any synopsis line change?
SYNOPSIS_CHANGED=$(git diff "$BASE" "$HEAD" -- 'packages/boxel-cli/plugin/skills/**/SKILL.md' \
| grep -E '^[+-](### `boxel |\*\*Arguments|\*\*Options|- `[-A-Za-z]+|- `<|- `\[)' || true)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect all generated synopsis edits before skipping bump check

The grep pattern only matches headings/argument/option bullet formats, so generated-block edits that only change descriptive text (for example updated command descriptions from Commander metadata) are ignored and the workflow skips the version-bump requirement. Since those description lines are part of the generated synopsis, this creates a false negative and can publish stale plugin content under an unchanged version.

Useful? React with 👍 / 👎.

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