コマンドラインインターフェイス ガイドライン (2021)
(clig.dev)- 伝統的な UNIX 哲学を現代的に再解釈した CLI プログラム設計原則と具体的ガイドライン を、オープンソース文書として整理したリファレンスであり、コマンドラインツールを作る開発者を主な読者としている
- CLI は単なるスクリプティングプラットフォームではなく 人間中心のテキスト UI へと進化しており、この変化に合わせて設計原則も更新されるべきである
- コンポーザビリティ(composability)と人間親和性 は相反するものではなく、標準入出力・パイプ・終了コードなど UNIX の慣習を守れば両立できる
- ヘルプテキスト、エラーメッセージ、出力形式、インタラクティビティ、設定体系など、実務で見落とされがちな細部まで具体的な推奨事項として提供
- CLI ツールの 将来互換性とユーザーの信頼 は、インターフェイスの安定性と分析データの透明性で決まり、このガイドはその基準線を示している
哲学 (Philosophy)
人間中心設計
- 伝統的な UNIX コマンドは主に他のプログラムが使う前提で設計されていたが、現在の CLI は人間が直接使う場合がほとんどであるため、人間優先の設計 が必要
- かつての CLI は "machine-first" だったが、現在は "human-first" のテキストベース UI へと進化した
組み合わせ可能な小さな部品
- UNIX 哲学の核心は 小さく単純なプログラムを組み合わせてより大きなシステムを構成すること であり、今でも有効
- 標準の stdin/stdout/stderr、シグナル、終了コードがプログラム間の接続を保証し、JSON はより構造化されたデータ交換を支援する
- ソフトウェアは必ずより大きなシステムの部品になるため、うまく機能する部品になれるかどうかは設計段階で決まる
一貫性
- ターミナル利用者は既存の慣習に手が慣れているため、CLI は 既存のパターンに従うこと が推奨される
- ただし、一貫性が使いやすさを損なう場合は、慎重に慣例を破ることもできる
適切な情報量
- コマンドが数分間まったく出力せずに待機すれば「少なすぎる」情報であり、大量のデバッグログを吐き出せば「多すぎる」情報である
- 情報量のバランス は、ソフトウェアがユーザーを支援するうえで絶対的に重要である
発見しやすさ (Ease of Discovery)
- GUI は画面上に機能をすべて広げて見せるが、CLI は記憶に依存するものだと誤解されがちである
- 包括的なヘルプテキスト、豊富な例、次のコマンド提案 など GUI の手法を取り入れることで、CLI も学びやすくできる
対話としての CLI
- CLI の利用は反復的な試行錯誤による 対話構造 を持ち、エラー修正の提案・中間状態の表示・危険な作業前の確認などがこの特性を活かす設計手法である
- 最悪の相互作用はユーザーを無力に感じさせる敵対的な対話であり、最善は達成感を与える快いやり取りである
堅牢性 (Robustness)
- ソフトウェアは 実際にも、感覚としても 堅牢であるべきだ
- 予期しない入力の優雅な処理、冪等性(idempotence)の維持、進行状況の案内、スタックトレースの露出抑制が重要
- 複雑な特殊ケースを減らして単純さを保てば、堅牢性は高まる
共感 (Empathy)
- CLI ツールは開発者の創造的な道具であるため、楽しく使えるべきだ
- ユーザーが 自分の味方だと感じられるように、問題を十分に考え抜いて設計すること
混沌 (Chaos)
- ターミナルの世界は不一致に満ちているが、その混沌こそが自由な創造の源でもある
- "標準が生産性やユーザー満足度に明らかに害を及ぼすなら、その標準は捨てよ" — Jef Raskin
ガイドライン — 基本 (The Basics)
- 引数パースライブラリ を使うこと: 言語別の推奨ライブラリには Go(Cobra, cli)、Python(Click, Typer, Argparse)、Rust(clap)、Node(oclif) などがある
- 成功時は 終了コード 0、失敗時は 0 以外のコード を返す — スクリプトが成功・失敗を判定する基準
- 既定の出力は
stdout、ログ・エラーなどのメッセージはstderrに送る
ガイドライン — ヘルプ (Help)
-hまたは--helpフラグで 詳細なヘルプテキスト を表示し、サブコマンドにも同様に適用- 引数なしで実行した場合は 簡潔なヘルプ を表示する (説明、1〜2 個の例、フラグ説明、
--help案内を含む)jqがこれをうまく実装した例として挙げられている
--help/-h/help subcommandなど さまざまな形式のヘルプ要求 をすべてサポート- ヘルプテキスト上部に Web ドキュメントへのリンクとフィードバック経路 を提供
- まず例を見せること — 複雑な活用例へ段階的につながるストーリー構成が推奨される
- よく使うフラグとコマンド をヘルプテキスト上部に配置する (git の構成方式を参照)
- 太字の見出しなどの書式 を活用してスキャンしやすく構成するが、ターミナル非依存の方法を使う
- ユーザーが誤入力したときは 意図を推測して修正案を提示 できる — ただし自動実行するかどうかは慎重に判断すること
- 誤入力が単なるタイプミスではなく論理的なミスである可能性があり、自動修正するとその構文を恒久的にサポートしなければならない負担が生じる
ガイドライン — ドキュメント (Documentation)
- Web ベースのドキュメント を提供する — 検索性とリンク共有のために必須
- ターミナルベースのドキュメント を提供する — インストール済みバージョンと同期し、オフラインでもアクセスできる
- man ページ の提供も検討する —
ronnのようなツールで生成でき、npm help lsのようにサブコマンド経由でアクセスできるようにするのが望ましい
ガイドライン — 出力 (Output)
- 人間にとっての読みやすさを最優先 — TTY かどうかで人が読んでいるかを判定
- テキストストリームは UNIX の普遍的インターフェイスであり、機械可読な出力 もサポートすること
- 人間向けの出力がパイプ互換性を損なう場合は、
--plainフラグで プレーンテキスト出力 を提供 --jsonフラグが渡されたら JSON 形式の出力 をサポート- 成功時の出力は簡潔にし、不要なら無出力で — スクリプト用に
-qオプションで出力抑制もサポート - 状態が変わったときはユーザーに知らせる —
git pushがリモートブランチ状態を出力するのは良い例 git statusのように 現在のシステム状態を簡単に確認 でき、次の作業も案内する出力構成にする- 色は意図的に使い、パイプ状態・
NO_COLOR・TERM=dumb・--no-colorなどの条件では 色を無効化 することが必須 - TTY でない環境では アニメーションやスピナーを表示しない (CI ログ汚染防止)
- 絵文字や記号は明確さを高める場合にのみ使う (
yubikey-agentが例として示されている) - 開発者にしか分からない情報は既定の出力から除外し、verbose モード でのみ表示
stderrをログファイルのように使わないこと — 既定ではログレベルラベル (ERR,WARN) の出力を控える- 大量出力では
lessなど ページャの使用 も検討する — TTY 環境でのみ有効化し、less -FIRXオプションが推奨される
ガイドライン — エラー (Errors)
- 予測可能なエラーは 人間が理解できるメッセージに書き換える (例: "chmod +w file.txt を実行する必要があります")
- S/N 比 を維持する — 同種のエラーは単一のヘッダーにまとめて出力
- 重要な情報は 出力の末尾に配置 — 赤いテキストは意図的に、まれに使う
- 予期しないエラーが発生した場合は、デバッグ情報と バグレポート提出方法の案内 を含める
- バグレポート URL に情報を 自動入力して提出しやすく 構成する
ガイドライン — 引数とフラグ (Arguments and Flags)
- 引数(args)は位置ベース、フラグ(flags)は名前ベース — 引数よりフラグを優先 すること
- すべてのフラグに 完全名のバージョン を提供する (例:
-hと--helpを同時サポート) - 単一文字フラグ は頻繁に使うフラグだけに限定
- 標準がある場合は 標準フラグ名 を使う (
-f/--force,-q/--quiet,-v,--jsonなど) - 既定値は 大半のユーザーに適した値 に設定する
- 引数やフラグが渡されない場合は プロンプトで入力を求める、ただし非対話環境ではプロンプトを強制しない
- 危険な作業の前には 確認を求める — 危険度に応じて
y/n確認、dry-run の提供、または直接テキスト入力を要求する- mild(ファイル削除)、moderate(ディレクトリ削除、リモートリソース変更)、severe(サーバー全体削除) に分けて危険度を区別
- ファイル入出力では
-による stdin/stdout の読み書き をサポートする (例:curl ... | tar xvf -) - フラグで シークレットを直接受け取らない —
--password-fileフラグや stdin の使用を推奨 (ps出力やシェル履歴に露出する危険があるため)
ガイドライン — インタラクティビティ (Interactivity)
- プロンプトやインタラクティブ要素は stdin が TTY のときだけ表示 する
--no-inputが渡されたらすべてのプロンプトを無効化- パスワード入力時は エコーを無効化 (入力内容を画面に表示しない)
- ユーザーがいつでも 抜け出せるよう明確に案内 し、Ctrl-C は常に機能するように保つ
ガイドライン — サブコマンド (Subcommands)
- サブコマンド間で フラグ名・出力形式の一貫性 を保つ
- 複雑なツールでは
noun verbまたはverb noun形式の 2 段階サブコマンド構造 を使う (例:docker container create) - 曖昧または類似した名前のサブコマンド は避ける (例: update と upgrade の同時使用は推奨しない)
ガイドライン — 堅牢性 (Robustness Guidelines)
- 入力検証 を早い段階で行い、不正なデータは分かりやすいエラーとともに早期終了する
- 応答性は速度より重要 — 100ms 以内に何かを出力 すること
- 時間のかかる作業には 進捗バー(progress bar) を提供する — Python(tqdm)、Go(schollz/progressbar)、Node(node-progress) のライブラリが利用できる
- 並列処理時は出力が 混ざらないように 注意する
- ネットワークタイムアウトを設定 する — 既定値を含め、永遠に待たないようにする
- 一時的なエラー発生後の 再試行時に前の状態から再開 できるよう設計する
- crash-only 設計 — 後始末なしで即時終了できる構造にして冪等性を確保する
ガイドライン — 将来互換性 (Future-proofing)
- 変更は 後方互換な追加(additive) 方式で維持する
- 互換性を壊す変更の前には プログラム内で事前警告 を表示する
- 人間向け出力の変更は一般に許容される — スクリプト用には
--plain・--jsonの使用を促す - catch-all サブコマンドを禁止 — 後からその名前のサブコマンドを追加できなくなる問題が生じる
- サブコマンド略称の自動許可を禁止 — 明示的な alias のみ許可し、安定して維持する
- 「時限爆弾」を避ける — 20 年後でも動作できるよう外部依存を最小化する
ガイドライン — シグナルと制御文字 (Signals)
- Ctrl-C(INT シグナル)を受けたら 即座に終了 し、クリーンアップ処理にはタイムアウトを設定する
- クリーンアップ中に Ctrl-C が再入力された場合は強制終了できるよう案内する (Docker Compose の例を参照)
- プログラムは クリーンアップ処理が完了していない状態で開始される可能性 を前提に設計する
ガイドライン — 設定 (Configuration)
設定の適用優先順位 (高 → 低):
- フラグ → 現在のシェル環境変数 → プロジェクトレベル設定(
.env) → ユーザーレベル設定 → システム全体設定
設定種別ごとの推奨:
-
呼び出しごとに変わる設定 (デバッグレベル、dry-run): フラグを使う
-
プロジェクト・マシンごとに異なる設定 (パス、色、HTTP プロキシ): フラグ + 環境変数の組み合わせ
-
プロジェクト全体で共有する設定 (Makefile、package.json 型): バージョン管理ファイルを使う
-
XDG Base Directory 仕様 に従う —
~/.configベースの設定パスを推奨 (yarn、fish、neovim、tmux などが対応) -
他プログラムの設定ファイルを自動変更する場合は ユーザーの同意取得 が必須
ガイドライン — 環境変数 (Environment Variables)
- 環境変数は 実行コンテキストによって変わる動作 に適している
- 名前には 大文字・数字・アンダースコア のみを使い、数字で始めない
- 1 行の値 を推奨 — 複数行だと
envコマンドとの互換性問題が発生する NO_COLOR,DEBUG,EDITOR,HTTP_PROXY,SHELL,TMPDIR,HOME,PAGERなどの 汎用環境変数 を優先的に確認する- プロジェクト別
.envファイルの読み込みサポートを推奨 — ただし.envは正式な設定ファイルの代替ではない.envの限界: バージョン管理に含まれない、履歴がない、文字列の単一型のみ、エンコーディング問題に弱い
- 環境変数からシークレットを読まない — すべてのプロセスへ伝播し、ログ漏えい、Docker inspect・systemctl show で露出する危険がある
- シークレットは認証情報ファイル、パイプ、
AF_UNIXソケット、シークレット管理サービスを通じてのみ受け取る
- シークレットは認証情報ファイル、パイプ、
ガイドライン — ネーミング (Naming)
- 単純で覚えやすい単語 を使う — あまりに一般的すぎると他のコマンドと衝突する危険がある
- 小文字と必要に応じたダッシュのみ を使う (
curlは良い例、DownloadURLは悪い例) - 短く保つが、
cd・ls・psのような極端に短い名前は汎用ユーティリティ用に予約されている - Docker Compose の前身である
plum→fig→docker composeへの改名事例は、タイピングのしやすさがネーミングの重要な基準であることを示す実例である
ガイドライン — 配布 (Distribution)
- 可能なら 単一バイナリで配布 する — PyInstaller などを活用
- 単一バイナリが不可能な場合は プラットフォームネイティブのパッケージインストーラ を使う
- アンインストール方法をインストール案内の末尾に明記 する
ガイドライン — 分析データ (Analytics)
- ユーザーの同意なしに使用データやクラッシュデータを送信しない
- 収集する場合は、収集項目、理由、匿名化方法、保存期間を明確に公開する
- 既定では opt-in を推奨 — opt-out 方式なら初回起動時または Web サイトで明確に告知する
- Angular.js(明示的 opt-in)、Homebrew(Google Analytics、FAQ 公開)、Next.js(既定有効の匿名統計) の 3 事例を紹介
- 分析の代替として Web ドキュメントの計測、ダウンロード数の計測、ユーザーへの直接インタビュー を活用できる
1件のコメント
Hacker News のコメント