This shows a refined YAML format for CLI specifications with improvements:
- Args use plain names without angle brackets
- Completions use YAML's multiline string syntax with
|
name "mycli"
bin "mycli"
version "1.0.0"
about "A simple CLI tool"
flag "-v --verbose" help="Enable verbose output" global=#true count=#true
flag "-q --quiet" help="Suppress output" global=#true
cmd "server" help="Manage the server" {
cmd "start" help="Start the server" {
flag "-p --port <port>" help="Port to listen on" default="8080"
flag "-h --host <host>" help="Host to bind to" default="localhost"
flag "-d --daemon" help="Run in background"
}
cmd "stop" help="Stop the server" {
flag "-f --force" help="Force stop"
}
cmd "config" help="Manage server configuration" {
cmd "set" help="Set a server config value" {
arg "<key>" help="Configuration key"
arg "<value>" help="Configuration value"
flag "--restart" help="Restart server after change"
}
cmd "get" help="Get a server config value" {
arg "<key>" help="Configuration key"
flag "--json" help="Output as JSON"
}
cmd "list" help="List all server config values" {
flag "--filter <pattern>" help="Filter by pattern"
}
}
}
cmd "config" help="Manage global configuration" {
cmd "set" help="Set a config value" {
arg "<key>" help="Configuration key"
arg "<value>" help="Configuration value"
}
cmd "get" help="Get a config value" {
arg "<key>" help="Configuration key"
}
}
complete "key" run="echo 'host\nport\ndebug'"name: mycli
bin: mycli
version: 1.0.0
about: A simple CLI tool
flags:
"-v --verbose":
help: Enable verbose output
global: true
count: true
"-q --quiet":
help: Suppress output
global: true
commands:
server:
help: Manage the server
subcommands:
start:
help: Start the server
flags:
"-p --port <port>":
help: Port to listen on
default: "8080"
"-h --host <host>":
help: Host to bind to
default: localhost
"-d --daemon":
help: Run in background
stop:
help: Stop the server
flags:
"-f --force":
help: Force stop
config:
help: Manage server configuration
subcommands:
set:
help: Set a server config value
args:
key:
help: Configuration key
value:
help: Configuration value
flags:
"--restart":
help: Restart server after change
get:
help: Get a server config value
args:
key:
help: Configuration key
flags:
"--json":
help: Output as JSON
list:
help: List all server config values
flags:
"--filter <pattern>":
help: Filter by pattern
config:
help: Manage global configuration
subcommands:
set:
help: Set a config value
args:
key:
help: Configuration key
value:
help: Configuration value
get:
help: Get a config value
args:
key:
help: Configuration key
completions:
key:
run: |
echo 'host
port
debug'Before:
args:
"<key>":
help: Configuration keyAfter:
args:
key:
help: Configuration keyThis is cleaner since:
- Angle brackets are CLI convention for documentation, not actual identifiers
- The arg name is now a valid YAML key without special characters
- Easier to type and read
Before:
completions:
key:
run: echo 'host\nport\ndebug'After:
completions:
key:
run: |
echo 'host
port
debug'Benefits:
- More readable for multi-line commands
- No need to escape newlines with
\n - Natural formatting for shell scripts
- Can easily add more complex completion logic
For more complex completions:
completions:
plugin:
run: |
mise plugins --core
mise plugins --user
task:
run: |
if [ -f Taskfile.yml ]; then
task --list-all | awk '{print $2}'
fiOr for long help text:
commands:
deploy:
help: |
Deploy the application to production.
This will build the app, run tests, and deploy to
the configured production environment.
args:
environment:
help: Target environment (staging/production)| Feature | KDL | YAML (Improved) |
|---|---|---|
| Lines | 41 | 71 |
| Arg syntax | arg "<key>" |
key: |
| Flag syntax | flag "-v --verbose" |
"-v --verbose": |
| Completions | run="echo..." with \n |
run: | multiline |
| Nesting | Braces { } |
Indentation |
| Comments | C-style // or # |
# |
Both formats are now quite readable, with KDL being more compact and YAML being more familiar to most developers.