scaffold-cli-command
について
このスキルは、オプション処理、3つの出力モード(人間可読形式、JSON、サイレント)、およびエラー管理を含む完全な構造で、新しいCommander.js CLIコマンドの基盤を構築します。既存のCLIにコマンドを追加する場合、新規ツールをゼロから構築する場合、またはマルチコマンドアプリケーション全体でパターンを標準化する場合に設計されています。生成されるコードは、命名規則、共有コンテキスト、アクションハンドラー、および統合テストを網羅しています。
クイックインストール
Claude Code
推奨npx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/scaffold-cli-commandこのコマンドをClaude Codeにコピー&ペーストしてスキルをインストールします
ドキュメント
CLI-Befehl scaffolden
Einen neuen Befehl zu einer Commander.js-CLI-Anwendung mit konsistenter Options-Behandlung, drei Ausgabe-Modi und Integrations-Tests hinzufuegen.
Wann verwenden
- Hinzufuegen eines neuen Befehls zu einer existierenden Commander.js-CLI
- Entwerfen eines Multi-Befehl-CLI-Tools von Grund auf
- Standardisieren der Befehls-Struktur damit alle Befehle denselben Mustern folgen
- Hinzufuegen einer "Zeremonie"-Variante die Maschinen-Ausgabe mit warmer, narrativer Ausgabe ersetzt
Eingaben
- Erforderlich: Befehlsname und -verb (z.B.
gather,audit,sync) - Erforderlich: Was der Befehl tut (ein Satz)
- Erforderlich: Pfad zum CLI-Eintrittspunkt (z.B.
cli/index.js) - Optional: Ob der Befehl eine Zeremonie-Variante braucht (warme narrative Ausgabe)
- Optional: Custom-Optionen ueber das Standard-Set hinaus
- Optional: Subbefehl-Argumente (positionelle Args wie
<name>oder[names...])
Vorgehensweise
Schritt 1: Befehlsname und Kategorie waehlen
Ein Verb auswaehlen das die Aktion des Befehls kommuniziert. Befehle in Kategorien gruppieren:
| Kategorie | Verben | Muster |
|---|---|---|
| CRUD | install, uninstall, list, search | Operiert auf Inhalt |
| Lifecycle | init, sync, audit | Verwaltet Projekt-State |
| Zeremonie | gather, scatter, tend, campfire | Warme narrative Ausgabe |
Namens-Konventionen:
- Ein einzelnes Verb verwenden (nicht
install-skill— Optionen spezifizieren lassen was) - Kleinbuchstaben verwenden, keine Bindestriche im Befehlsnamen selbst
- Positionelle Args:
<required>oder[optional]oder[variadic...]
program
.command('gather <name>')
.description('Gather a team around the campfire')
Erwartet: Ein Befehlsname, eine Beschreibung und positionelle Args definiert.
Bei Fehler: Wenn das Verb mit einem existierenden Befehl ueberlappt, sie entweder komponieren (eine Option zum existierenden Befehl hinzufuegen) oder klar in der Beschreibung differenzieren.
Schritt 2: Optionen definieren
Jeder Befehl sollte ein Standard-Set geteilter Optionen plus befehl-spezifische unterstuetzen.
Standard-Optionen (nach Bedarf einbeziehen):
.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')
Befehl-spezifische Optionen — nur hinzufuegen was der Befehl braucht:
.option('--ceremonial', 'Show each item arriving individually')
.option('--only <items>', 'Comma-separated subset to include')
.option('-y, --yes', 'Skip confirmation prompts')
Design-Regeln:
- Kurze Flags (
-n) fuer haeufig genutzte Optionen - Lange Flags (
--dry-run) fuer Klarheit - Default-Werte als drittes Argument wo angemessen
- Boolesche Flags (kein Argument) fuer Toggles
Erwartet: Eine vollstaendige Options-Kette mit beiden Standard- und Custom-Optionen.
Bei Fehler: Wenn zu viele Optionen akkumulieren (>8), in Erwaegung ziehen in Subbefehle aufzuteilen oder verwandte Optionen zu gruppieren.
Schritt 3: Den Action-Handler implementieren
Der Action-Handler folgt einem konsistenten Muster:
.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);
}
})
Der getContext()-Shared-Helper zentralisiert:
- Root-Verzeichnis-Detection
- Registry-Laden
- Framework-Detection oder explizite Auswahl
- Scope-Aufloesung
Erwartet: Ein Action-Handler der dem 5-Schritte-Muster folgt: Kontext → Aufloesen → Vorschau → Ausfuehren → Ausgabe.
Bei Fehler: Wenn der Befehl nicht in das Resolve-then-Execute-Muster passt (z.B. er ist rein informationell wie detect), vereinfachen zu: Kontext → Berechnen → Ausgabe.
Schritt 4: Die drei Ausgabe-Modi hinzufuegen
Jeder Befehl sollte drei Ausgabe-Modi unterstuetzen:
Default (menschlich lesbar):
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-Ausgabe — praegnante Zeilen mit Status-Icons (+, -, =, !), keine Zeremonie, keine Dekoration.
JSON (--json):
{
"command": "install",
"items": 3,
"installed": 2,
"skipped": 1,
"failed": 0
}
Implementations-Muster:
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);
Erwartet: Alle drei Modi produzieren nuetzliche Ausgabe. JSON ist parsebar. Quiet ist praegnant. Default ist informativ.
Bei Fehler: Wenn der Befehl keine bedeutungsvolle JSON-Repraesentation hat (z.B. detect), den JSON-Modus ueberspringen und dokumentieren warum.
Schritt 5: Zeremonie-Variante hinzufuegen (Optional)
Fuer Befehle die von warmer, narrativer Ausgabe statt transaktionalem Reporting profitieren:
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,
});
}
Zeremonie-Ausgabe folgt Stimm-Regeln:
- Praesens, Aktiv ("mystic arrives", nicht "mystic was installed")
- Keine Ausrufezeichen
- Metapher ersetzt Jargon ("practices" nicht "dependencies")
- Versagen sind ehrlich, nicht katastrophal ("a spark was lost")
- Schlusszeile reflektiert Zustand ("The fire burns.")
- Keine Emojis — Unicode-Glyphen verwenden (✦ ◉ ◎ ○ ✗)
- Jedes Wort muss Information tragen
Siehe den design-cli-output-Skill fuer detaillierte Terminal-Ausgabe-Muster.
Erwartet: Zeremonie-Ausgabe die alle Stimm-Regeln befolgt und warme, informative Narrativen produziert.
Bei Fehler: Wenn die Zeremonie-Ausgabe sich erzwungen anfuehlt oder keine Information ueber die Standard-Ausgabe hinaus hinzufuegt, sie ueberspringen. Nicht jeder Befehl braucht eine Zeremonie-Variante.
Schritt 6: Fehler und Grenzfaelle behandeln
// 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);
}
Fehler-Design-Prinzipien:
- Fehlermeldungen schlagen die Korrekturmassnahme vor
process.exit(1)fuer nicht behebbare Fehler- Bestaetigungs-Prompts fuer destruktive Operationen (umgehen mit
--yes) - Dry-run ist immer erfolgreich (blockiert nie auf Bestaetigung)
Erwartet: Alle Fehler-Pfade produzieren hilfreiche Nachrichten. Destruktive Operationen erfordern Bestaetigung.
Bei Fehler: Wenn Bestaetigungs-Prompts mit Skripting interferieren, sicherstellen dass --yes und --quiet beide sie umgehen.
Schritt 7: Integrations-Tests schreiben
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/);
});
});
Siehe den test-cli-application-Skill fuer umfassende CLI-Test-Muster.
Erwartet: Mindestens 3 Tests: Dry-Run, JSON-Ausgabe, Fehler-Fall. Mehr fuer komplexe Befehle.
Bei Fehler: Wenn execSync Timeout erreicht, das Timeout erhoehen oder auf interaktive Prompts pruefen die den Befehl blockieren.
Validierung
- Befehl ist im CLI-Eintrittspunkt registriert und erscheint in
--help - Standard-Optionen (
--dry-run,--quiet,--json) funktionieren korrekt - Default-Ausgabe ist menschlich lesbar und informativ
- JSON-Ausgabe ist gueltig und parsebar
- Fehlermeldungen schlagen Korrekturmassnahmen vor
- Destruktive Operationen erfordern Bestaetigung (umgangen durch
--yes) - Mindestens 3 Integrations-Tests bestehen
- Befehl folgt dem getContext → Aufloesen → Ausfuehren → Ausgabe-Muster
Haeufige Stolperfallen
- Den JSON-Modus vergessen: Maschinen-Konsumenten (Skripte, CI) haengen von strukturierter Ausgabe ab. Immer
--jsonimplementieren auch wenn der Befehl interaktiv-only erscheint. - Bestaetigungs-Prompts blockieren Skripte: Jeder Befehl der nach Eingabe fragt wird in nicht-interaktiven Kontexten haengen. Immer
--yesfuer destruktive Befehle bereitstellen und sicherstellen dass--quietPrompts unterdrueckt. - Inkonsistente Fehler-Exit-Codes:
process.exit(1)fuer alle Fehler verwenden. Tools die CLI-Ausgabe parsen pruefen Exit-Codes zuerst. - Optionen ohne Defaults: Optionen wie
--scopesollten sinnvolle Defaults haben damit Benutzer sie nicht jedes Mal spezifizieren muessen. - Zeremonie in Quiet-Modus lecken: Das
--quiet-Flag bedeutet "minimale Ausgabe fuer Maschinen". Wenn Zeremonie-Text in Quiet-Modus leckt, werden Skripte an unerwarteter Ausgabe brechen.
Verwandte Skills
build-cli-plugin— den Adapter/das Plugin bauen auf dem Befehle operierentest-cli-application— umfassende CLI-Test-Muster ueber die Basics in Schritt 7 hinausdesign-cli-output— Terminal-Ausgabe-Design fuer alle Verbosity-Stufeninstall-almanac-content— Beispiel eines gut strukturierten CLI-Befehls-Skills
GitHub リポジトリ
関連スキル
evaluating-llms-harness
テストこのClaudeスキルは、lm-evaluation-harnessを実行し、MMLUやGSM8Kなど60以上の標準化学術タスクでLLMをベンチマークします。開発者がモデルの品質を比較し、トレーニングの進捗を追跡し、学術的な結果を報告するために設計されています。このツールはHuggingFaceやvLLMモデルを含む様々なバックエンドをサポートしています。
cloudflare-cron-triggers
テストこのスキルは、cron式を使用してWorkersをスケジュールするためのCloudflare Cron Triggersの実装に関する包括的な知識を提供します。定期的なタスクの設定、メンテナンスジョブ、自動化されたワークフローの構築を網羅し、無効なcron式やタイムゾーン問題といった一般的な課題への対処法も含みます。開発者はこれを使用して、スケジュールされたハンドラーの設定、cronトリガーのテスト、WorkflowsやGreen Computeとの連携を構成できます。
webapp-testing
テストこのClaude Skillは、Playwrightベースのツールキットを提供し、Pythonスクリプトを通じてローカルWebアプリケーションのテストを可能にします。フロントエンドの検証、UIデバッグ、スクリーンショット撮影、ログ表示を実現し、サーバーライフサイクルを管理します。ブラウザ自動化タスクにご利用いただけますが、コンテキストの汚染を避けるため、スクリプトのソースコードを読むのではなく直接実行してください。
finishing-a-development-branch
テストこのスキルは、開発者がテストの合格を確認し、構造化された統合オプションを提示することで、完成した作業を仕上げることを支援します。実装が完了した後のマージ、PR作成、ブランチの整理といったワークフローを案内します。コードが準備できてテスト済みの際に使用し、開発プロセスを体系的に完了させましょう。
