A squat turret carrying three blocks of three sizes feeds a straight grooved rail through four open pawl gates; an indigo channel runs down the rail to a finished block beside a ring terminal, the far half of the rail drawn as ghosted outlines.
Development

CreateCLI

Generates production-ready TypeScript CLIs via a 3-tier template system (manual arg parsing, Commander.js, oclif), each shipping full implementation, docs, package.json, strict config, JSON output, and exit-code compliance

03
Workflows
01
Tool
02
References
07
Triggers

The Problem

Every time you need a CLI for an API or service, you start with a bash script, realize it needs error handling, then real help text, then type safety, then documentation — and end up rewriting the whole thing from scratch. A generic AI will generate something that compiles once but skips exit codes, ships `any` types, has no README, and breaks when you pipe it to jq.

How This Skill Approaches It

CreateCLI uses a three-tier template system to pick the right level of complexity upfront. Tier 1 is the llcli pattern — manual argument parsing, zero dependencies, Bun and TypeScript, around 300-400 lines, ships for 80% of cases. Tier 2 adds Commander.js for tools that need subcommands and nested options. Tier 3 is oclif as a reference for enterprise scale. Every generated CLI clears four hard gates before it ships: zero TypeScript errors in strict mode, correct exit codes (0 success, 1 error), a thorough --help, and JSON output that pipes cleanly to jq. The full package includes a README, a QUICKSTART, package.json, and tsconfig — nothing left to fill in.

Not for LifeOS skill scaffolding (use CreateSkill)

In Action

What you say to your DA, and what the CreateCLI skill actually does.

  • You say "create a CLI for the GitHub API that can list repos, create issues, and search code"
    Runs CreateCli workflow at Tier 1, generates a ~350-line TypeScript file with full type safety and error handling, package.json configured for Bun, .env.example for GITHUB_TOKEN, README explaining each command, and QUICKSTART with the most common patterns — all gates verified before handing it over.
  • You say "add a bulk-delete command to my existing CLI"
    Runs the AddCommand workflow, reads the existing CLI to determine tier, adds the new command following the same argument-parsing pattern already in place, updates --help text, verifies TypeScript still compiles clean.
  • You say "this CLI is getting complex, it needs subcommands now"
    Runs UpgradeTier, migrates the Tier 1 manual-parsing implementation to Commander.js while keeping all existing commands working, updates README to reflect the new subcommand structure.

Inside the Skill

The thinking, frameworks, and architecture that distinguish this skill from a generic version of the same task.

Ideal State

  • Every CLI the skill creates or changes ships whole: typed source, README.md and QUICKSTART.md, a Bun package.json, a strict tsconfig.json, an .env.example, and --help that lists every command with real examples.
  • Output follows one contract across intents: JSON to stdout, errors with context to stderr, exit code 0 on success and 1 on error, and strict tsc clean before the work is reported done.
  • A CLI for a public-facing app meets the agent-first contract (OPERATIONAL_PREFERENCES § Deployment): a browser device login that mints a scoped, expiring API key; --json stdout and fixed exit codes; a help --json catalog; RateLimit headers with per-key and per-IP limits; /docs/cli rendered from the CLI's own catalog; and a self-hosted, SHA-checked install. Intents/CreateCli.md § Ideal State itemizes it, and Config.md names the reference implementation to match when one is configured. Where that contract and the output contract above differ, the agent-first contract governs.
  • The tier fits the need: Tier 1 unless a Tier 2 indicator holds, oclif never generated, and a CLI moves up a tier only when it has outgrown the one it is on.
  • A change to an existing CLI keeps every command it already had working.

Intent Routing

Intent Trigger File
CreateCli "create CLI", "build a CLI", "wrap this API in a command-line tool" Intents/CreateCli.md
AddCommand "add a command to " Intents/AddCommand.md
UpgradeTier "upgrade tier", "move this CLI to Commander" Intents/UpgradeTier.md
File Read when
FrameworkComparison.md choosing or justifying a framework: Manual vs Commander vs oclif, plus cleye, citty, Yargs and Ink
Tools/CheckCli.ts proving a CLI meets the output contract: strict tsc, --help names every command, --version, unknown command exits 1, --json-args stdout parses as JSON
Setup.md first-time setup: the optional Reference CLI: key in Config.md

Data & Config

User customizations live at <configRoot>/LIFEOS/USER/CUSTOMIZATIONS/SKILLS/CreateCLI/ (configRoot is $CLAUDE_CONFIG_DIR when set, else ~/.claude). When that directory exists, its PREFERENCES.md, configurations and resources apply and override the defaults here; when it is absent, the defaults stand.

Config.md there holds one optional key, Reference CLI:, naming an existing CLI that already meets the public-app agent-first contract (its path and the criteria that define it). When it is set, a new public-app CLI matches that CLI's command catalog, device login, exit codes and install script; when it is unset, the contract as written here governs. First-time setup: Setup.md.

Gotchas

  • Bun, never npm or npx, with no exceptions: the system prompt's tech stack names bun as the package manager.
  • TypeScript only, never Python. Every CLI this skill generates is TypeScript on Bun, with no Python or other scripting-language helpers. The install's broader language preferences (for example, which compiled language to use when a binary is required) live in the USER PREFERENCES.md (§ Data & Config).
  • Env loading has one correct shape. Read secrets from the canonical ~/.claude/.env, never ${LIFEOS_DIR}/.env (the ~/.claude/LIFEOS/.env path public issue #1490 found dead) or $LIFEOS_CONFIG_DIR/.env, and slice past the first = instead of .split('=')[1], which truncates values that contain '=' such as padded base64 keys. Intents/CreateCli.md § Output format carries the correct loadConfig().

Examples

Example 1: API Client CLI (Tier 1)

User Request: "Create a CLI for the GitHub API that can list repos, create issues, and search code"

Generated Structure:

~/.claude/LIFEOS/TOOLS/ghcli/  # generated example, not shipped
├── ghcli.ts              # 350 lines, complete implementation
├── package.json          # Bun + TypeScript
├── tsconfig.json         # Strict mode
├── .env.example          # GITHUB_TOKEN=your_token
├── README.md             # Full documentation
└── QUICKSTART.md         # Common use cases

Usage:

ghcli repos --user exampleuser
ghcli create-issue --repo myrepo --title "Bug fix"
ghcli search "typescript CLI"
ghcli --help

Example 2: Add a command

User: "Add a search command to ghcli"
→ AddCommand intent
→ `ghcli search <query>` runs and exits 0, appears in --help and the README, and every existing command still works

Example 3: Outgrown Tier 1

User: "notioncli has 18 commands in four groups now, move it to Commander"
→ UpgradeTier intent
→ A Commander.js CLI at 2.0.0 with every command and the help examples intact, and a Breaking Changes note in the README that names what changed for callers

Workflows & Routing · 3

Each workflow is one job the skill runs. The trigger phrases route your request to the right one — this is the skill's routing table.

  1. 01
    CreateCli Intents/CreateCli.md

    create CLI, build a CLI, wrap this API in a command-line tool

  2. 02
    AddCommand Intents/AddCommand.md

    add a command to <cli>

  3. 03
    UpgradeTier Intents/UpgradeTier.md

    upgrade tier, move this CLI to Commander

Tools · 1

Deterministic executables the workflows call — the code that does the real work, not prompt scaffolding.

  • CheckCli.ts

How to Invoke

Say any of these to your DA and LifeOS activates the CreateCLI skill automatically:

  • "create CLI"
  • "build CLI"
  • "command-line tool"
  • "wrap API"
  • "add command"
  • "upgrade tier"
  • "TypeScript CLI"

Or invoke explicitly:

Skill("CreateCLI")

References · 2

Auxiliary files the skill loads at runtime — frameworks, guides, configs.

  • FrameworkComparison
  • Setup

Want LifeOS to do this for you?

Install LifeOS on your machine — your DA gets the CreateCLI skill plus 96 others, all hooked into one Life OS.