yargs の使い方 — Node.js CLIツール開発の定番パーサー
一言でいうと
yargs は、Node.js でコマンドライン引数のパース・バリデーション・ヘルプ生成を一括で行うライブラリです。サブコマンド、オプション、位置引数などを宣言的に定義するだけで、本格的なCLIツールを構築できます。
どんな時に使う?
- 社内向けCLIツールの開発 — デプロイスクリプトやコード生成ツールなど、
mycli deploy --env productionのようなインターフェースを手早く作りたいとき - 複数サブコマンドを持つCLIアプリ —
gitのようにmycli init/mycli serve/mycli buildといったコマンド体系を構築したいとき - 引数のバリデーションとヘルプ自動生成 — 必須オプションのチェック、型の強制、
--helpの自動出力を手書きせずに実現したいとき
インストール
# npm
npm install yargs
# yarn
yarn add yargs
# pnpm
pnpm add yargs
TypeScript を使う場合は型定義も追加します。
npm install --save-dev @types/yargs
※ 本記事は yargs v18.0.0 を基に執筆しています。v18 は ESM ファーストの設計です。
基本的な使い方
最もシンプルなパターンから見ていきましょう。
#!/usr/bin/env node
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
const argv = await yargs(hideBin(process.argv))
.option('name', {
alias: 'n',
type: 'string',
description: '挨拶する相手の名前',
demandOption: true,
})
.option('greeting', {
alias: 'g',
type: 'string',
description: '挨拶の言葉',
default: 'こんにちは',
})
.parse();
console.log(`${argv.greeting}、${argv.name}さん!`);
$ node greet.js --name 太郎
こんにちは、太郎さん!
$ node greet.js -n 花子 -g おはよう
おはよう、花子さん!
$ node greet.js --help
Options:
--help Show help [boolean]
--version Show version number [boolean]
--name, -n 挨拶する相手の名前 [string] [required]
--greeting, -g 挨拶の言葉 [string] [default: "こんにちは"]
hideBin(process.argv) は process.argv.slice(2) の安全なラッパーで、Electron 環境などの差異を吸収してくれます。
よく使うAPI — yargs の使い方を深掘り
1. .command() — サブコマンドの定義
CLIツールの中核となるAPIです。サブコマンドごとにオプションとハンドラを定義できます。
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
yargs(hideBin(process.argv))
.command(
'serve [port]',
'HTTPサーバーを起動する',
(yargs) => {
return yargs
.positional('port', {
describe: 'バインドするポート番号',
type: 'number',
default: 3000,
})
.option('host', {
type: 'string',
default: 'localhost',
});
},
(argv) => {
console.log(`Server starting at http://${argv.host}:${argv.port}`);
}
)
.command(
'build <entry>',
'プロジェクトをビルドする',
(yargs) => {
return yargs.positional('entry', {
describe: 'エントリーポイントのパス',
type: 'string',
});
},
(argv) => {
console.log(`Building from ${argv.entry}...`);
}
)
.demandCommand(1, 'コマンドを1つ指定してください')
.strictCommands()
.parse();
$ node app.js serve --port 8080
Server starting at http://localhost:8080
$ node app.js build src/index.ts
Building from src/index.ts...
[port]— 角括弧は省略可能な位置引数<entry>— 山括弧は必須の位置引数
2. .option() / .options() — オプションの定義
個別に .option() を呼ぶか、まとめて .options() で定義できます。
const argv = await yargs(hideBin(process.argv))
.options({
env: {
alias: 'e',
type: 'string',
choices: ['development', 'staging', 'production'] as const,
default: 'development',
description: '実行環境',
},
verbose: {
alias: 'v',
type: 'boolean',
default: false,
description: '詳細ログを出力',
},
retry: {
type: 'number',
default: 3,
description: 'リトライ回数',
},
tags: {
type: 'array',
string: true,
description: 'タグのリスト',
},
})
.parse();
// argv.env は 'development' | 'staging' | 'production'
// argv.verbose は boolean
// argv.retry は number
// argv.tags は string[] | undefined
console.log(argv);
$ node deploy.js --env production --verbose --tags api backend
{ env: 'production', verbose: true, retry: 3, tags: ['api', 'backend'], ... }
主要なオプション設定プロパティ:
| プロパティ | 説明 |
|---|---|
type | 'string' / 'number' / 'boolean' / 'array' / 'count' |
alias | 短縮名(-v など) |
default | デフォルト値 |
demandOption | true で必須化 |
choices | 許容値の配列 |
describe / description | ヘルプに表示する説明文 |
coerce | 値の変換関数 |
conflicts | 同時指定不可のオプション |
implies | このオプション指定時に必須となる他オプション |
3. .middleware() — 前処理の挿入
ハンドラ実行前に共通処理を差し込めます。認証チェックや設定ファイルの読み込みに便利です。
import fs from 'node:fs';
yargs(hideBin(process.argv))
.middleware((argv) => {
// 設定ファイルがあればマージ
const configPath = (argv.config as string) || './config.json';
if (fs.existsSync(configPath)) {
const fileConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
Object.assign(argv, fileConfig);
}
})
.middleware((argv) => {
// ログレベルの正規化
if (argv.verbose) {
argv.logLevel = 'debug';
}
})
.command('deploy', 'デプロイを実行', {}, (argv) => {
console.log(`Log level: ${argv.logLevel}`);
})
.parse();
ミドルウェアは登録順に実行されます。非同期関数(async)も使用可能です。
4. .check() — カスタムバリデーション
choices や demandOption では表現しきれない複雑なバリデーションを記述できます。
const argv = await yargs(hideBin(process.argv))
.option('port', {
type: 'number',
demandOption: true,
})
.option('start-date', {
type: 'string',
})
.check((argv) => {
if (argv.port < 1 || argv.port > 65535) {
throw new Error('--port は 1〜65535 の範囲で指定してください');
}
if (argv['start-date'] && isNaN(Date.parse(argv['start-date'] as string))) {
throw new Error('--start-date は有効な日付形式で指定してください');
}
return true; // バリデーション通過時は true を返す
})
.parse();
$ node app.js --port 99999
Error: --port は 1〜65535 の範囲で指定してください
5. .completion() — シェル補完スクリプトの生成
Bash / Zsh 向けの補完スクリプトを自動生成できます。
yargs(hideBin(process.argv))
.command('init', 'プロジェクトを初期化')
.command('build', 'ビルドを実行')
.command('deploy', 'デプロイを実行')
.option('env', {
choices: ['dev', 'staging', 'prod'],
})
.completion('completion', 'シェル補完スクリプトを出力')
.parse();
# 補完スクリプトを生成して .bashrc に追加
$ node app.js completion >> ~/.bashrc
# 以降、Tab キーでコマンドやオプションが補完される
$ node app.js <TAB>
init build deploy completion
カスタム補完ロジックも定義可能です。
.completion('completion', (current, argv, done) => {
// 非同期で候補を取得
fetchAvailableTargets().then((targets) => {
done(targets);
});
})
類似パッケージとの比較
| 特徴 | yargs | commander | meow | citty |
|---|---|---|---|---|
| サブコマンド | ✅ ネスト可 | ✅ ネスト可 | ❌ | ✅ |
| 自動ヘルプ生成 | ✅ 高機能 | ✅ | ✅ 最小限 | ✅ |
| シェル補完 | ✅ 組み込み | ❌(別パッケージ) | ❌ | ❌ |
| TypeScript サポート | @types/yargs | 組み込み | 組み込み | 組み込み |
| バリデーション | ✅ 豊富 | 最小限 | ❌ | ✅ |
| バンドルサイズ | やや大きい | 中程度 | 小さい | 小さい |
| 設計思想 | 宣言的・機能豊富 | メソッドチェーン | ミニマル | モダン・軽量 |
選定の目安:
- 機能豊富なCLIを作りたい → yargs
- 軽量でシンプルに済ませたい → commander / meow
- TypeScript ファーストで最新のエコシステム → citty(unjs)
注意点・Tips
parse() は非同期になりうる
v16 以降、.parse() は Promise を返す場合があります(コマンドハンドラが async の場合など)。await を付けるか、.parseAsync() を明示的に使うのが安全です。
// 推奨
const argv = await yargs(hideBin(process.argv)).option('name', { type: 'string' }).parse();
hideBin を忘れない
yargs(process.argv) と書くと、node や実行ファイルパスまでパースされてしまいます。必ず hideBin を通しましょう。
// ❌ NG
yargs(process.argv).parse();
// ✅ OK
yargs(hideBin(process.argv)).parse();
.strict() を有効にする
未定義のオプションが渡された場合にエラーにしてくれます。タイポの早期発見に有効です。
yargs(hideBin(process.argv))
.strict() // 未定義オプションをエラーに
.strictCommands() // 未定義コマンドをエラーに
.option('port', { type: 'number' })
.parse();
$ node app.js --prot 3000
Unknown argument: prot
.config() で設定ファイルをサポート
JSON 設定ファイルからオプションを読み込む機能が組み込まれています。
yargs(hideBin(process.argv))
.config('config', 'JSON設定ファイルのパス')
.option('port', { type: 'number', default: 3000 })
.parse();
# config.json: { "port": 8080 }
$ node app.js --config ./config.json
グループ化でヘルプを見やすくする
オプションが多い場合は .group() でカテゴリ分けすると、--help の出力が格段に読みやすくなります。
yargs(hideBin(process.argv))
.option('host', { type: 'string', default: 'localhost' })
.option('port', { type: 'number', default: 3000 })
.option('verbose', { alias: 'v', type: 'boolean' })
.option('quiet', { alias: 'q', type: 'boolean' })
.group(['host', 'port'], 'サーバー設定:')
.group(['verbose', 'quiet'], 'ログ