
cli-building
Build command-line interfaces with async-first design, composable commands, and proper output formatting. Use when creating CLI tools, commands, or interactive terminal applications.
Build command-line interfaces with async-first design, composable commands, and proper output formatting. Use when creating CLI tools, commands, or interactive terminal applications.
CLI Building
Guidelines for building command-line interfaces with modern patterns and best practices.
When to Use
- Creating new CLI tools or commands
- Building interactive terminal applications
- Adding commands to existing projects
- Implementing command-line interfaces
- Working with CLI frameworks
Core Principles
- Async-first: All I/O operations should be async/await, avoid blocking operations
- Composable commands: Commands should be modular and reusable, use command composition
- Strategy pattern: Use strategy pattern for branching workflows or task-based commands
- Output formatting: Proper formatting with unicode symbols and color support
Framework Selection
TypeScript/JavaScript
stricli (@bloomberg/stricli, recommended for modern async-first CLIs):
- Built for async/await from ground up
- Type-safe command definitions with full type inference
- Lazy loading for startup performance
- Zero dependencies
oclif (alternative):
- Mature framework with extensive features
- Plugin system
- Good for complex CLIs
Python
cyclopts (recommended for async-first):
- Modern async-first CLI framework
- Type-safe with excellent async support
- Clean API design
typer (when fully async support available):
- Based on Python type hints
- Clean and intuitive
- Good for simple to medium complexity CLIs
Command Architecture
Composable Commands
Design commands as reusable modules:
- Shared command utilities
- Command middleware
- Reusable command modules
- Command composition patterns
Strategy Pattern
Use strategy pattern for:
- Workflow branching
- Task-based commands
- Dynamic command routing
- Conditional command execution
Output Formatting
- No emojis: Do not use emojis unless explicitly directed
- Unicode symbols: Use unicode symbols (✓, ✗, →, ⚠) for status indicators
- Color support: Use color libraries, never hardcoded ANSI codes
- NO_COLOR: Always respect
NO_COLORenvironment variable - Formatting: Use formatting for better readability (bold, dim, etc.)
Async Patterns
Async-First Design
All I/O should be async:
- File operations: use async file APIs
- Network requests: use async HTTP clients
- Process execution: use async process APIs
- Database operations: use async database clients
Error Handling
Handle async errors properly:
- Use try/catch with await
- Handle promise rejections
- Provide clear error messages
- Exit with appropriate codes
Command Structure
Basic Command
// stricli example
import { createCli } from '@bloomberg/stricli';
async function myCommand() {
// Async implementation
}
const cli = createCli({
name: 'my-cli',
commands: {
'my-command': myCommand
}
});
cli.run();
# cyclopts example
from cyclopts import App
app = App()
@app.default
async def my_command():
# Async implementation
pass
if __name__ == '__main__':
app()
Best Practices
- Async by default: All operations should be async
- Composable design: Build reusable command modules
- Strategy pattern: Use for workflow branching
- Proper formatting: Unicode symbols and color with NO_COLOR support
- Error handling: Clear error messages and exit codes
- Type safety: Use TypeScript types or Python type hints
- Testing: Test commands in isolation
References
For detailed guidance, see:
references/async-patterns.md- Async/await best practicesreferences/composable-commands.md- Command composition patternsreferences/strategy-pattern.md- Strategy pattern for workflowsreferences/output-formatting.md- Output formatting guidelinesreferences/frameworks.md- Framework comparisons and selection
You Might Also Like
Related Skills

coding-agent
Run Codex CLI, Claude Code, OpenCode, or Pi Coding Agent via background process for programmatic control.
openclaw
add-uint-support
Add unsigned integer (uint) type support to PyTorch operators by updating AT_DISPATCH macros. Use when adding support for uint16, uint32, uint64 types to operators, kernels, or when user mentions enabling unsigned types, barebones unsigned types, or uint support.
pytorch
at-dispatch-v2
Convert PyTorch AT_DISPATCH macros to AT_DISPATCH_V2 format in ATen C++ code. Use when porting AT_DISPATCH_ALL_TYPES_AND*, AT_DISPATCH_FLOATING_TYPES*, or other dispatch macros to the new v2 API. For ATen kernel files, CUDA kernels, and native operator implementations.
pytorch
skill-writer
Guide users through creating Agent Skills for Claude Code. Use when the user wants to create, write, author, or design a new Skill, or needs help with SKILL.md files, frontmatter, or skill structure.
pytorch
implementing-jsc-classes-cpp
Implements JavaScript classes in C++ using JavaScriptCore. Use when creating new JS classes with C++ bindings, prototypes, or constructors.
oven-sh
implementing-jsc-classes-zig
Creates JavaScript classes using Bun's Zig bindings generator (.classes.ts). Use when implementing new JS APIs in Zig with JSC integration.
oven-sh