fix(#2644): deduplicate Cursor slash menu (#2812)

* fix(#2644): deduplicate Cursor slash menu

* fix: preserve installer executable mode

* chore: add changeset for PR #2812

* test(#2644): acknowledge Cursor emission changes

* test(#2644): drop spent emitted drift acknowledgments

* fix(#2644): remove retired Cursor command converter

---------

Co-authored-by: clezcoding <clezcoding@users.noreply.github.com>
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
This commit is contained in:
𝚌𝚕𝚎𝚣𝚌𝚘𝚍𝚒𝚗𝚐
2026-08-03 18:05:45 +02:00
committed by GitHub
parent 067a4d1c6c
commit 88f6d9bd1b
29 changed files with 727 additions and 360 deletions

View File

@@ -981,36 +981,11 @@ function convertClaudeCommandToCursorSkill(content, skillName) {
const shortDescription = description.length > 180 ? `${description.slice(0, 177)}...` : description;
const adapter = getCursorSkillAdapterHeader(skillName);
// #2341: mark user-invocable:false so the skill is NOT shown in Cursor's '/'
// menu (it defaults to true). Cursor also writes a commands/ surface (#785),
// and surfacing both duplicated every /gsd-* entry. This mirrors the #789
// CodeBuddy de-dup: the commands/ surface is the sole '/' entry point; skills
// stay model-invocable background knowledge. (user-invocable:false hides from
// '/' while keeping model invocation — distinct from disable-model-invocation.)
return `---\nname: ${yamlIdentifier(skillName)}\ndescription: ${yamlQuote(shortDescription)}\nuser-invocable: false\n---\n\n${adapter}\n\n${body.trimStart()}`;
}
/**
* Convert a Claude Code command to a Cursor 1.6 slash command (#785).
*
* Cursor slash commands live in `.cursor/commands/<name>.md` and are
* plain markdown — no YAML frontmatter, no adapter header. The filename
* becomes the command name (e.g. `gsd-help.md` → `/gsd-help`).
*
* Applies the same `convertClaudeToCursorMarkdown` transforms as the skill
* converter (tool renames, brand substitution, slash-command normalisation),
* then strips the YAML frontmatter block so only the prose body remains.
*
* @param {string} content raw Claude Code command markdown (may have frontmatter)
* @param {string} _commandName the target command name (unused; present for
* API symmetry with other converters so the runtime-artifact-layout stage
* function can call it uniformly)
* @returns {string} plain markdown body, no frontmatter
*/
function convertClaudeCommandToCursorCommand(content, _commandName) {
const converted = convertClaudeToCursorMarkdown(content);
const { body } = extractFrontmatterAndBody(converted);
return body.trimStart();
// Cursor skills are both slash-invocable and model-invocable. Do not emit the
// unsupported `user-invocable` field: it is ignored by Cursor and previously
// hid the real cause of duplicate entries, the parallel commands/ surface
// retired in #2644.
return `---\nname: ${yamlIdentifier(skillName)}\ndescription: ${yamlQuote(shortDescription)}\n---\n\n${adapter}\n\n${body.trimStart()}`;
}
// --- Windsurf converters ---
@@ -3030,7 +3005,6 @@ export = {
buildKimiAgentArtifacts,
convertClaudeToCursorMarkdown,
convertClaudeCommandToCursorSkill,
convertClaudeCommandToCursorCommand,
convertClaudeToWindsurfMarkdown,
convertClaudeCommandToWindsurfSkill,
convertClaudeCommandToWindsurfWorkflow,