garrytan/gstack · warning · Error

Usage: $B skill run <name> [--arg k=v]... [--timeout=Ns]

Error message

Usage: $B skill run <name> [--arg k=v]... [--timeout=Ns]

What it means

Thrown by handleRun when args[0] is falsy — the caller invoked `$B skill run` with no skill name. Identical shape to the show-usage guard but for the run path; parseSkillRunArgs is never reached because the name check short-circuits first.

Source

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

export function parseSkillRunArgs(args: string[]): ParsedRunArgs {
  const passthrough: string[] = [];
  let timeoutSeconds = DEFAULT_TIMEOUT_SECONDS;
  for (let i = 0; i < args.length; i++) {
    const a = args[i];
    if (a.startsWith('--timeout=')) {
      const n = parseInt(a.slice('--timeout='.length), 10);
      if (!isNaN(n) && n > 0) timeoutSeconds = n;
      continue;
    }
    passthrough.push(a);
  }
  return { passthrough, timeoutSeconds };
}

async function handleRun(args: string[], ctx: SkillCommandContext): Promise<string> {
  const name = args[0];
  if (!name) throw new Error('Usage: $B skill run <name> [--arg k=v]... [--timeout=Ns]');
  const tiers = ctx.tiers ?? defaultTierPaths();
  const skill = readBrowserSkill(name, tiers);
  if (!skill) throw new Error(`Skill "${name}" not found.`);

  const { passthrough, timeoutSeconds } = parseSkillRunArgs(args.slice(1));
  const result = await spawnSkill({
    skill,
    skillArgs: passthrough,
    trusted: skill.frontmatter.trusted,
    timeoutSeconds,
    port: ctx.port,
  });

  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`

View on GitHub (pinned to 94993f7401)

Solutions

  1. Re-run with a name: `$B skill run <name> [--arg k=v]... [--timeout=Ns]`.
  2. Put the name before any flags: `$B skill run hn-frontpage --arg k=v`.
  3. Run `$B skill list` to confirm the exact name spelling.

Example fix

// before
$B skill run --timeout=30
// after
$B skill run hn-frontpage --timeout=30
Defensive patterns

Strategy: validation

Validate before calling

function requireRunArgs(args: string[]): { name: string; rest: string[] } {
  const name = args[0];
  if (!name || name.startsWith('--')) {
    throw new Error('Usage: $B skill run <name> [--arg k=v]... [--timeout=Ns]');
  }
  return { name, rest: args.slice(1) };
}

Prevention

When it happens

Trigger: handleSkillCommand(['run'], ctx) or ['run','--timeout=30'] with no positional name before the flags — note parseSkillRunArgs would happily put '--timeout=30' into passthrough, so the name guard fires first to prevent a nonsense lookup.

Common situations: Agent constructs the run command from a template and forgets to substitute the name; user passes only flags; argument array was built by splitting an empty/whitespace-only name segment.

Understand the failure class

Related errors


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