garrytan/gstack · warning · Error
Usage: $B skill test <name>
Error message
Usage: $B skill test <name>
What it means
Thrown by handleTest when args[0] is falsy — `$B skill test` was invoked with no skill name. The guard fires before readBrowserSkill so no filesystem walk happens; same usage-error pattern as show/run.
Source
Thrown at browse/src/browser-skill-commands.ts:178
if (result.exitCode !== 0 || result.timedOut || result.truncated) {
const summary = result.truncated
? `truncated stdout at ${MAX_STDOUT_BYTES} bytes`
: result.timedOut
? `timed out after ${timeoutSeconds}s`
: `exit ${result.exitCode}`;
const err = new Error(`Skill "${name}" failed: ${summary}\n--- stderr ---\n${result.stderr.slice(0, 4096)}`);
(err as any).exitCode = result.exitCode || 1;
throw err;
}
return result.stdout;
}
// ─── test ───────────────────────────────────────────────────────
async function handleTest(args: string[], ctx: SkillCommandContext): Promise<string> {
const name = args[0];
if (!name) throw new Error('Usage: $B skill test <name>');
const tiers = ctx.tiers ?? defaultTierPaths();
const skill = readBrowserSkill(name, tiers);
if (!skill) throw new Error(`Skill "${name}" not found.`);
const testFile = path.join(skill.dir, 'script.test.ts');
if (!fs.existsSync(testFile)) {
throw new Error(`Skill "${name}" has no script.test.ts at ${testFile}`);
}
const proc = Bun.spawn(['bun', 'test', testFile], {
cwd: skill.dir,
stdout: 'pipe',
stderr: 'pipe',
env: process.env,
});
const exitCode = await proc.exited;
const stdout = proc.stdout ? await new Response(proc.stdout).text() : '';
const stderr = proc.stderr ? await new Response(proc.stderr).text() : '';View on GitHub (pinned to 94993f7401)
Solutions
- Re-run with a name: `$B skill test <name>`.
- Run `$B skill list` to enumerate skills that actually have test files.
- Confirm the target skill ships a script.test.ts (only skills authored with tests are testable).
Example fix
// before $B skill test // after $B skill test hn-frontpage
Defensive patterns
Strategy: validation
Validate before calling
function requireTestName(args: string[]): string {
const name = args[0];
if (!name) throw new Error('Usage: $B skill test <name>');
return name;
} Prevention
- Only testable skills have script.test.ts — check with `$B skill list` first.
- Pass the name as args[0], separate from any flags.
- Programmatic callers should validate args.length > 0 before dispatching.
When it happens
Trigger: handleSkillCommand(['test'], ctx) or ['test',''] — the subcommand resolves but no name follows. Distinct from the script.test.ts-missing error (which fires only after the skill is found).
Common situations: Incomplete command typed by an agent or user; programmatic caller forgets to append the name; CI harness issues `$B skill test` against a dynamically-resolved name that came back empty.
Related errors
- Usage: $B skill show <name>
- Usage: $B skill run <name> [--arg k=v]... [--timeout=Ns]
- Skill "${name}" has no script.test.ts at ${testFile}
- Skill "${name}" tests failed (exit ${exitCode}).\n${stderr}
- Usage: $B skill rm <name> [--global]
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/14aff7bdd9ea8302.
Report an issue: GitHub.