* fix(#2957): claude+global post-install instructs restart and skill fallback `npx get-shit-done-cc --claude --global` writes skills to `~/.claude/skills/gsd-*/SKILL.md` (CC 2.1.88+ format) and removes the legacy `~/.claude/commands/gsd/`. The post-install message still told users to type `/gsd-new-project` without mentioning the required Claude Code restart or the skill-name fallback. On configurations where CC does not auto-surface skills in the slash menu, users hit "no commands appear" and assumed the install failed. Split the post-install message: the existing single-line instruction stays for every non-Claude runtime and for `--claude --local`. For `--claude --global` it now reads: Restart Claude Code, then in any directory either type /gsd-new-project or ask Claude to run the gsd-new-project skill. This covers both invocation paths and surfaces the restart requirement. Add tests/bug-2957-claude-global-postinstall-message.test.cjs as a regression guard: captures the printed message for claude+global, claude+local, and opencode+global; asserts content for each. Verified the test fails on main (pre-fix) and passes after the fix. Closes #2957 * test(#2957): assert legacy generic instruction is replaced not extended CodeRabbit flagged that the test would still pass if the new restart/ fallback copy were printed *alongside* the old 'open a blank directory' instruction. Adding a doesNotMatch assertion proves the claude+global branch replaces the legacy line rather than appending to it.
This commit is contained in:
@@ -10,6 +10,7 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||||||
|
|
||||||
- **`gsd-sdk query agent-skills` emits raw `<agent_skills>` block instead of JSON-wrapped string** — workflows that embed via `$(gsd-sdk query agent-skills <agent>)` were receiving a JSON-quoted string literal mid-prompt (e.g. `"<agent_skills>\n…"`), silently breaking all `<agent_skills>` injection into spawned subagents. The CLI dispatcher now honors an opt-in `format: 'text'` field on `QueryResult` and writes such results raw via `process.stdout.write`; `--pick` always returns JSON regardless. (#2917)
|
- **`gsd-sdk query agent-skills` emits raw `<agent_skills>` block instead of JSON-wrapped string** — workflows that embed via `$(gsd-sdk query agent-skills <agent>)` were receiving a JSON-quoted string literal mid-prompt (e.g. `"<agent_skills>\n…"`), silently breaking all `<agent_skills>` injection into spawned subagents. The CLI dispatcher now honors an opt-in `format: 'text'` field on `QueryResult` and writes such results raw via `process.stdout.write`; `--pick` always returns JSON regardless. (#2917)
|
||||||
- **`sketch --wrap-up` now dispatches correctly** — `/gsd-sketch --wrap-up` was silently no-oping because the flag dispatch wiring was omitted when the micro-skill entry point was absorbed in #2790. (#2949)
|
- **`sketch --wrap-up` now dispatches correctly** — `/gsd-sketch --wrap-up` was silently no-oping because the flag dispatch wiring was omitted when the micro-skill entry point was absorbed in #2790. (#2949)
|
||||||
|
- **Post-install message for `--claude --global` now reflects the skills-only layout** — `npx get-shit-done-cc --claude --global` ships skills to `~/.claude/skills/gsd-*/SKILL.md` (CC 2.1.88+ format) and removes the legacy `commands/gsd/`, but the post-install message still instructed users to type `/gsd-new-project` without mentioning the required CC restart or the skill-name fallback. Users on configurations where CC does not auto-surface skills in the slash menu hit a dead-end "no commands appear". The Claude-global branch now reads: *"Restart Claude Code, then in any directory either type /gsd-new-project or ask Claude to run the gsd-new-project skill."* Other runtimes and the `--claude --local` path are unchanged. (#2957)
|
||||||
|
|
||||||
### Added — 1.40.0-rc.1
|
### Added — 1.40.0-rc.1
|
||||||
- **Six namespace meta-skills with keyword-tag descriptions** — replace the flat 86-skill
|
- **Six namespace meta-skills with keyword-tag descriptions** — replace the flat 86-skill
|
||||||
|
|||||||
@@ -8150,6 +8150,20 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|||||||
if (runtime === 'cline') command = '/gsd-new-project';
|
if (runtime === 'cline') command = '/gsd-new-project';
|
||||||
if (runtime === 'qwen') command = '/gsd-new-project';
|
if (runtime === 'qwen') command = '/gsd-new-project';
|
||||||
if (runtime === 'hermes') command = '/gsd-new-project';
|
if (runtime === 'hermes') command = '/gsd-new-project';
|
||||||
|
|
||||||
|
// Claude Code global installs use the skills/ format (CC 2.1.88+).
|
||||||
|
// Restart is required for CC to pick up newly-installed skills, and the
|
||||||
|
// slash-menu surface depends on CC version — so the instruction needs to
|
||||||
|
// cover both invocation paths to avoid #2957-style "no commands appear".
|
||||||
|
if (runtime === 'claude' && isGlobal) {
|
||||||
|
console.log(`
|
||||||
|
${green}Done!${reset} Restart ${program}, then in any directory either type ${cyan}${command}${reset} or ask Claude to run the ${cyan}gsd-new-project${reset} skill.
|
||||||
|
|
||||||
|
${cyan}Join the community:${reset} https://discord.gg/mYgfVNfA2r
|
||||||
|
`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`
|
console.log(`
|
||||||
${green}Done!${reset} Open a blank directory in ${program} and run ${cyan}${command}${reset}.
|
${green}Done!${reset} Open a blank directory in ${program} and run ${cyan}${command}${reset}.
|
||||||
|
|
||||||
|
|||||||
70
tests/bug-2957-claude-global-postinstall-message.test.cjs
Normal file
70
tests/bug-2957-claude-global-postinstall-message.test.cjs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
process.env.GSD_TEST_MODE = '1';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bug #2957: post-install message for `--claude --global` must instruct
|
||||||
|
* users to restart Claude Code and offer the skill-name fallback, since
|
||||||
|
* the skills-only install layout (CC 2.1.88+) leaves nothing in
|
||||||
|
* commands/gsd/ for the slash menu to read on older configurations.
|
||||||
|
*
|
||||||
|
* Captures the call to finishInstall(runtime='claude', isGlobal=true) and
|
||||||
|
* asserts the printed message contains both invocation paths.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { test, describe } = require('node:test');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const path = require('node:path');
|
||||||
|
|
||||||
|
const ROOT = path.join(__dirname, '..');
|
||||||
|
const installModule = require(path.join(ROOT, 'bin', 'install.js'));
|
||||||
|
|
||||||
|
function captureFinishInstallOutput(runtime, isGlobal) {
|
||||||
|
const original = console.log;
|
||||||
|
const lines = [];
|
||||||
|
console.log = (...args) => { lines.push(args.join(' ')); };
|
||||||
|
try {
|
||||||
|
installModule.finishInstall(
|
||||||
|
'/tmp/gsd-test-settings.json',
|
||||||
|
{},
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
runtime,
|
||||||
|
isGlobal,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
console.log = original;
|
||||||
|
}
|
||||||
|
// Strip ANSI color escapes so message-content assertions don't couple to colors.
|
||||||
|
return lines.join('\n').replace(/\x1B\[[0-9;]*m/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Bug #2957: claude+global post-install message', () => {
|
||||||
|
test('claude+global message tells the user to restart and offers skill-name fallback', () => {
|
||||||
|
const output = captureFinishInstallOutput('claude', true);
|
||||||
|
|
||||||
|
assert.match(output, /restart claude code/i, 'should mention restart');
|
||||||
|
assert.match(output, /\/gsd-new-project/, 'should still mention /gsd-new-project');
|
||||||
|
assert.match(output, /gsd-new-project skill/i, 'should mention the skill name fallback');
|
||||||
|
assert.doesNotMatch(
|
||||||
|
output,
|
||||||
|
/open a blank directory/i,
|
||||||
|
'global claude install should replace, not extend, the legacy generic instruction',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('claude+local message keeps the original /gsd-new-project instruction', () => {
|
||||||
|
const output = captureFinishInstallOutput('claude', false);
|
||||||
|
|
||||||
|
assert.match(output, /\/gsd-new-project/, 'should still mention /gsd-new-project');
|
||||||
|
assert.doesNotMatch(output, /restart claude code/i, 'local install does not require the skills restart note');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('non-claude runtimes keep their original message format', () => {
|
||||||
|
const output = captureFinishInstallOutput('opencode', true);
|
||||||
|
|
||||||
|
assert.match(output, /Open a blank directory/, 'opencode message should be unchanged');
|
||||||
|
assert.doesNotMatch(output, /restart/i, 'opencode message should not have the claude-specific restart note');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user