{"record":{"id":"8cb78468d550a9a8","repo":"garrytan/gstack","slug":"usage-b-skill-rm-name-global","errorCode":null,"errorMessage":"Usage: $B skill rm <name> [--global]","messagePattern":"Usage: \\$B skill rm <name> \\[--global\\]","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"browse/src/browser-skill-commands.ts","lineNumber":207,"sourceCode":"    cwd: skill.dir,\n    stdout: 'pipe',\n    stderr: 'pipe',\n    env: process.env,\n  });\n  const exitCode = await proc.exited;\n  const stdout = proc.stdout ? await new Response(proc.stdout).text() : '';\n  const stderr = proc.stderr ? await new Response(proc.stderr).text() : '';\n  if (exitCode !== 0) {\n    throw new Error(`Skill \"${name}\" tests failed (exit ${exitCode}).\\n${stderr}`);\n  }\n  return stderr || stdout || `tests passed for \"${name}\"`;\n}\n\n// ─── rm ─────────────────────────────────────────────────────────\n\nfunction handleRm(args: string[], ctx: SkillCommandContext): string {\n  const name = args[0];\n  if (!name) throw new Error('Usage: $B skill rm <name> [--global]');\n  const isGlobal = args.includes('--global');\n  const tier: 'project' | 'global' = isGlobal ? 'global' : 'project';\n\n  const tiers = ctx.tiers ?? defaultTierPaths();\n  // For UX: if no project tier exists at all, default to global.\n  const effectiveTier: 'project' | 'global' = (tier === 'project' && !tiers.project) ? 'global' : tier;\n\n  const dst = tombstoneBrowserSkill(name, effectiveTier, tiers);\n  return `Tombstoned \"${name}\" (${effectiveTier} tier) → ${dst}\\n`;\n}\n\n// ─── spawnSkill (load-bearing) ──────────────────────────────────\n\nexport interface SpawnSkillOptions {\n  skill: BrowserSkill;\n  skillArgs: string[];\n  trusted: boolean;\n  timeoutSeconds: number;","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/browser-skill-commands.ts#L189-L225","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-run with a name: `$B skill rm <name>` or `$B skill rm <name> --global`.","Run `$B skill list` to confirm the exact name and which tier it lives in.","Remember rm tombstones rather than deletes — recovery is possible from <tier>/.tombstones/."],"exampleFix":"// before\n$B skill rm --global\n// after\n$B skill rm hn-frontpage --global","handlingStrategy":"validation","validationCode":"function requireRmArgs(args: string[]): { name: string; global: boolean } {\n  const name = args[0];\n  if (!name || name.startsWith('--')) {\n    throw new Error('Usage: $B skill rm <name> [--global]');\n  }\n  return { name, global: args.includes('--global') };\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Place the skill name before --global in `skill rm` invocations.","Remember rm tombstones (move to <tier>/.tombstones/) rather than deleting.","Validate args[0] is a name, not a flag, before dispatching."],"tags":["cli-usage","skill-management","gstack"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}