MCP HubMCP Hub
Retour aux compétences

scaffold-cli-command

pjt222
Mis à jour 2 days ago
7 vues
17
2
17
Voir sur GitHub
Teststestingdesign

À propos

Cette compétence échafaude une nouvelle commande CLI pour une application Commander.js, générant la structure pour les options, un gestionnaire d'action et trois modes de sortie (lisible par l'humain, silencieux, JSON). Elle couvre la dénomination des commandes, la gestion des erreurs et les tests d'intégration pour garantir la cohérence. Utilisez-la lors de l'ajout à une CLI existante, de la construction d'un nouvel outil à partir de zéro ou de la standardisation des commandes dans une CLI à commandes multiples.

Installation rapide

Claude Code

Recommandé
Principal
npx skills add pjt222/agent-almanac -a claude-code
Commande PluginAlternatif
/plugin add https://github.com/pjt222/agent-almanac
Git CloneAlternatif
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/scaffold-cli-command

Copiez et collez cette commande dans Claude Code pour installer cette compétence

Documentation

Scaffold a CLI Command

Add new command to Commander.js CLI app. Consistent option handling, three output modes, integration tests.

When Use

  • Add new command to existing Commander.js CLI
  • Design multi-command CLI tool from scratch
  • Standardize command structure so all follow same patterns
  • Add "ceremony" variant — replace machine output with warm narrative

Inputs

  • Required: Command name + verb (e.g., gather, audit, sync)
  • Required: What command does (one sentence)
  • Required: Path to CLI entry (e.g., cli/index.js)
  • Optional: Ceremony variant (warm narrative output)
  • Optional: Custom options beyond standard
  • Optional: Subcommand args (positional <name> or [names...])

Steps

Step 1: Choose Command Name and Category

Pick verb that says what command does. Group commands by category.

CategoryVerbsPattern
CRUDinstall, uninstall, list, searchOperates on content
Lifecycleinit, sync, auditManages project state
Ceremonygather, scatter, tend, campfireWarm narrative output

Naming.

  • Single verb (not install-skill — let options specify what)
  • Lowercase, no hyphens in command name itself
  • Positional args: <required> or [optional] or [variadic...]
program
  .command('gather <name>')
  .description('Gather a team around the campfire')

Got: Command name, description, positional args defined.

If fail: Verb overlaps existing? Compose (add option to existing) or differentiate clearly in description.

Step 2: Define Options

Every command should support standard shared options + command-specific.

Standard options (include as needed).

  .option('-n, --dry-run', 'Preview without making changes')
  .option('-q, --quiet', 'Suppress human-readable output')
  .option('--json', 'Output as JSON')
  .option('-f, --framework <id>', 'Target specific framework')
  .option('-g, --global', 'Use global scope')
  .option('--scope <scope>', 'Scope: project, workspace, global', 'project')
  .option('--source <path>', 'Path to tool root directory')

Command-specific options — add only what command needs.

  .option('--ceremonial', 'Show each item arriving individually')
  .option('--only <items>', 'Comma-separated subset to include')
  .option('-y, --yes', 'Skip confirmation prompts')

Design rules.

  • Short flags (-n) for frequent options
  • Long flags (--dry-run) for clarity
  • Defaults as third arg where appropriate
  • Boolean flags (no arg) for toggles

Got: Complete option chain — standard + custom.

If fail: Too many options (>8)? Split into subcommands or group related.

Step 3: Implement Action Handler

Action handler follows consistent pattern.

.action(async (name, options) => {
  // 1. Get shared context (registries, adapters, paths)
  const ctx = getContext(options);

  // 2. Resolve what to operate on
  const items = resolveItems(ctx, name, options);
  if (!items || items.length === 0) {
    reporter.error('Nothing found.');
    process.exit(1);
  }

  // 3. Preview if dry-run
  if (options.dryRun) reporter.printDryRun();

  // 4. Execute the operation
  const results = await executeOperation(items, ctx, options);

  // 5. Output results (3 modes)
  if (options.json) {
    console.log(JSON.stringify(results, null, 2));
  } else if (options.quiet) {
    reporter.printResults(results);
  } else {
    printHumanOutput(results, options);
  }
})

getContext() shared helper centralizes.

  • Root directory detection
  • Registry loading
  • Framework detection or explicit selection
  • Scope resolution

Got: Action handler follows 5-step pattern: context → resolve → preview → execute → output.

If fail: Command does not fit resolve-then-execute (purely informational like detect)? Simplify: context → compute → output.

Step 4: Add Three Output Modes

Every command should support three output modes.

Default (human-readable):

Installing 3 item(s) to Claude Code...

  + create-skill [claude-code] .claude/skills/create-skill
  + write-tests  [claude-code] .claude/skills/write-tests
  = commit-changes [claude-code] (skipped)

  2 installed, 1 skipped

Quiet (--quiet): Standard reporter output — concise lines with status icons (+, -, =, !), no ceremony, no decoration.

JSON (--json):

{
  "command": "install",
  "items": 3,
  "installed": 2,
  "skipped": 1,
  "failed": 0
}

Implementation.

if (options.json) {
  console.log(JSON.stringify(data, null, 2));
  return;
}
if (options.quiet) {
  reporter.printResults(results);
  return;
}
// Default: human-readable output
printHumanReadable(results, options);

Got: All three modes useful. JSON parseable. Quiet concise. Default informative.

If fail: Command no meaningful JSON (e.g., detect)? Skip JSON mode, document why.

Step 5: Add Ceremony Variant (Optional)

For commands that benefit from warm, narrative output instead of transactional.

if (options.json) {
  ceremonyReporter.printJson(data);
} else if (options.quiet) {
  reporter.printResults(results);
} else {
  ceremonyReporter.printArrival({
    teamId: name,
    agents,
    results: { installed, skipped, failed },
    ceremonial: options.ceremonial || false,
  });
}

Ceremony output voice rules.

  1. Present tense, active voice ("mystic arrives", not "mystic was installed")
  2. No exclamation marks
  3. Metaphor replaces jargon ("practices" not "dependencies")
  4. Failures honest, not catastrophic ("a spark was lost")
  5. Closing line reflects state ("The fire burns.")
  6. No emoji — use Unicode glyphs (✦ ◉ ◎ ○ ✗)
  7. Every word must carry information

See design-cli-output skill for detailed terminal output patterns.

Got: Ceremony output follows all voice rules, produces warm, informative narratives.

If fail: Ceremony feels forced or no info beyond standard? Skip. Not every command needs ceremony.

Step 6: Handle Errors and Edge Cases

// Unknown item
if (!item) {
  reporter.error(`Unknown: ${name}. Use 'tool list' to browse.`);
  process.exit(1);
}

// Confirmation for destructive actions
if (!options.yes && !options.quiet && !options.dryRun) {
  const answer = await askYesNo('Proceed?');
  if (!answer) {
    console.log('  Cancelled.');
    return;
  }
}

// State validation
if (!state.fires[name]) {
  reporter.error(`Not active. Nothing to remove.`);
  process.exit(1);
}

Error design.

  • Error msgs suggest corrective action
  • process.exit(1) for unrecoverable
  • Confirmation for destructive (bypass with --yes)
  • Dry-run always succeeds (never blocks on confirmation)

Got: All error paths give helpful msgs. Destructive ops require confirmation.

If fail: Confirmation interferes with scripting? Ensure --yes and --quiet both bypass.

Step 7: Write Integration Tests

import { describe, it, after } from 'node:test';
import assert from 'node:assert/strict';
import { execSync } from 'child_process';

const CLI = 'node cli/index.js';
function run(args) {
  return execSync(`${CLI} ${args}`, { encoding: 'utf8', timeout: 10000 });
}

describe('new-command', () => {
  after(() => { /* cleanup created files/state */ });

  it('dry-run shows preview', () => {
    const out = run('new-command arg --dry-run');
    assert.match(out, /DRY RUN/);
  });

  it('--json outputs valid JSON', () => {
    const out = run('new-command arg --json');
    const start = out.indexOf('{');
    const data = JSON.parse(out.slice(start));
    assert.equal(data.command, 'new-command');
  });

  it('rejects unknown input', () => {
    assert.throws(() => run('new-command nonexistent'), /Unknown/);
  });
});

See test-cli-application skill for full CLI testing patterns.

Got: At least 3 tests: dry-run, JSON output, error case. More for complex commands.

If fail: execSync times out? Up timeout or check for interactive prompts blocking command.

Checks

  • Command registered in CLI entry, appears in --help
  • Standard options (--dry-run, --quiet, --json) work
  • Default output human-readable, informative
  • JSON output valid, parseable
  • Error msgs suggest corrective actions
  • Destructive ops require confirmation (bypass --yes)
  • At least 3 integration tests pass
  • Command follows getContext → resolve → execute → output pattern

Pitfalls

  • Forget JSON mode: Machine consumers (scripts, CI) need structured output. Always implement --json even if seems interactive-only.
  • Confirmation prompts block scripts: Any command that prompts hangs in non-interactive contexts. Always provide --yes for destructive, ensure --quiet suppresses prompts.
  • Inconsistent error exit codes: Use process.exit(1) for all errors. Tools parsing CLI output check exit codes first.
  • Options without defaults: --scope should have sensible default so users do not specify every time.
  • Leak ceremony into quiet mode: --quiet = "minimal output for machines." Ceremony text leak = scripts break on unexpected output.

See Also

  • build-cli-plugin — build adapter/plugin commands operate on
  • test-cli-application — full CLI testing patterns beyond Step 7 basics
  • design-cli-output — terminal output design for all verbosity levels
  • install-almanac-content — example well-structured CLI command skill

Dépôt GitHub

pjt222/agent-almanac
Chemin: i18n/caveman/skills/scaffold-cli-command
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

Compétences associées

evaluating-llms-harness

Tests

Cette compétence Claude exécute le lm-evaluation-harness pour évaluer les modèles de langage sur plus de 60 tâches académiques standardisées telles que MMLU et GSM8K. Elle est conçue pour permettre aux développeurs de comparer la qualité des modèles, de suivre les progrès de l'entraînement ou de rapporter des résultats académiques. L'outil prend en charge différents backends, incluant les modèles HuggingFace et vLLM.

Voir la compétence

cloudflare-cron-triggers

Tests

Cette compétence fournit une connaissance complète pour la mise en œuvre de Déclencheurs Cron Cloudflare afin de planifier des Workers à l'aide d'expressions cron. Elle couvre la configuration de tâches périodiques, de travaux de maintenance et de flux de travail automatisés, tout en traitant des problèmes courants tels que les expressions cron non valides et les problèmes de fuseau horaire. Les développeurs peuvent l'utiliser pour configurer des gestionnaires planifiés, tester des déclencheurs cron et intégrer avec Workflows et Green Compute.

Voir la compétence

webapp-testing

Tests

Cette Compétence Claude fournit une boîte à outils basée sur Playwright pour tester des applications web locales via des scripts Python. Elle permet la vérification frontend, le débogage d'interface utilisateur, la capture d'écrans et la consultation des journaux, tout en gérant les cycles de vie du serveur. Utilisez-la pour les tâches d'automatisation de navigateur, mais exécutez les scripts directement plutôt que de lire leur code source pour éviter la pollution du contexte.

Voir la compétence

finishing-a-development-branch

Tests

Cette compétence aide les développeurs à finaliser leur travail en vérifiant que les tests passent, puis en présentant des options d'intégration structurées. Elle guide le processus de fusion, de création de PRs ou de nettoyage des branches une fois l'implémentation terminée. Utilisez-la lorsque votre code est prêt et testé pour finaliser systématiquement le cycle de développement.

Voir la compétence