yargs の使い方

yargs the modern, pirate-themed, successor to optimist.

v18.0.0/週MITCLI
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

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デフォルト値
demandOptiontrue で必須化
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() — カスタムバリデーション

choicesdemandOption では表現しきれない複雑なバリデーションを記述できます。

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);
  });
})

類似パッケージとの比較

特徴yargscommandermeowcitty
サブコマンド✅ ネスト可✅ ネスト可
自動ヘルプ生成✅ 高機能✅ 最小限
シェル補完✅ 組み込み❌(別パッケージ)
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'], 'ログ

比較記事