feat(tools): add Command Code command adapter for /opsx-* commands - #1622
feat(tools): add Command Code command adapter for /opsx-* commands#1622clay-good wants to merge 2 commits into
Conversation
Command Code documents custom slash commands under `.commandcode/commands/`, where the command name is the markdown filename without its `.md` extension (see https://commandcode.ai/docs/reference/slash-commands). That is the same flat naming Cursor and OpenCode use, so a standard flat adapter writing `.commandcode/commands/opsx-<id>.md` registers `/opsx-<id>`. Registering the adapter flips Command Code from `none` to `adapter-backed`, so with the default `both` delivery `openspec init` now generates OpenSpec commands alongside the skills it already installs under `.commandcode/skills/`. Builds on #1613, which registered Command Code as a skills-only tool. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deploying openspec-docs with
|
| Latest commit: |
41d0d63
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://32b807bd.openspec-docs.pages.dev |
| Branch Preview URL: | https://feat-command-code-command-ad.openspec-docs.pages.dev |
📝 WalkthroughWalkthroughCommand Code is added as a supported tool. Initialization generates ChangesCommand Code support
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant InitCommand
participant CommandAdapterRegistry
participant commandCodeAdapter
participant CommandFiles
InitCommand->>CommandAdapterRegistry: request command generation
CommandAdapterRegistry->>commandCodeAdapter: generateCommand
commandCodeAdapter->>CommandFiles: write .commandcode/commands/opsx-<id>.md
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/core/command-generation/adapters/command-code.ts`:
- Around line 16-17: Update the placeholder detection in command-code generation
to recognize $ARGUMENTS, $@, ${ARGUMENTS}, and ${@} anywhere in body, not only
as the complete **Provided arguments** line, so injection never duplicates an
existing placeholder. In test/core/command-generation/adapters.test.ts lines
146-155, add coverage for each placeholder appearing outside that section and
assert no second placeholder is injected.
In `@test/core/command-generation/registry.test.ts`:
- Line 133: Update the registry test around the noYamlFrontmatter list to
explicitly verify that CommandAdapterRegistry registers the "command-code"
adapter, using get, has, or a getAll membership assertion. Keep the existing
frontmatter behavior checks unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1b170c2f-8da2-4ce1-86fa-933f08370921
📒 Files selected for processing (4)
src/core/command-generation/adapters/command-code.tstest/core/command-generation/adapters.test.tstest/core/command-generation/registry.test.tstest/core/init.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- test/core/init.test.ts
| if (/^\*\*Provided arguments\*\*:\s*(?:\$(?:ARGUMENTS|@)|\$\{(?:ARGUMENTS|@)\})\s*$/m.test(body)) { | ||
| return body; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Detect supported placeholders throughout the command body.
Line 16 only recognizes a placeholder when it is the complete value of a **Provided arguments** line. A body that already uses $ARGUMENTS, $@, ${ARGUMENTS}, or ${@} elsewhere receives a second injected $ARGUMENTS line. This duplicates the invocation text.
src/core/command-generation/adapters/command-code.ts#L16-L17: Detect the supported placeholders anywhere inbodybefore injection.test/core/command-generation/adapters.test.ts#L146-L155: Add cases with each supported placeholder outside**Provided arguments**and assert that injection does not add a second placeholder.
📍 Affects 2 files
src/core/command-generation/adapters/command-code.ts#L16-L17(this comment)test/core/command-generation/adapters.test.ts#L146-L155
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/core/command-generation/adapters/command-code.ts` around lines 16 - 17,
Update the placeholder detection in command-code generation to recognize
$ARGUMENTS, $@, ${ARGUMENTS}, and ${@} anywhere in body, not only as the
complete **Provided arguments** line, so injection never duplicates an existing
placeholder. In test/core/command-generation/adapters.test.ts lines 146-155, add
coverage for each placeholder appearing outside that section and assert no
second placeholder is injected.
|
|
||
| // Tools that don't use YAML frontmatter (markdown headers or TOML or plain) | ||
| const noYamlFrontmatter = ['cline', 'kilocode', 'roocode', 'gemini']; | ||
| const noYamlFrontmatter = ['cline', 'command-code', 'kilocode', 'roocode', 'gemini']; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add an explicit Command Code registry assertion.
The noYamlFrontmatter list only affects adapters that getAll() already returns. If command-code is not registered, this test still passes. Assert that CommandAdapterRegistry.get('command-code'), has('command-code'), or getAll() includes the adapter.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/core/command-generation/registry.test.ts` at line 133, Update the
registry test around the noYamlFrontmatter list to explicitly verify that
CommandAdapterRegistry registers the "command-code" adapter, using get, has, or
a getAll membership assertion. Keep the existing frontmatter behavior checks
unchanged.
Closes #1614
Builds on #1613
Status
Ready for review. Full suite green except the two failures that are pre-existing on
main(config-profilePATH-resolution test,artifact-workflowCursor test) — baselined below.What was missing / the motivation
#1613 added Command Code as a skills-only tool (skills under
.commandcode/skills/), on the premise that "Command Code has no slash-command files." That premise is incorrect. Command Code's own docs document custom slash commands:So Command Code discovers custom commands from
.commandcode/commands/*.mdwith the same flat naming Cursor and OpenCode use. #1614 specifically wanted the/opsxcommand surface, which skills-only does not deliver.What it does
Adds a Command Code command adapter — a standard flat adapter writing
.commandcode/commands/opsx-<id>.md, which Command Code registers as/opsx-<id>.Registering the adapter flips Command Code from
nonetoadapter-backedincommand-surface.ts, so with the defaultbothdeliveryopenspec initnow generates commands alongside the skills it already installs. No new wiring — the existing delivery machinery does the rest..commandcode/skills/openspec-*/SKILL.md.commandcode/commands/opsx-<id>.md→/opsx-<id>Proof it works
adapters.test.ts): path is.commandcode/commands/opsx-explore.md, plain-Markdown output,$ARGUMENTSpropagation, and/opsx:→/opsx-reference rewriting.init.test.ts): a realopenspec init --tools command-codewrites both the skill file and.commandcode/commands/opsx-explore.md.invocation.test.tsclassifies it automatically (flat,/prefix) — no edit needed.main(verified by stash-and-run), so zero regression.Hardening
$ARGUMENTSbeside each workflow’s**Input**:contract so invocations such as/opsx-propose add-authretain user input.onboardworkflow is exempt.Notes / merge order
config.tsentry so it builds and tests green standalone), so it will conflict with feat(tools): add Command Code support as a skills-only tool #1613 on a few shared lines when feat(tools): add Command Code support as a skills-only tool #1613 lands first. All trivial:src/core/config.ts,docs/cli.md,docs/supported-tools.mdtool-ID lists — identical additions, keep one copy.docs/supported-tools.mdTool Directory row — keep this PR's (.commandcode/commands/opsx-<id>.md), drop feat(tools): add Command Code support as a skills-only tool #1613's "Not generated" version.test/core/init.test.ts— feat(tools): add Command Code support as a skills-only tool #1613's "adapterless skills-only" test asserts commands are not generated and becomes wrong after this change; delete it, keep this PR's "both skills and generated commands" test..commandcode/commands/and derives the name from the.md-less filename, per the doc quoted above. If its real command dir differs, onlycommand-code.ts'sgetFilePathneeds to change.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
openspec init --tools command-codenow generates skills in.commandcode/skillsand/opsx-<id>commands in.commandcode/commands.Documentation
Tests