クイックスタート
このガイドでは、インストールで作成したスタータープロジェクトをベースに、コマンドの追加やビルドなど、Rune における基本的な開発の流れを体験します。
スタータープロジェクトの構造
Section titled “スタータープロジェクトの構造”create rune-app コマンドにより生成されたプロジェクトは、次のような構成になっています:
ディレクトリsrc
ディレクトリcommands/
- hello.ts
- hello.test.ts
ディレクトリtext/
- _group.ts
- count.ts
- count.test.ts
- package.json
- tsconfig.json
スターターには、シンプルなトップレベルの hello コマンドに加えて、count サブコマンドをもつ text コマンドグループも含まれています。Rune では src/commands 以下のファイル構成がそのまま CLI のコマンド構造になります。詳しくはルーティングのガイドを参照してください。
hello コマンドの実行とテスト
Section titled “hello コマンドの実行とテスト”スターターに含まれる hello コマンドの中身を見てみましょう。src/commands/hello.ts は以下のようになっています:
import { defineCommand } from "@rune-cli/rune";
export default defineCommand({ description: "Say hello from your new Rune CLI", run({ output }) { output.log("hello from my-cli"); },});defineCommand() にオブジェクトを渡し、返り値をデフォルトエクスポートすることでコマンドを定義します。run 関数がコマンドの実体です。output.log を通じて標準出力に書き込むことで、テスト時に runCommand で出力をキャプチャできるようになります。
インストールのステップで動作確認は済んでいますが、改めて実行してみます:
$ pnpm start hellohello from my-cli$ npm run start -- hellohello from my-cli$ yarn start hellohello from my-cli$ bun start hellohello from my-cliスターターにはテストファイルも含まれています。src/commands/hello.test.ts を確認してみましょう:
import { runCommand } from "@rune-cli/rune/test";import { expect, test } from "vitest";
import helloCommand from "./hello";
test("hello command prints a greeting", async () => { const result = await runCommand(helloCommand);
expect(result.stdout).toEqual("hello from my-cli\n");});@rune-cli/rune/test が提供する runCommand を使うと、子プロセスを起動せずにコマンドをインプロセスで実行し、出力を検証できます。ここではコマンドの標準出力が hello from my-cli であることをテストしています。スターターにはテストフレームワークの Vitest も同梱されているため、すぐにテストを実行できます:
pnpm testnpm run testyarn testbun run test以下のような出力が表示されれば成功です:
RUN v4.1.4 /path/to/project
✓ src/commands/hello.test.ts (1 test) 1ms✓ src/commands/text/count.test.ts (2 tests) 2ms
Test Files 2 passed (2) Tests 3 passed (3) Start at 22:42:44 Duration 96ms (transform 22ms, setup 0ms, import 59ms, tests 3ms, environment 0ms)コマンドグループ
Section titled “コマンドグループ”上で述べたように、スターターにはトップレベルの hello だけでなく、text というコマンドグループも含まれています。src/commands/text/ のように src/commands 以下にディレクトリを作ると、その名前が複数のコマンドを束ねるコマンドグループとなり、中にあるルーティング対象ファイルがサブコマンドとして公開されます。
このスターターにはすでに src/commands/text/count.ts が含まれているため、text count というコマンドが自動的に有効化されます。src/commands/text/_group.ts では、そのグループの説明文などのメタデータを定義しています。
text count を実行してみましょう。このコマンドは与えられた文字列に含まれる単語の数をカウントします:
$ pnpm start text count "hello rune world"3$ npm run start -- text count "hello rune world"3$ yarn start text count "hello rune world"3$ bun start text count "hello rune world"3サブコマンドの追加
Section titled “サブコマンドの追加”次に、既存の text コマンドグループに transform サブコマンドを追加してみましょう。
src/commands/text/transform.ts を作成し、以下の内容を記述します:
import { defineCommand } from "@rune-cli/rune";
export default defineCommand({ description: "Transform the input text", args: [ { name: "input", type: "string", required: true, }, ], run({ args, output }) { output.log(args.input.toUpperCase()); },});このファイルを src/commands/text/ に追加すると、Rune はこれを text transform コマンドとして認識します。また、args で位置引数を定義しており、run 関数内では args.input として型安全にアクセスできます。
実行してみましょう:
$ pnpm start text transform helloHELLO$ npm run start -- text transform helloHELLO$ yarn start text transform helloHELLO$ bun start text transform helloHELLOオプションの追加
Section titled “オプションの追加”続いて、transform コマンドに --mode オプションを追加してみましょう。これは upper または lower を受け取る enum オプションで、入力テキストを大文字と小文字のどちらに変換するかを切り替えます。options に定義を追加します:
import { defineCommand } from "@rune-cli/rune";
export default defineCommand({ description: "Transform the input text", options: [ { name: "mode", type: "enum", values: ["upper", "lower"], default: "upper", description: "Transformation to apply", }, ], args: [ { name: "input", type: "string", required: true, }, ], run({ args, output }) { output.log(args.input.toUpperCase()); run({ options, args, output }) { const result = options.mode === "upper" ? args.input.toUpperCase() : args.input.toLowerCase(); output.log(result); },});--mode lower を指定すると、入力を小文字に変換できます:
$ pnpm start text transform HELLO --mode lowerhello$ npm run start -- text transform HELLO --mode lowerhello$ yarn start text transform HELLO --mode lowerhello$ bun start text transform HELLO --mode lowerhello--help で、オプションや引数の情報が自動的にヘルプに反映されていることも確認できます:
Transform the input text
Usage: my-cli text transform [options] <input>
Options: --mode <upper|lower> Transformation to apply (default: "upper") -h, --help Show help
Arguments: input <string>transform コマンドのテスト
Section titled “transform コマンドのテスト”hello コマンドのテストと同様に、transform コマンドのテストも書いてみましょう。src/commands/text/transform.test.ts を作成します:
import { runCommand } from "@rune-cli/rune/test";import { expect, test } from "vitest";
import transformCommand from "./transform";
test("uppercases by default", async () => { const result = await runCommand(transformCommand, ["hello"]);
expect(result.stdout).toEqual("HELLO\n");});
test("lowercases with --mode lower", async () => { const result = await runCommand(transformCommand, ["HELLO", "--mode", "lower"]);
expect(result.stdout).toEqual("hello\n");});runCommand の第2引数にコマンドライン引数を配列として渡すことで、実際の CLI 呼び出しと同じ条件でテストできます。テストを実行して結果を確認しましょう:
pnpm testnpm run testyarn testbun run test以下のような出力が表示されれば成功です:
RUN v4.1.4 /path/to/project
✓ src/commands/hello.test.ts (1 test) 1ms✓ src/commands/text/count.test.ts (2 tests) 2ms✓ src/commands/text/transform.test.ts (2 tests) 2ms
Test Files 3 passed (3) Tests 5 passed (5) Start at 22:42:44 Duration 164ms (transform 56ms, setup 0ms, import 86ms, tests 4ms, environment 0ms)CLI のビルド
Section titled “CLI のビルド”Rune プロジェクトをビルドすると、配布可能な CLI バイナリとして出力されます。
pnpm buildnpm run buildyarn buildbun run buildビルド成果物は dist/ ディレクトリに出力されます。package.json の bin フィールドに指定されたエントリーポイント(デフォルトでは dist/cli.mjs)を通じて、npx やグローバルインストール経由で CLI を実行できます。