All skills
mblode avatar

/scaffold-cli

@eb5e208
by Matthew Blodemblode/agent-skills136 stars
12

Scaffolds a TypeScript CLI and npm package with the house toolchain, dual tsdown outputs, CLI contracts, changesets, and publishing templates. Use when asked to "scaffold a CLI" or "start an npm package". For an existing package release use autoship; for existing API ergonomics use dx-audit.

Use this Skill: https://skilld.dev/gh/mblode/agent-skills/scaffold-cli

This session only. Nothing lands on disk.

referencesagent-friendly-cli.md

≈900 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Agent-Friendly CLI Patterns

Pinned patterns to copy into the scaffolded CLI when a command needs them. Copy the block verbatim, adjust only the command and field names. The base src/cli.ts already ships the globals these build on: --output text|json, --no-input, the stdout data / stderr log split, and the top-level JSON error envelope. Copy a pattern only when its condition holds; do not add all of them by default.

Contents


Input validation helper

Copy into src/ when a command takes an identifier, path, or URL segment. An agent will pass plausible but wrong values, and this is the last checkpoint before they reach the filesystem or a URL.

import { resolve, sep } from "node:path";

function hasControlChar(value: string): boolean {
  return [...value].some((ch) => ch.charCodeAt(0) < 0x20); // rejects bytes 0x00 to 0x1f
}

export function assertSafeId(value: string): string {
  if (hasControlChar(value) || /[?#%]/.test(value) || !/^[\w.-]+$/.test(value)) {
    throw new TypeError(`invalid id ${JSON.stringify(value)}: expected [A-Za-z0-9_.-]`);
  }
  return value;
}

export function containedPath(baseDir: string, userPath: string): string {
  const full = resolve(baseDir, userPath);
  if (full !== resolve(baseDir) && !full.startsWith(resolve(baseDir) + sep)) {
    throw new Error(`path ${JSON.stringify(userPath)} escapes ${baseDir}`);
  }
  return full;
}

export function urlSegment(value: string): string {
  return encodeURIComponent(value); // never splice raw input into a URL path
}

Dry-run pattern

Copy into any command that mutates state. --dry-run validates and reports the plan without executing.

program
  .command("delete <id>")
  .option("--dry-run", "validate and report without executing")
  .action((id: string, flags: { dryRun?: boolean }) => {
    assertSafeId(id);
    if (flags.dryRun) {
      console.error(`would delete ${id}`); // report to stderr, no side effect
      return;
    }
    // ... perform the mutation
  });

Confirmation and no-input

Copy into destructive commands. Confirm in a TTY; when stdin is not a TTY, require an explicit --yes and fail naming the flag rather than hang on a prompt.

import { confirm, isCancel } from "@clack/prompts";

async function confirmDestructive(
  action: string,
  flags: { yes?: boolean; input?: boolean },
): Promise<boolean> {
  if (!process.stdin.isTTY || flags.input === false) {
    if (!flags.yes) {
      console.error(`refusing to ${action} without --yes`);
      process.exitCode = 1;
      return false;
    }
    return true;
  }
  const ok = await confirm({ message: `${action}?` });
  return !isCancel(ok) && ok === true;
}

Schema command

Copy when the CLI has more than a couple of commands. It prints the command tree, options, defaults, and required-ness as JSON so an agent discovers the surface without scraping --help.

program
  .command("schema")
  .description("print the command surface as JSON")
  .action(() => {
    const schema = program.commands.map((cmd) => ({
      command: cmd.name(),
      description: cmd.description(),
      options: cmd.options.map((opt) => ({
        flag: opt.long,
        description: opt.description,
        default: opt.defaultValue,
        required: opt.required,
      })),
    }));
    process.stdout.write(JSON.stringify(schema));
  });

Source: SKILL.md on GitHub

2 warningstoday5 checks · Risk SAFE
  • Gen Agent Trust Hubtoday

    The skill is a developer tool for scaffolding new TypeScript CLI projects and npm packages. It performs expected filesystem and network operations to initialize repositories and install dependencies. It has an indirect prompt injection surface typical of code generators, where user-supplied strings are placed into generated files, but it also includes best-practice validation helpers for the generated software.

  • Sockettoday

    No alerts

  • Snyktoday

    Risk: MEDIUM · 1 issue

  • Runlayer6mo

    1/4 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at eb5e208. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 1 hour ago.

Activeupdated 15 hours ago
Other metadata
compatibility
Requires a shell, Git, Node.js, pnpm, and npm registry access. Remote publishing requires the relevant account authentication.

README badge

README badge for mblode/agent-skills/scaffold-cli