Skip to content
Agentmart
Submit a tool
This entry duplicates cli-design, which is the one we list in search.

cli-design

Unix-composable CLI design patterns.

Skill by Yabuku-xD

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/yabuku-xd-cli-design

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Unix-composable CLI design patterns. Use when building CLI tools, designing command trees, implementing output layers, or testing CLI behavior. Covers stream separation (stdout/stderr), format flags (--json/--plain), exit codes, TTY detection, composability, and error design. Language-agnostic principles; TypeScript implementation patterns in resources/. For API design (REST, HTTP), see api-design.

Use cases: design, backend, testing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions: not checked yet.

What's inside

Skill name
cli-design
Description
Unix-composable CLI design patterns. Use when building CLI tools, designing command trees, implementing output layers, or testing CLI behavior. Covers stream separation (stdout/stderr), format flags (--json/--plain), exit codes, TTY detection, composability, and error design. Language-agnostic principles; TypeScript implementation patterns in resources/. For API design (REST, HTTP), see api-design.
License
MIT
Instructions
500 lines in SKILL.md · view on GitHub

Before installing

  • Instructions call the network
  • Instructions read files in your home folder (~/.ssh, ~/.aws…)

Files (1)

  • SKILL.md

SKILL.md (first lines)

# CLI Design: Unix-Composable Command-Line Interfaces

This skill covers **language-agnostic** CLI design principles. The rules about stream separation, exit codes, format flags, and composability apply regardless of implementation language.

This bundle adapts the CC BY-SA 4.0 [Command Line Interface Guidelines](https://clig.dev/).
Pinned provenance, modification notes, and license scope are recorded in
[`resources/source-notes.md`](resources/source-notes.md) and [`LICENSE`](LICENSE).

For API contract stability and Hyrum's Law, see the `api-design` skill. For config, env vars, and graceful shutdown, see the `twelve-factor` skill.

**TypeScript implementation patterns** are in the `resources/` directory. Load them on demand when building a CLI in TypeScript:

| Resource | Load when... |
|----------|-------------|
| `output-architecture.md` | Implementing Result types, entry point wiring, formatters, logger, JSON envelope schemas |
| `testing-cli.md` | Writing Vitest tests for CLI behavior (streams, exit codes, pipes, contract tests) |
| `stream-contracts.md` | Understanding Node.js buffering, NDJSON, signal handling, crash-only design |
| `composability.md` | Designing or testing pipe behavior — worked shell examples (jq filtering, NDJSON streaming, stdin, chaining, `--fields`, parallel `xargs`) |

---

## When to Use

- Building any command-line tool (any language)
- Designing command tree, flags, and I/O contracts
- Implementing the output layer (format detection, stream routing)
- Testing CLI behavior (stdout/stderr separation, exit codes)
- Reviewing a CLI for Unix composability

---

## Core Principle

**stdout is for DATA only — the product the user asked for.**
**stderr is for EVERYTHING ELSE — diagnostics, progress, spinners, warnings, errors.**

This separation is what makes `mycli --json | jq ...` work. One spinner character on stdout breaks every downstream pipe.

> "Whatever software you're building, you can be absolutely certain that people will use it in ways you didn't anticipate. Your software will become a part in a larger system — your only choice is over whether it will be a well-behaved part." — clig.dev

---

## The Unix Stream Contract

| Content | Stream | Why |
|---------|--------|-----|
| Primary output (data, results, JSON) | stdout | Pipeable, buffered for throughput |
| Progress bars, spinners, status | stderr | Not data — must not corrupt pipes |
| Warnings, errors, diagnostics | stderr | Visible to user even when stdout is piped |
| Debug/verbose output | stderr | Diagnostic, never data |

**Stream behavior:**

- Check stdout and stderr independently; stdout being piped does not mean stderr is piped
- Do not assume C stdio's line/block/unbuffered rules describe every language runtime
- In Node.js, sync/async process-stream behavior varies by operating system and destination; always respect `.write()` backpressure for high-volume output

When stdout is piped, the user doesn't want your status messages in their data. All non-data output must go to stderr.

For a deep dive on buffering behavior and performance implications, see `resources/stream-contracts.md`.

---

## Keep Handlers Pure

The practical rule: **functions that do the work should return data, not write to stdout.** The CLI entry point handles all I/O.

```
Entry point (CLI main)              Your logic (handlers)
─────────────────────               ─────────────────────
parse args                          (input) → structured result
detect format (json/plain/human)    no printing to stdout
call handler                        no writing to stderr
format the result                   no calling exit
write to correct stream             just returns data
set exit code
```

This isn't an architecture mandate — it's just clean function design. The benefits are concrete:

- **Testable without subprocess spawning** — call the handler, assert on the returned value
- **Format flexibility for free** — same data renders as JSON, plain text, or coloured tables by swapping one function
- **Reusable** — the same handler works from a CLI, MCP server, HTTP API, or programmatic import

For simple CLIs where the "handler" is just calling a library, this separation already exists naturally — your library returns data, your CLI formats it. No extra layers needed.

If your project uses hexagonal architecture, the mapping is direct: the CLI entry point is a **driving adapter**, and the handler is a **use case** that returns a result through a port. See the `hexagonal-architecture` skill — the patterns reinforce each other, but hex arch is not required to benefit from keeping handlers pure.

For TypeScript implementation patterns (Result types, entry point wiring, formatters, logger interfaces), see `resources/output-architecture.md`.

---

## Selecting a TypeScript Stack

Prefer the command and prompt libraries the repository already owns when they can satisfy the contracts in this skill. For a new material dependency, inspect current versions and project constraints and use `evaluate-existing-solutions`; do not select from remembered popularity or stale package characteristics.

Stricli can fit typed, injected command handlers, and `@clack/prompts` can fit optional TTY-gated interactivity. Treat them as candidates, not defaults. Compare them with the existing stack and alternatives on handler testability, type safety, startup cost measured in the target runtime, maintenance, dependency weight, non-interactive behavior, and migration cost.

---

## Format Flag Contract

Three-tier output hierarchy:

### Default: Human-Readable

- Colors, tables, formatted text
- Progress bars and spinners on **stderr**
- Output tailored for terminal width
- May change between versions — this is **not** a contract

### `--plain`: Grep/Awk-Friendly

- One record per line, no formatting, no colors
- Stable between minor versions — this **is** a contract
- Flat table rows, no borders, no grouped sections
- Enables: `mycli list --plain | grep error | wc -l`

> "Encourage your users to use `--plain` or `--json` in scripts to keep output stable." — clig.dev

From Yabuku-xD/omfx, MIT.

More from Yabuku-xD/omfx

Signals

Stars
0
Forks
0
Open issues
0
Last commit (this folder)
Aug 24, 2026 (2 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

Same skill elsewhere

Copies of this SKILL.md published by others; search shows only one of them.

More from Yabuku-xD

Cite this page

cli-design skill. Agent Mart. https://agentmart.dev/skills/yabuku-xd-cli-design (last updated 2026-10-24)