garrytan/gstack · warning · Error

Usage: $B skill rm <name> [--global]

Error message

Usage: $B skill rm <name> [--global]

What it means

Thrown by handleRm when args[0] is falsy — `$B skill rm` was invoked with no skill name. The --global flag is parsed only after this guard, so `$B skill rm --global` without a name still trips this error first.

Source

Thrown at browse/src/browser-skill-commands.ts:207

    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() : '';
  if (exitCode !== 0) {
    throw new Error(`Skill "${name}" tests failed (exit ${exitCode}).\n${stderr}`);
  }
  return stderr || stdout || `tests passed for "${name}"`;
}

// ─── rm ─────────────────────────────────────────────────────────

function handleRm(args: string[], ctx: SkillCommandContext): string {
  const name = args[0];
  if (!name) throw new Error('Usage: $B skill rm <name> [--global]');
  const isGlobal = args.includes('--global');
  const tier: 'project' | 'global' = isGlobal ? 'global' : 'project';

  const tiers = ctx.tiers ?? defaultTierPaths();
  // For UX: if no project tier exists at all, default to global.
  const effectiveTier: 'project' | 'global' = (tier === 'project' && !tiers.project) ? 'global' : tier;

  const dst = tombstoneBrowserSkill(name, effectiveTier, tiers);
  return `Tombstoned "${name}" (${effectiveTier} tier) → ${dst}\n`;
}

// ─── spawnSkill (load-bearing) ──────────────────────────────────

export interface SpawnSkillOptions {
  skill: BrowserSkill;
  skillArgs: string[];
  trusted: boolean;
  timeoutSeconds: number;

View on GitHub (pinned to 94993f7401)

Solutions

  1. Re-run with a name: `$B skill rm <name>` or `$B skill rm <name> --global`.
  2. Run `$B skill list` to confirm the exact name and which tier it lives in.
  3. Remember rm tombstones rather than deletes — recovery is possible from <tier>/.tombstones/.

Example fix

// before
$B skill rm --global
// after
$B skill rm hn-frontpage --global
Defensive patterns

Strategy: validation

Validate before calling

function requireRmArgs(args: string[]): { name: string; global: boolean } {
  const name = args[0];
  if (!name || name.startsWith('--')) {
    throw new Error('Usage: $B skill rm <name> [--global]');
  }
  return { name, global: args.includes('--global') };
}

Prevention

When it happens

Trigger: handleSkillCommand(['rm'], ctx), ['rm',''], or ['rm','--global'] (the --global is treated as no name because args[0] is '--global' which is truthy but not a valid name — note this slips through the usage guard and would fail later in tombstoneBrowserSkill as 'not found'). The pure usage error fires only when args[0] is genuinely empty.

Common situations: Agent or user runs `$B skill rm --global` expecting it to be prompted for a name; a destructive-ops confirmation wrapper strips the name; argument array built incorrectly by a script.

Related errors


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/8cb78468d550a9a8. Report an issue: GitHub.