Summary
OpenSpec documents slash commands with colon syntax (/opsx:propose, /opsx:apply, …), but openspec init --tools cursor generates Cursor command files that register hyphen syntax (/opsx-propose, /opsx-apply, …) in the command palette. Users who follow OpenSpec docs cannot invoke the commands they expect.
Related: #680 (same class of mismatch for Qwen CLI).
Environment
- OpenSpec CLI: 1.5.0
- Cursor IDE (slash commands from
.cursor/commands/)
- Configured via
openspec init --tools cursor
Expected behavior
After openspec init or openspec update for Cursor:
- The command palette should list
/opsx:propose, /opsx:apply, /opsx:explore, /opsx:archive, /opsx:sync.
- The post-init "Getting started" message, generated command bodies, and skills should all use the same colon syntax.
- In-file cross-references (e.g. "run
/opsx:apply") should match what the palette registers.
Actual behavior
Command palette shows hyphens, not colons
Typing /opsx in Cursor shows:
opsx-propose
opsx-apply
opsx-explore
opsx-archive
opsx-sync
The user cannot invoke /opsx:propose — only /opsx-propose.
Init message uses colons (correct per OpenSpec docs)
displaySuccessMessage() in src/core/init.ts prints colon syntax:
Start your first change: /opsx:propose "your idea"
So docs and palette disagree.
Cursor adapter hardcodes hyphen syntax
The Cursor adapter (src/core/command-generation/adapters/cursor.ts) writes:
// File path
return path.join('.cursor', 'commands', `opsx-${commandId}.md`);
// Frontmatter
name: /opsx-${content.id}
id: opsx-${content.id}
By contrast, the Claude adapter uses content.name, which is the canonical colon form (/opsx:propose).
Generated command bodies also mix conventions depending on version/update path — sometimes colon references inside files whose frontmatter registers hyphens.
transformToHyphenCommands makes things worse for Cursor
transformToHyphenCommands() (src/utils/command-references.ts) converts /opsx: → /opsx-. It is applied for opencode and pi in src/core/init.ts and src/core/update.ts, but the Cursor adapter already emits hyphens in frontmatter regardless. The real fix is not to hyphenate Cursor content — it is to emit colon syntax for Cursor, consistent with OpenSpec docs and the Claude adapter.
Steps to reproduce
openspec init --tools cursor in a fresh project (or openspec update --force).
- Restart Cursor.
- Type
/opsx in the command palette → commands appear as opsx-propose, not opsx:propose.
- Compare with
openspec init success output which says /opsx:propose.
Suggested fix
- Cursor adapter: use
content.name (colon form) in frontmatter, same as Claude:
name: ${escapeYamlValue(content.name)} // /opsx:propose
- Investigate Cursor command registration: confirm whether colon syntax in
name is sufficient, or whether file naming (opsx-<id>.md) forces hyphen display — if so, consider a nested layout (e.g. .cursor/commands/opsx/<id>.md) similar to Claude.
- Do not apply
transformToHyphenCommands to Cursor.
- Keep colon syntax in
displaySuccessMessage() / welcome text when that is the canonical form.
Related issues
Summary
OpenSpec documents slash commands with colon syntax (
/opsx:propose,/opsx:apply, …), butopenspec init --tools cursorgenerates Cursor command files that register hyphen syntax (/opsx-propose,/opsx-apply, …) in the command palette. Users who follow OpenSpec docs cannot invoke the commands they expect.Related: #680 (same class of mismatch for Qwen CLI).
Environment
.cursor/commands/)openspec init --tools cursorExpected behavior
After
openspec initoropenspec updatefor Cursor:/opsx:propose,/opsx:apply,/opsx:explore,/opsx:archive,/opsx:sync./opsx:apply") should match what the palette registers.Actual behavior
Command palette shows hyphens, not colons
Typing
/opsxin Cursor shows:The user cannot invoke
/opsx:propose— only/opsx-propose.Init message uses colons (correct per OpenSpec docs)
displaySuccessMessage()insrc/core/init.tsprints colon syntax:So docs and palette disagree.
Cursor adapter hardcodes hyphen syntax
The Cursor adapter (
src/core/command-generation/adapters/cursor.ts) writes:By contrast, the Claude adapter uses
content.name, which is the canonical colon form (/opsx:propose).Generated command bodies also mix conventions depending on version/update path — sometimes colon references inside files whose frontmatter registers hyphens.
transformToHyphenCommandsmakes things worse for CursortransformToHyphenCommands()(src/utils/command-references.ts) converts/opsx:→/opsx-. It is applied foropencodeandpiinsrc/core/init.tsandsrc/core/update.ts, but the Cursor adapter already emits hyphens in frontmatter regardless. The real fix is not to hyphenate Cursor content — it is to emit colon syntax for Cursor, consistent with OpenSpec docs and the Claude adapter.Steps to reproduce
openspec init --tools cursorin a fresh project (oropenspec update --force)./opsxin the command palette → commands appear asopsx-propose, notopsx:propose.openspec initsuccess output which says/opsx:propose.Suggested fix
content.name(colon form) in frontmatter, same as Claude:nameis sufficient, or whether file naming (opsx-<id>.md) forces hyphen display — if so, consider a nested layout (e.g..cursor/commands/opsx/<id>.md) similar to Claude.transformToHyphenCommandsto Cursor.displaySuccessMessage()/ welcome text when that is the canonical form.Related issues