Help us improve
Share bugs, ideas, or general feedback.
From cli-spec-to-goal
Convert a Node.js CLI tool specification (even a vague one) into a Codex /goal-ready bundle — GOAL.md, VERIFY.md, PROGRESS.md inside goals/<slug>/ — with AI-agent-friendly patterns (--json, stdout/stderr separation, exit codes, structured errors, TTY detection, --dry-run) baked into every goal. Asks clarifying questions in focused batches (each with options + recommendation + reasoning), reaches 95% confidence, optionally scaffolds a missing CLI project (bin/, src/, package.json, AGENTS.md, CLAUDE.md behavioral snippet), and emits a tailored /goal command. Handles both new CLIs and adding commands to existing ones. Supports JavaScript (default) and TypeScript, commander.js, Vitest, conditional SQLite and cosmiconfig. For Node.js CLI tools, not web apps, servers, or non-Node projects.
npx claudepluginhub nathanonn/agent-skills --plugin cli-spec-to-goalHow this skill is triggered — by the user, by Claude, or both
Slash command
/cli-spec-to-goal:cli-spec-to-goalThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Turn a rough Node.js CLI tool idea into the three files Codex `/goal` needs to drive autonomous implementation:
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Explores codebases via GitNexus: discover repos, query execution flows, trace processes, inspect symbol callers/callees, and review architecture.
Share bugs, ideas, or general feedback.
Turn a rough Node.js CLI tool idea into the three files Codex /goal needs to drive autonomous implementation:
goals/<slug>/
GOAL.md what done looks like (full CLI tool template with AI-agent patterns)
VERIFY.md how /goal proves it's done (host-native verification)
PROGRESS.md the audit trail /goal will populate
The skill optionally scaffolds a missing CLI project (bin/, src/, package.json, AGENTS.md, CLAUDE.md) and prints a tailored /goal command at the end.
A full multi-prompt workflow kit is overkill for CLI tools that fit in one or two goal slices. This skill collapses the "spec → goal trio" hop into a single guided conversation that:
It does not replace the multi-prompt kit for complex CLI suites with 10+ commands. Use the kit for big builds; use this skill for the small-to-medium ones.
Every GOAL.md, VERIFY.md, and scaffold generated by this skill includes these patterns. They make CLI tools safe and useful for AI agents to invoke — not just humans.
--json flag on every command — stdout receives only valid JSON; no spinners, colors, or progress bars. Gold standard: the gh CLI.!process.stdin.isTTY.--json is active: { "error": "CODE", "message": "...", "suggestion": "..." }.--dry-run on mutating commands — any create/update/delete command previews without executing.These patterns reinforce each other: --json + structured errors = machine-parseable success and failure; TTY detection + --dry-run = safe automated execution.
goals-plan.md.goals/<slug>/./goal command + a short "how to run" note.Never write any files until confidence on what's about to be produced is at 95%+.
Before asking the user anything, inspect the cwd. The point is to ground recommendations in reality so questions don't waste the user's time on things already settled by the project state.
Look for:
| Signal | What it tells us |
|---|---|
package.json → bin field | Existing CLI entry point; binary name already chosen |
package.json → type field | ESM vs CJS — skip module system question |
package.json → engines | Node version constraint |
package.json → scripts | Existing test/lint/build commands |
package.json → dependencies | Arg parsing lib already chosen (commander/yargs/meow/citty) |
package.json → devDependencies | Test framework (vitest/jest), TS, linter (eslint/biome) |
tsconfig.json | TypeScript project — skip language question |
bin/ or src/cli.* | Existing entry points |
.env / .env.example | External service config pattern in use |
goals/ folder | Previous goal runs; pick non-conflicting slug |
AGENTS.md | Existing conventions to respect |
CLAUDE.md | Existing behavioral guidance to reference |
vitest.config.* / jest.config.* | Test infra in place — skip framework question |
.gitignore | Check coverage for node_modules, .env, dist/ |
eslint.config.* / biome.json | Lint setup exists |
*.db / *.sqlite / drizzle/ / migrations/ | Data storage in use — triggers data storage questions |
.toolrc / *.config.js / cosmiconfig in deps | Config file pattern already wired |
src/auth.* / src/oauth.* | OAuth flow already implemented |
open or opener in deps | Browser-opening for OAuth consent flow |
.env containing CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, or REFRESH_TOKEN | OAuth credentials pattern in use |
Use this to inform Step 3 recommendations. Skip questions that the probe already answers.
New vs. existing CLI detection:
bin field in package.json or src/cli.* exists → existing CLI, focus on adding commandsRead the user's spec and decide whether it fits one goal or wants to be split.
Multi-goal signals:
--help before vertical features)If multi-goal, surface it before other clarifying questions:
This spec looks like it could be 2-3 separate goals. I can either generate one combined goal or write a
goals-plan.mdand scaffold the first slice. Which do you prefer?
If the user picks split, write goals-plan.md at the project root with a numbered list of proposed goals (each with a 1-2 line description), then ask which slice to generate first. Re-run the skill later for the next slice.
Use the AskUserQuestion tool when available. Fall back to natural-language Q&A with the same shape: 2-4 questions per round, each with 2-4 options, recommended option first and labeled (Recommended), plus a one-line reason for the recommendation.
Aim for ≤3 rounds total. Skip any question already answered by the spec or the probe.
Only ask questions not settled by the probe.
type field found in package.json. ESM because it's 2026.If existing CLI: Replace identity questions with:
Configuration decision matrix:
| Scenario | Recommendation |
|---|---|
| API credentials only | Env vars + dotenv only |
| 1-3 non-secret settings | CLI flags only |
| >3 non-secret persistent settings | Env vars + dotenv + cosmiconfig |
| Per-project tool | cosmiconfig |
| User-global tool | Env vars or XDG config |
Only surface when the probe detects storage signals (*.db, *.sqlite, better-sqlite3 in deps, drizzle/, migrations/) OR the spec mentions persistence keywords (store, save, history, cache, log, database, persist, record, track, remember, catalog, index).
SQLite via better-sqlite3 is recommended because: zero setup (no server, connection string, or Docker), single file, synchronous API, AI-agent-friendly (no daemon to manage).
Only surface when the tool has many non-secret settings that users would want to persist across runs.
.toolrc, tool.config.js, etc.) / No (CLI flags only). Recommend yes if >3 persistent settings.Only surface when the probe detects OAuth signals (existing src/auth.*, open in deps, CLIENT_ID in .env) OR the spec mentions OAuth authentication with an external API that requires user consent (not just a static API key).
OAuth keywords: oauth, login, authenticate, authorization, consent, token, refresh token, access token, redirect, callback URL.
auth login.The OAuth flow uses Authorization Code with a temporary localhost redirect server (like gh auth login). The scaffold adds src/auth.js, src/token-store.js, and src/commands/auth.js with auth login, auth status, and auth logout subcommands.
If OAuth is active, it may independently trigger SQLite as a dependency (for Tier 2 or access token caching). When both OAuth and the data storage layer are active, they share the same SQLite database.
After each round, ask yourself: "If I started writing files now, what could go wrong because of something I don't know?"
| Area | Heuristic |
|---|---|
| Identity | Kebab-case from tool name; honor existing package.json name |
| Scope | Narrowest scope that achieves the spec. Out-of-scope wins ties |
| Security | Env vars for secrets, never in stdout. Strictest reasonable approach |
| Verification | Integration tests for CLI behavior, unit tests for library code, both when crossing the boundary |
| Goal slicing | Single goal unless AC clearly spans unrelated subsystems |
| Language | JS default; TS when user mentions types or when adding to a TS project |
| Framework | commander for ≤10 commands; yargs for complex trees; respect existing choice |
If the probe found a new CLI (no existing project structure) and the user agrees, create missing project files. Templates are in references/scaffold-templates.md. Read that file when scaffolding.
Default scaffold (JavaScript):
bin/<tool-name>.js shebang + import
src/cli.js Commander setup, --json, --version, TTY detection
src/config.js loadConfig() from env vars via dotenv
src/errors.js AppError with code, message, suggestion, exitCode
src/commands/ one file per subcommand
tests/cli.test.js smoke tests
.env.example documented env var template
.gitignore node_modules, .env, dist/, *.db
package.json bin, type:module, engines, scripts, deps
AGENTS.md stack, conventions, canonical commands
CLAUDE.md behavioral snippet: when/how AI agents use each command
TypeScript additions (when TS is chosen):
tsconfig.json (strict, nodenext, es2022, outDir: dist)bin/ imports from dist/ instead of src/build and typecheck scripts added to package.jsontypescript added to devDependenciesfiles field set to ["bin", "dist"]Conditional additions:
src/db.js — when data storage round chose SQLite (better-sqlite3 singleton, WAL mode, foreign keys, initSchema())src/config.js — when config file round chose yessrc/auth.js — when OAuth round confirmed (OAuth Authorization Code flow with local redirect server)src/token-store.js — when OAuth round confirmed (token storage with optional AES-256-GCM encryption)src/commands/auth.js — when OAuth round confirmed (auth login, auth status, auth logout subcommands)Collision handling: Never overwrite without explicit user confirmation. Exceptions:
.gitignore — offer to merge missing linesAGENTS.md and CLAUDE.md — offer to append rather than overwriteGenerate three files at goals/<slug>/. Templates live in:
references/goal-template.md — full GOAL.md template (16 sections with CLI defaults and AI-agent patterns)references/verify-template.md — full VERIFY.md template (host-native verification: binary smoke, functional, exit code, integration checks)references/progress-template.md — initial PROGRESS.md skeletonRead these reference files when generating. Substitute placeholders with everything confirmed in Step 3 and observed in Step 1.
{{Tool Name}}, {{slug}}, {{AC ID}}) — replace with concrete values from Step 3 answers and Step 1 probe. Never leave one in.Not applicable. plus a one-line reason rather than deleting the section — /goal's completion audit expects the section to exist.AC-001.1. The audit table in GOAL.md and the evidence table in PROGRESS.md reference these IDs.--dry-run from the AI-agent patterns and note why.{{ outside of code-fenced template-instruction comments. If you find any, you missed something — fix it.Every command in the goal trio runs directly on the host. There is no container layer. The binary is invoked as node bin/<name>.js (or just <name> if the package is linked). Tests run with npm test. No routing decisions needed.
If the harness running /goal sandboxes shell access:
No Docker socket, no playwright browser, no container filesystem concerns.
Everything lives on the host:
tests/tests/fixtures/goals/<goal-dir>/checks/goals/<goal-dir>/test-artifacts/After writing the files, print:
Generated:
goals/<slug>/GOAL.md
goals/<slug>/VERIFY.md
goals/<slug>/PROGRESS.md
To run with Codex /goal:
/goal Complete goals/<slug>/GOAL.md. Use goals/<slug>/VERIFY.md as the verification contract. Update goals/<slug>/PROGRESS.md continuously. Treat uncertainty as incomplete.
How to run:
1. Open Codex inside this repo: codex
2. (Optional) /plan Read goals/<slug>/GOAL.md and VERIFY.md and propose an implementation plan.
3. Paste the /goal command above.
4. Review changes via `git diff` before committing.
If scaffold files were created in Step 4, list them above the goal trio under Scaffolded:.
If goals-plan.md was written in Step 2, append a Next slice: note.
| Scenario | Detection | Behavior difference |
|---|---|---|
| New CLI | No bin field in package.json, no src/cli.* | Full scaffold offered, all questions asked |
| Existing CLI | bin field exists, entry points found | No scaffold, questions focus on the new command/feature, probe informs existing conventions to respect |
For existing CLIs:
Stop and ask the user instead of guessing if:
bin/ already exists)./goal's job./goal's job./goal directly with a bug-fix-oriented goal.