Node.jsでCLIツールを作ろうとすると、どのライブラリを選べばいいか迷うことはありませんか? 本稿では、シンプルで使いやすい「citty」というライブラリをご紹介します。
cittyには次のような魅力的な特徴があります:
- TypeScriptによる型安全な引数(args)の定義
- 直感的なサブコマンドの作り方
- 美しいヘルプ表示
僕自身、cittyを使ってCLIツールを作ってみて、その使いやすさに感動しました。本稿では、cittyの基本的な使い方から実践的な実装方法まで、順を追って解説していきます。
cittyのインストール
まずは、新しいプロジェクトを作成し、cittyをインストールしましょう。
# プロジェクトの作成
mkdir my-cli && cd my-cli
npm init -y
# package.jsonの設定
# "type": "module" を追加する(ESモジュールとして実行するため)
# cittyのインストール
npm install citty
最もシンプルなCLIの作成
cittyを使った最も基本的なCLIを作ってみましょう。以下のコードをindex.ts
に保存します:
import { defineCommand, runMain } from "citty";
const main = defineCommand({
meta: {
name: "my-cli",
description: "My first CLI using citty",
},
run() {
console.log("Hello from my CLI!");
},
});
runMain(main);
このコードについて説明しましょう:
-
defineCommand
で新しいコマンドを定義 -
meta
オブジェクトでコマンドの基本情報を設定 -
run
関数に実行時の処理を記述 -
runMain
でコマンドを実行
実行してみましょう:
node --experimental-strip-types index.ts
Hello from my CLI!
/* 最近のNode.jsはTypeScriptが直接実行できて便利ですね! */
型安全な引数の定義
cittyの大きな魅力の一つは、型安全に引数を定義できることです。例えば、ユーザーから名前(--name
)を受け取る引数を追加してみましょう:
import { defineCommand, runMain } from "citty";
const main = defineCommand({
meta: {
name: "my-cli",
description: "CLI with arguments",
},
args: {
name: {
type: "string",
description: "Your name",
required: true,
},
},
run({ args }) {
console.log(`Hello, ${args.name}!`);
},
});
runMain(main);
このコードのポイントを説明します:
-
args
オブジェクトで引数を定義 - 各引数に
type
を指定することで型安全性を確保 -
required: true
で必須パラメータとして設定 -
description
でヘルプ表示時の説明文を設定
node --experimental-strip-types index.ts --name Taro
Hello, Taro!
サブコマンドの実装
大規模なCLIツールでは、複数のコマンドを提供したいケースがあります。cittyではサブコマンドもかなり直感的に実装できます:
import { defineCommand, runMain } from "citty";
// サブコマンドの定義
const greetCommand = defineCommand({
meta: {
name: "greet",
description: "Say hello"
},
args: {
name: { type: "string", required: true },
},
run({ args }) {
console.log(`Hello, ${args.name}!`);
},
});
const main = defineCommand({
meta: {
name: "my-cli",
description: "CLI with subcommands"
},
subCommands: {
greet: greetCommand, // サブコマンドの組み入れ
},
});
runMain(main);
サブコマンドごとにdefineCommand
を使って定義し、それをsubCommands
に加えることで、サブコマンドを追加できます。簡単ですね。
実行例:
node --experimental-strip-types index.ts greet --name Taro
Hello, Taro!
美しいヘルプ表示
cittyの魅力の一つは、デフォルトできれいなヘルプを自動生成してくれることです。--help
オプションを付けて実行してみましょう:
node --experimental-strip-types index.ts --help
このように、コマンドの使い方が見やすく表示されます。サブコマンドのヘルプも確認できます:
node --experimental-strip-types index.ts greet --help
まとめ
cittyは、以下のような点がいい感じです:
- TypeScriptの型システムを活かした安全な引数定義
- 直感的なAPIによるシンプルな実装
- サブコマンドの柔軟な管理
- 美しく見やすいヘルプ表示
Node.jsでCLIツールを作る際は、ぜひcittyの採用を検討してみてください。シンプルさと型安全性を両立した素晴らしいライブラリだと思います。
最後までお読みいただき、ありがとうございました。
Twitterでは、Node.js、TypeScriptに関する話題を発信しています。よろしければフォローをお願いします! @suin