CLI Guidelines - Designing Great Command-Line Interfaces#
CLI Guidelines
Comprehensive guide for creating user-friendly command-line tools:
Core Design Principles:#
Human-First Design: #
Helpful by Default : Show useful information without being asked
Fail Gracefully : Clear error messages with actionable suggestions
Consistent Behavior : Follow established conventions
Progressive Disclosure : Start simple, allow complexity when needed
Error Handling Best Practices: #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Bad error message
error: invalid input
# Good error message
error: expected a number, got "hello"
Try: mycommand --count 5
# Even better with suggestions
error: unknown flag '--hep'
Did you mean '--help' ?
# Excellent with context
error: cannot connect to database
database: postgresql://localhost:5432/myapp
reason: connection refused
help: is PostgreSQL running? try 'brew services start postgresql'
Guidelines by Category:#
Arguments and Flags: #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Prefer flags over positional arguments for clarity
# Good
deploy --environment staging --version 1.2.3
# Less clear
deploy staging 1.2.3
# Support both short and long forms
grep -r --recursive # Both work
grep -R --recursive # Consistent
# Use consistent flag naming
--verbose / -v # Standard conventions
--quiet / -q
--help / -h
--version / -V ( capital for version)
Output and Feedback: #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Show progress for long operations
Downloading... [ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ] 100% ( 15.2 MB/s)
# Provide machine-readable output options
mycommand --format json
mycommand --format csv
mycommand --format table # Human-readable default
# Color coding (but respect NO_COLOR)
โ Success: Database backup completed
โ Warning: Low disk space
โ Error: Connection failed
# Quiet modes for scripts
mycommand --quiet # No output on success
mycommand --silent # Minimal output
Configuration and Environment: #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Configuration hierarchy (most to least specific)
1. Command-line flags
2. Environment variables
3. Configuration files
4. Defaults
# Environment variable naming
MYAPP_DATABASE_URL
MYAPP_LOG_LEVEL
MYAPP_CONFIG_PATH
# Config file locations (XDG spec)
~/.config/myapp/config.yaml # Primary
~/.myapp.yaml # Fallback
/etc/myapp/config.yaml # System-wide
Advanced Features:#
Interactive Elements: #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Example: Interactive confirmation
import click
@click.command ()
@click.option ( '--force' , is_flag = True , help = 'Skip confirmation' )
def delete_database ( force ):
if not force :
click . confirm ( 'This will delete all data. Continue?' , abort = True )
with click . progressbar ( tables , label = 'Dropping tables' ) as bar :
for table in bar :
drop_table ( table )
click . secho ( 'โ Database deleted' , fg = 'green' )
# Tab completion support
@click.command ()
@click.argument ( 'environment' , type = click . Choice ([ 'dev' , 'staging' , 'prod' ]))
def deploy ( environment ):
"""Deploy to specified environment."""
pass
Documentation Integration: #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Multi-level help
mycommand --help # Overview
mycommand deploy --help # Subcommand help
mycommand --help-advanced # Advanced options
# Examples in help text
Usage: git-deploy [ OPTIONS] ENVIRONMENT
Deploy application to specified environment.
Examples:
git-deploy staging
git-deploy prod --version 1.2.3
git-deploy dev --force --no-backup
Options:
--version TEXT Specific version to deploy
--force Skip safety checks
--no-backup Skip database backup
--help Show this message and exit.
Parinfer - Revolutionary Lisp Editing#
Parinfer - simpler Lisp editing
Innovative approach to editing Lisp code that infers parentheses from indentation:
The Parentheses Problem:#
Traditional Lisp Editing Challenges: #
1
2
3
4
5
6
7
8
9
10
11
;; Traditional Lisp - parentheses can be overwhelming
( defn factorial [n]
( if ( <= n 1 )
1
( * n ( factorial ( - n 1 )))))
;; Easy to have mismatched parens
( defn broken [x]
( if ( > x 0 )
( inc x )
( dec x )) ; Missing closing paren somewhere?
Parinfer Modes:#
Indent Mode: #
Indentation drives structure : Parentheses inferred from indentation
Writing-focused : Natural for entering new code
Familiar : Works like Python or other indentation-based languages
1
2
3
4
5
6
7
8
9
10
11
;; Type this (without worrying about parens):
defn factorial [n]
if ( <= n 1 )
1
* n ( factorial ( - n 1 ))
;; Parinfer automatically adds parens:
( defn factorial [n]
( if ( <= n 1 )
1
( * n ( factorial ( - n 1 )))))
Paren Mode: #
Parentheses drive structure : Indentation adjusted to match parens
Editing-focused : Good for modifying existing code
Traditional : Familiar to experienced Lisp programmers
1
2
3
4
5
6
7
8
9
10
11
;; Move a closing paren:
( defn example [x]
( if ( > x 0 )
( inc x ))
( dec x ))
;; Parinfer adjusts indentation:
( defn example [x]
( if ( > x 0 )
( inc x )
( dec x )))
Smart Features:#
Cursor-Based Inference: #
1
2
3
4
5
6
7
8
;; Cursor position affects paren inference
;; Cursor at end of line:
( map inc [1 2 3|])
;; Result: (map inc [1 2 3])
;; Cursor in middle:
(map inc [1 2| 3] )
;; Different grouping possible based on context
Tab Stops: #
1
2
3
4
5
6
7
8
9
;; Smart tab stops for alignment
( let [x 1
y 2 ; Aligned automatically
long 3] )
;; Function arguments align naturally
( function arg1
arg2 ; Aligned with first arg
arg3 )
Editor Integration:#
Available Implementations: #
Atom : Lisp editing with Parinfer integration
VS Code : Parinfer extension for modern editor
Vim/Neovim : Multiple Parinfer plugins available
Emacs : Parinfer packages for the classic Lisp editor
Sublime Text : Community-maintained Parinfer support
Configuration Example (VS Code): #
1
2
3
4
5
6
{
"parinfer.defaultMode" : "indent" ,
"parinfer.forceBalance" : true ,
"parinfer.previewCursorScope" : true ,
"parinfer.dimParens" : true
}
Benefits for Lisp Learning:#
Reduced Cognitive Load: #
Focus on Logic : Less mental energy spent on parentheses
Visual Structure : Indentation makes nesting obvious
Error Prevention : Automatic balancing prevents common mistakes
Gentle Learning Curve : Familiar indentation-based editing
Before/After Comparison: #
1
2
3
4
5
6
7
8
9
10
11
12
13
;; Without Parinfer - manual paren management
( defn process-items [items]
( map ( fn [item]
( if ( valid? item )
( transform item )
( default-value ))) items ))
;; With Parinfer - focus on structure
defn process-items [items]
map ( fn [item]
if ( valid? item )
transform item
default-value ) items
Mosh - Mobile Shell#
Mosh: the mobile shell
Robust, responsive terminal application that handles intermittent connectivity:
Problems with Traditional SSH:#
Common SSH Issues: #
Connection Drops : WiFi disconnections kill sessions
Lag : Every keystroke waits for round-trip
IP Changes : Moving between networks breaks connections
Firewall Issues : NAT and firewall complications
Mosh Solutions:#
Key Technologies: #
S
-
-
-
P
-
-
-
t
r
a
C
O
W
e
S
U
R
t
l
n
o
d
h
n
e
e
i
l
r
i
o
d
d
e
y
k
c
w
e
u
S
n
s
t
s
r
c
y
t
s
i
l
e
n
e
v
t
i
s
c
a
n
v
e
y
n
h
n
d
e
p
e
p
r
d
s
r
E
e
s
e
o
c
d
r
n
s
d
U
h
p
c
i
e
i
D
o
c
r
e
z
r
f
P
:
h
e
i
a
v
f
a
d
v
t
e
e
f
r
i
e
i
r
r
o
a
c
d
o
e
r
c
t
n
m
n
t
i
l
a
c
b
e
o
a
P
i
e
e
r
n
t
r
n
s
t
s
s
e
o
t
,
t
n
t
a
e
i
u
c
o
i
n
r
m
n
y
c
n
o
m
t
o
t
h
e
i
d
l
s
a
d
l
r
y
f
n
i
a
(
n
u
d
a
c
m
S
c
l
l
t
o
a
S
h
l
i
e
n
t
P
r
n
l
f
i
)
o
s
g
y
i
c
:
n
c
r
a
i
r
o
m
l
z
e
f
e
l
e
e
d
y
d
n
p
a
b
t
u
c
y
e
p
k
r
d
e
s
m
a
t
e
i
t
r
n
e
l
v
a
s
o
e
l
s
r
s
s
t
a
t
e
Roaming Support: #
1
2
3
4
5
6
7
# Traditional SSH breaks when IP changes
ssh user@server
# WiFi โ 4G transition = broken connection
# Mosh maintains connection across IP changes
mosh user@server
# WiFi โ 4G โ different WiFi = seamless transition
Technical Architecture:#
Connection Process: #
1
2
3
4
5
6
7
8
# 1. Mosh client connects via SSH
mosh user@server
# 2. SSH launches mosh-server on remote host
# 3. mosh-server chooses UDP port and prints connection info
# 4. SSH connection terminates
# 5. Client connects directly via UDP
# 6. State synchronization begins
State Synchronization: #
C
S
U
C
S
N
S
l
e
s
l
e
e
e
i
r
e
i
r
t
r
e
v
r
e
v
w
v
n
e
n
e
o
e
t
r
t
t
r
r
r
y
k
S
S
p
S
S
S
t
t
e
t
t
p
t
a
a
s
a
a
a
a
t
t
:
t
t
c
t
e
e
e
e
k
e
:
:
:
:
e
:
t
"
"
"
"
"
a
"
h
h
h
h
h
r
h
e
e
e
e
e
r
e
l
l
l
l
l
i
l
l
l
l
l
l
v
l
o
o
o
o
o
e
o
s
w
w
w
w
w
:
w
o
o
o
o
o
o
r
r
r
r
r
r
l
l
l
l
l
l
d
d
d
d
d
d
"
"
!
!
"
!
"
"
"
(
(
(
i
u
s
m
n
y
m
t
n
e
i
c
d
l
h
i
r
a
n
o
t
e
n
e
t
i
l
w
z
y
o
e
r
d
s
k
)
h
o
p
w
a
n
c
)
k
e
t
a
r
r
i
v
e
s
)
Advanced Features:#
Predictive Text Display: #
#
$
#
$
#
$
U
g
O
g
I
g
s
i
n
i
f
i
e
t
c
t
t
r
e
s
c
c
e
c
t
o
s
o
r
o
y
m
e
m
v
m
p
m
r
m
e
m
e
i
v
i
r
i
s
t
e
t
t
r
d
q
-
-
i
-
u
m
c
m
f
m
i
o
f
c
"
n
"
e
"
k
f
f
f
r
f
l
i
i
i
s
i
y
x
r
x
:
x
:
m
b
s
b
b
u
(
:
u
(
u
g
u
g
n
g
"
n
"
o
"
d
r
(
e
m
s
r
a
e
l
l
r
i
v
n
d
e
e
i
r
d
s
p
h
=
l
a
a
d
p
y
r
d
e
=
i
d
f
i
c
f
c
o
e
t
n
r
e
f
e
d
i
n
)
r
t
m
e
r
d
e
)
s
p
o
n
s
e
)
Firewall and NAT Traversal: #
1
2
3
4
5
6
7
8
# Mosh uses UDP port range (default 60000-61000)
# Configure firewall to allow:
iptables -A INPUT -p udp --dport 60000:61000 -j ACCEPT
# Or specify port range:
mosh --server= "mosh-server new -p 2222" user@server
# Works through NAT (unlike SSH X11 forwarding)
Installation and Usage:#
Installation: #
1
2
3
4
5
6
7
8
9
10
11
# Ubuntu/Debian (both client and server needed)
sudo apt install mosh
# macOS
brew install mosh
# CentOS/RHEL
sudo yum install mosh
# Client connects to server (server auto-installed via SSH)
mosh user@hostname
Advanced Options: #
1
2
3
4
5
6
7
8
9
10
# Specify SSH port
mosh --ssh= "ssh -p 2222" user@server
# Set prediction mode
mosh --predict= always user@server # Always predict
mosh --predict= never user@server # Never predict
mosh --predict= adaptive user@server # Default
# Specify colors (for 256-color support)
mosh --colors= 256 user@server
ripgrep-all (rga) - Search Inside Documents#
rga: ripgrep, but also search in PDFs, E-Books, Office documents, zip, tar.gz, etc.
Extended version of ripgrep that searches inside various file formats:
Supported File Types:#
1
2
3
4
5
6
7
# Search inside compressed archives
rga "search term" archive.zip
rga "function name" backup.tar.gz
rga "config setting" bundle.tar.xz
# Nested archives supported
rga "password" archive.zip/nested.tar.gz/document.pdf
1
2
3
4
5
6
7
8
9
10
11
12
# Office documents
rga "quarterly report" presentation.pptx
rga "budget analysis" spreadsheet.xlsx
rga "project timeline" document.docx
# PDF documents
rga "machine learning" research_paper.pdf
rga "installation guide" manual.pdf
# E-books
rga "character development" novel.epub
rga "design patterns" programming_book.mobi
1
2
3
4
5
6
7
8
9
10
# Image text extraction (OCR)
rga "street sign" photo.jpg
rga "license plate" security_footage.png
# Subtitle files
rga "dramatic scene" movie.mkv # Searches embedded subtitles
rga "dialogue" subtitles.srt
# Database files
rga "user_table" database.sqlite
Advanced Usage:#
Adapter Configuration: #
1
2
3
4
5
6
7
8
9
10
11
# List available adapters
rga --rga-list-adapters
# Use specific adapter
rga --rga-adapters= zip,tar "search term"
# Disable slow adapters (like OCR)
rga --rga-adapters= -tesseract "search term"
# Cache results for faster repeated searches
rga --rga-cache-max-blob-len= 10M "search term"
Integration with ripgrep Options: #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Case-insensitive search
rga -i "Search Term" documents/
# Show context lines
rga -C 3 "important phrase" reports/
# Search specific file types only
rga -t pdf "research data" papers/
# JSON output for processing
rga --json "api_key" config_files/
# Parallel processing
rga -j 8 "performance" large_archive.zip
Caching Strategy: #
1
2
3
4
5
6
# Enable caching for large files
export RGA_CACHE_DIR = ~/.cache/rga
rga --rga-cache-max-blob-len= 100M "search term"
# Preprocess large archives
rga --rga-cache-compression-level= 1 "index term" huge_backup.tar.gz
Resource Management: #
1
2
3
4
5
6
7
8
# Limit memory usage for OCR
rga --rga-adapters= -tesseract "text" images/
# Parallel processing limits
rga -j 4 "search term" documents/ # Use 4 threads max
# Skip large files
rga --max-filesize= 50M "config" archive.zip
Practical Applications:#
Log Analysis: #
1
2
3
4
5
6
# Search compressed log archives
rga "ERROR" logs.tar.gz
rga -A 5 -B 5 "database timeout" application_logs.zip
# Find configuration in backups
rga "database.*password" system_backup.tar.gz
Research and Documentation: #
1
2
3
4
5
6
7
8
9
10
11
# Academic research
rga -i "neural network" papers/*.pdf
rga "methodology" thesis_sources.zip
# Code archaeology
rga "deprecated function" legacy_code.tar.gz
rga "TODO.*security" project_archive.zip
# Compliance and auditing
rga "personal.*data" document_archive.tar.gz
rga "license.*agreement" contracts.zip
Troubleshooting Script: #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# search-everywhere.sh - comprehensive search tool
search_term = " $1 "
directory = " ${ 2 :- . } "
echo "Searching for ' $search_term ' in $directory "
echo "======================================="
echo "Regular files:"
rg " $search_term " " $directory "
echo -e "\nDocuments and archives:"
rga " $search_term " " $directory "
echo -e "\nCase-insensitive search:"
rga -i " $search_term " " $directory "
echo -e "\nWith context:"
rga -C 2 " $search_term " " $directory "
These tools represent modern approaches to common development and system administration tasks - creating user-friendly CLIs, making complex code editing more accessible, handling unreliable network connections, and searching through diverse file formats efficiently.