Internal Tooling and CLI Design
Build internal CLI tools that developers actually want to use. Covers CLI architecture, argument parsing, progressive disclosure, output formatting, plugin systems, and the UX principles that make developer tools delightful.
Internal CLI tools are the interface between developers and the platform. A well-designed CLI saves hundreds of developer-hours per month. A poorly designed one creates frustration and workarounds. The difference is not the functionality — it is the developer experience.
CLI Architecture
platform [command] [subcommand] [flags]
platform service create --name order-service --template spring-boot
platform deploy staging order-service
platform logs order-service --since 1h --level error
platform db migrate --service order-service --dry-run
Command Structure
platform
├── service
│ ├── create Create a new service
│ ├── list List all services
│ ├── info Show service details
│ └── delete Delete a service
├── deploy
│ ├── staging Deploy to staging
│ ├── production Deploy to production
│ └── rollback Roll back last deploy
├── logs View service logs
├── db
│ ├── migrate Run database migrations
│ ├── connect Open database shell
│ └── backup Create database backup
└── config
├── set Set a config value
└── get Get a config value
Progressive Disclosure
Show simple usage first, reveal complexity as needed:
# Simple case: just works
$ platform service create
? Service name: order-service
? Template: spring-boot
? Team: order-team
✅ Service created: order-service
# Advanced case: flags for automation
$ platform service create \
--name order-service \
--template spring-boot \
--team order-team \
--database postgres \
--monitoring datadog \
--no-input
Output Design
Human-Friendly (Default)
$ platform service info order-service
Name: order-service
Owner: Order Team
Status: ✅ Healthy
Replicas: 3/3 running
Version: v2.4.1 (deployed 2h ago)
CPU: 23% avg
Memory: 512 Mi / 1 Gi
Recent Deploys:
DATE VERSION STATUS DURATION
2026-03-04 v2.4.1 ✅ 3m 42s
2026-03-03 v2.4.0 ✅ 4m 11s
2026-03-01 v2.3.9 ⚠️ 8m 23s (canary rollback)
Machine-Friendly (—json flag)
$ platform service info order-service --json
{
"name": "order-service",
"owner": "order-team",
"status": "healthy",
"replicas": {"running": 3, "desired": 3},
"version": "v2.4.1",
"cpu_percent": 23,
"memory_bytes": 536870912
}
Error Handling
# BAD: Cryptic error
$ platform deploy production order-service
Error: EPERM 403
# GOOD: Actionable error with context
$ platform deploy production order-service
❌ Deploy failed: Approval required for production deploys
Your deploy requires approval from a team lead.
Request URL: https://portal.internal/deploys/d-12345
Alternatively, deploy to staging first:
platform deploy staging order-service
Help System
$ platform --help
Garnet Platform CLI v3.2.0
USAGE
platform <command> [flags]
COMMANDS
service Manage services
deploy Deploy services
logs View service logs
db Database operations
config Configuration management
FLAGS
--help Show help
--json Output as JSON
--verbose Verbose output
--version Show version
EXAMPLES
$ platform service create
$ platform deploy staging order-service
$ platform logs order-service --since 1h
DOCUMENTATION
https://wiki.internal/platform-cli
Anti-Patterns
| Anti-Pattern | Consequence | Fix |
|---|---|---|
| No —help on commands | Developers read source code | Help text on every command |
| Only JSON output | Humans cannot read it | Human-friendly default + —json flag |
| Silent failures | Developer thinks it worked | Always output result or error |
| No confirmation for destructive actions | Accidental deletions | Prompt for confirmation, add —force flag |
| Require all flags (no interactive mode) | High barrier for new users | Interactive prompts when flags omitted |
A great CLI feels like a conversation with the platform. It anticipates what you need, tells you when something goes wrong, and helps you fix it.