Fix skill subcommand help handling (#708)

Ensure install, link, update, and check render static help before entering any operational path. Covers top-level and legacy routing for both -h and --help.

AI-assisted implementation under maintainer direction.
This commit is contained in:
Paul Bakaus
2026-09-02 11:38:23 -04:00
committed by GitHub
parent c0f4952122
commit a264199177
2 changed files with 87 additions and 0 deletions
+53
View File
@@ -525,6 +525,54 @@ async function promptCheckbox(message, options, { selectedValues = [] } = {}) {
// ─── skills help ──────────────────────────────────────────────────────────────
const SUBCOMMAND_HELP = {
install: `Usage: impeccable install [options]
Install compiled Impeccable skills into project or user-level harness folders.
Options:
-y, --yes Accept detected defaults without prompting
--providers=<names> Comma-separated harnesses to install
--scope=<scope> Install scope: project or global
--project Install into the current project
--user, --global Install at the user level
--no-hooks Install skills without provider hook manifests
--force Replace an existing installation
-h, --help Show this help message`,
link: `Usage: impeccable link [options]
Link Impeccable skills from a local checkout or submodule.
Options:
--source=<path> Source checkout (default: .impeccable)
--providers=<names> Comma-separated harnesses to link
-y, --yes Accept detected defaults without prompting
--force Replace existing skill folders with links
-h, --help Show this help message`,
update: `Usage: impeccable update [options]
Update an existing Impeccable skill installation.
Options:
-y, --yes Accept detected defaults without prompting
--scope=<scope> Update scope: project or global
--project Update the current project installation
--user, --global Update the user-level installation
--no-hooks Update skills without changing hook manifests
--force Replace installed skill files
-h, --help Show this help message`,
check: `Usage: impeccable check [options]
Check whether installed Impeccable skills are up to date.
Options:
-h, --help Show this help message`,
};
function showSubcommandHelp(subcommand) {
console.log(SUBCOMMAND_HELP[subcommand]);
}
async function showHelp() {
let commands;
try {
@@ -2533,6 +2581,11 @@ export {
export async function run(args) {
const sub = args[0];
if (SUBCOMMAND_HELP[sub] && args.slice(1).some(arg => arg === '--help' || arg === '-h')) {
showSubcommandHelp(sub);
return;
}
if (!sub || sub === 'help' || sub === '--help' || sub === '-h') {
await showHelp();
} else if (sub === 'install') {
+34
View File
@@ -864,6 +864,40 @@ describe('skills install/update: local universal bundle e2e', () => {
expect(output).not.toContain('skills install Install impeccable skills');
});
test('skill-management subcommand help exits before downloads, prompts, or writes (#699)', () => {
const commands = ['install', 'link', 'update', 'check'];
const prefixes = ['', 'skills '];
const helpFlags = ['--help', '-h'];
for (const command of commands) {
for (const prefix of prefixes) {
for (const helpFlag of helpFlags) {
const tmp = mkdtempSync(join(tmpdir(), `imp-test-${command}-help-`));
const home = mkdtempSync(join(tmpdir(), `imp-home-${command}-help-`));
execSync('git init', { cwd: tmp });
const output = run(`${prefix}${command} ${helpFlag}`, {
cwd: tmp,
env: {
...process.env,
HOME: home,
IMPECCABLE_BUNDLE_PATH: join(tmp, 'must-not-be-read'),
},
});
expect(output).toContain(`Usage: impeccable ${command}`);
for (const provider of ['.agents', '.claude', '.cursor', '.impeccable']) {
expect(existsSync(join(tmp, provider))).toBe(false);
expect(existsSync(join(home, provider))).toBe(false);
}
rmSync(tmp, { recursive: true, force: true });
rmSync(home, { recursive: true, force: true });
}
}
}
}, 30000);
test('top-level install aliases the legacy skills install command', () => {
const tmp = mkdtempSync(join(tmpdir(), 'imp-test-top-level-install-'));
const home = mkdtempSync(join(tmpdir(), 'imp-home-top-level-install-'));