cairn
cairn は、YAML で書いたハンズオン手順書を一歩ずつ案内する TUI ツールです。順番と確認条件が大切な作業を、迷わず・中断しても続きから進められる形にします。
ケルン(cairn)は登山道に積まれた石の道標です。次の一歩がどこかを示す、という意味を込めています。
インストール
インストールスクリプト
最も簡単な方法です。最新リリースのバイナリを ~/.local/bin にインストールします。
curl -sSfL https://raw.githubusercontent.com/taku-hatano/cairn/main/install.sh | sh
CAIRN_VERSION を指定すると対象のリリースを固定でき、CAIRN_INSTALL_DIR を指定するとインストール先を変更できます。macOS Intel には対応バイナリがないため、下記の go install を使ってください。リリースにはチェックサムが添付されています。手動で取得する場合は、たとえば gh release download v0.1.0 --repo taku-hatano/cairn を実行できます。
go install
go install github.com/taku-hatano/cairn/cmd/cairn@v0.1.0
ソースからビルド
ビルドには Go が必要です。使用する Go のバージョンは mise.toml で固定しているため、mise を使う場合は mise install を先に実行してください。すでにリポジトリを入手している場合は、リポジトリの親ディレクトリから次のようにビルドできます。
cd cairn && mise install && make build
./bin/cairn version
mkdir -p ~/.local/bin && ln -sf "$PWD/bin/cairn" ~/.local/bin/cairn
~/.local/bin が PATH に含まれていることを前提に、以降は cairn コマンドを使います。含まれていない場合は、シェルの設定で ~/.local/bin を PATH に追加してください。
クイックスタート
作業したいプロジェクトのルートで、チュートリアルを作ってすぐ実行します。
cairn init
cairn run example
cairn init は .cairn/example.yaml を作ります。cairn run example はそのチュートリアルを直接開始します。このサンプルでは confirm、choice の分岐と合流、contains / regex の paste 照合を体験できます。echo hello cairn と date +%Y-%m-%d だけを使うので外部ツールは不要です。
手順書を書く
YAML(.yaml または .yml)は一つのシナリオを表します。cairn run <name> の name は ファイルのベース名(例: deploy.yaml なら deploy)です。TUI カタログと cairn list にはこのベース名が表示されるので、そこで実行に使う名前を確認できます。一方、YAML の name は進捗ファイルの識別子です。別物なので、ファイル名と YAML の name は必ずしも一致しません。同じ name が複数あると進捗が衝突するため、重複させないでください。validate は重複を検出するとエラーにし、list と run は警告を表示して続行します。さらに list では重複した両方の進捗列を 名前重複 と表示し、共有された進捗を誤って示さないようにします。
| 項目 |
説明 |
version |
必須。現在は 1 |
name |
進捗ファイルに使う識別子。省略時はファイル名 |
title |
必須。カタログに表示するタイトル |
description |
カタログで表示する説明 |
start |
開始するステップ ID。省略時は先頭 |
steps |
一つ以上のステップ |
body は Markdown です。見出しは # を推奨します(画面ではバッジとして描画されます)。## / ### は記号が残るため、見出しには向きません。YAML の複数行本文で通常の改行だけを入れると、Markdown では soft line break として 1 行につながって表示されます。画面上で改行したい場所には空行を入れてください。本文の描画幅は約 100 桁が上限なので、広い端末で右側に余白があっても仕様です。
| 項目 |
説明 |
id |
必須。ファイル内で一意のステップ ID |
title |
必須。画面に表示するステップ名 |
body |
利用者へ表示する Markdown 本文 |
type |
confirm / choice / paste。省略時は confirm |
next |
次のステップ ID、または END / ABORT |
choices |
type: choice のとき必須の選択肢一覧 |
prompt |
type: paste の入力欄に表示する案内文 |
match |
type: paste のとき必須のログ照合条件 |
allow_skip |
paste ステップでの Ctrl-S によるスキップを許可するか。省略時は true |
choices の各要素は次の形です。
| 項目 |
必須 |
説明 |
label |
はい |
画面に表示する選択肢の文字列 |
next |
いいえ |
選択後の次ステップ ID。省略時はステップ自身の next、さらに省略時は YAML 上の次のステップへ進む |
version: 1
name: local-check
title: ローカル動作確認
steps:
- id: choose
title: 方法を選ぶ
type: choice
choices:
- label: 確認を続ける
next: check-log
- label: 今回は中止する
next: ABORT
- id: check-log
title: 起動ログを確認する
type: paste
prompt: 起動ログを貼り付けてください
match:
contains: "ready"
分岐、完了、中止
遷移は choice の next、ステップの next、YAML 上の次のステップ、末尾なら完了の順で決まります。
| 予約語 |
意味 |
記録 |
END |
その時点でシナリオを完了する |
完了 |
ABORT |
その時点でシナリオを中止する |
中止(完了とは別・通常どおり再開可能) |
「デプロイを中止する」のような、やり遂げていない終わり方には next: ABORT を使ってください。END は成功・完了として記録されます。中止後も cairn run <name> を実行すれば、中止したところからそのまま再開できます。
ログ照合
paste.match には contains または regex のどちらか一方を指定します。ignore_case: true を加えると大文字・小文字を区別しません。正規表現は Go の RE2 構文です。
match:
contains: "Successfully applied"
match:
regex: 'HTTP/[0-9.]+ 200'
ignore_case: true
既定では paste ステップで Ctrl-S によりスキップできます。入力が空で、まだ照合していない状態でも確認ダイアログを経てスキップできます。先へ進ませたくないステップには allow_skip: false を指定してください。作成・変更後は cairn validate path/to/scenario.yaml で確認できます。validate は start や遷移先の未定義参照、version、空の steps、choice の label、重複 name に加え、未知フィールド(例: allow_skips のような typo)も検出します。
操作キー
| キー |
有効な画面 |
操作 |
Enter |
ステップ / 選択肢 |
confirm を完了、選択肢を確定 |
↑ / ↓ |
ステップ / 選択肢 |
ステップ画面では本文をスクロール、choice 画面では選択肢カーソルを移動 |
PgUp / PgDn |
ステップ / 選択肢 |
本文をスクロール |
1〜9 |
すべての選択画面 |
選択肢カーソルを移動。Enter で確定。10 個以上の選択肢は ↑ / ↓ を使う |
Ctrl-D |
貼り付け中 / 入力解除後 |
ログを確定して照合 |
Ctrl-S |
貼り付け中 |
照合のスキップを確認する(許可時のみ)。このステップをスキップしますか? [y/N] で確認 |
Ctrl-U |
貼り付け中 |
入力欄をクリア |
Esc |
貼り付け中 |
入力欄から抜ける |
貼り付け中の b / q / ? |
貼り付け中 |
操作キーとしては効かず、入力欄に文字として入る。Esc で入力を解除してから使う |
Ctrl-C |
貼り付け中を含むすべての画面 |
進捗を保存して中断 |
Enter / i |
貼り付け入力を解除した後 |
入力欄に戻る |
b |
ステップ / 履歴 / 貼り付け入力を解除した後 |
前のステップへ戻る。paste は入力欄に復元 |
v |
ステップ / 貼り付け入力を解除した後 |
完了済みステップと貼り付けログを履歴で見る |
? |
ステップ / 選択肢 / 履歴 / カタログ |
ヘルプを表示・非表示 |
q |
ステップ / 選択肢 / 履歴 / カタログ |
保存して中断 |
進捗ツリーの ✔ は完了、⊘ は照合失敗のまま通過したスキップ、▶ は現在位置です。スキップも TUI ヘッダの進捗カウンタ(例: [3 ステップ通過])に加算されます。分岐では通らないステップがあるため、実行中の TUI には分母を出しません。一方、静的な一覧である cairn list は全ステップ数を基準に 3/8 と表示します。
choice 画面では、本文がスクロール可能なときだけフッタに [PgUp/PgDn] 本文スクロール が表示されます。
進捗の保存と再開
進捗は .cairn/.state/<scenario-name>.json に自動保存され、次回は続きから再開できます。貼り付けたログ本文は、照合が成功して確定したものだけがこの進捗ファイルに保存され、履歴画面(v)で見返せます。入力途中に Ctrl-C で中断した未確定の内容は保存されません。b で戻ると確定済みの内容は入力欄にも復元されます。.state/ は .gitignore されますが、機密情報を貼り付けるかはこの保存を踏まえて判断してください。cairn init は .cairn/example.yaml とともに、この .state/ を除外する .cairn/.gitignore も作成します。
途中または完了後に YAML を変更すると、⚠ 手順書が変更されています という警告が出ます。変更された手順を見落とさないために、再開または最初から開始を選んでください。
進捗がある状態で開くと「続きから再開する / 最初から始める / 終了する」を選べます。完了後に YAML を変更して開く場合は「最初からやり直す / 終了する」の 2 択です。中止した状態で開く場合は「中止したところから再開する / 最初から始める / 終了する」を選べます。
.cairn を別の場所に置く場合は --dir /path/to/.cairn または環境変数 CAIRN_DIR を使えます。フラグが優先されます。
.cairn のない cwd では、YAML を cairn run ./foo.yaml のように直接実行できます。進捗は ~/.local/state/cairn/<hash>/(XDG_STATE_HOME があればその配下)に保存され、保存先の案内は TUI を q で抜けた後に表示されます。cwd またはその親に .cairn が見つかる場合は、YAML 自体が .cairn の外にあっても、見つかった .cairn/.state/<scenario-name>.json に保存されます。不要になったフォールバック進捗は、この ~/.local/state/cairn/<hash>/ ディレクトリを削除して構いません。
コマンド
| コマンド |
内容 |
cairn / cairn run |
カタログから選んで実行 |
cairn run name |
ファイルのベース名で実行 |
cairn run path/to/file.yaml |
ファイルを直接実行 |
cairn --dir path/to/.cairn … |
使用する .cairn ディレクトリを明示指定(上位探索をしない) |
cairn run --reset |
保存済みの進捗を破棄して実行(進捗がある場合は確認する) |
cairn run --reset --yes / cairn run --reset -y |
確認を省略して進捗を破棄して実行 |
cairn list |
手順書と進捗を一覧表示 |
cairn validate [path...] |
YAML を検証。省略時はカタログ全件 |
cairn schema |
手順書 YAML の記法を表示 |
cairn init |
.cairn とチュートリアルを作成 |
cairn version / cairn --version / cairn -v |
バージョンを表示 |
cairn run --reset は進捗がある場合、対話型ターミナルで確認します。stdin が TTY でない環境では進捗を破棄せずに終了するため、意図して破棄する場合は -y または --yes を付けてください。
AI に手順書を書かせるときは、まず cairn schema の出力を渡すと最新の記法に沿わせられます。Claude Code を使う場合は次の「Claude Code で手順書を書く」を参照してください。
出力例:
v0.1.0 (go1.26.1, linux/amd64)
Claude Code で手順書を書く
このリポジトリは、手順書 YAML を書く作業を支援する Claude Code プラグイン cairn-scenario を同梱しています。Claude Code のセッションで次の 2 行を実行するとインストールできます。
/plugin marketplace add taku-hatano/cairn
/plugin install cairn-scenario@cairn
インストール後は「デプロイ手順を cairn で作りたい」のように依頼すると、Claude が次のように進めます。
cairn schema を実行して、その時点の記法を確認する
- 何の作業か、確認方法があるステップはどれか、分岐や中止が要るかをヒアリングする
- ステップの並びに合意してから
.cairn/<name>.yaml を書く
cairn validate が通るまで直す
- 聞き取れずに推測で埋めた箇所を「仮置き」として申告する
- 仕上げに
cairn run <name> を実際に通すことを勧める(TUI なので実行は人が行います)
粒度の決め方、paste にすべき確認とすべきでない確認、allow_skip: false を切る場所、contains と regex の使い分けといった設計上の観点もプラグインに含まれています。記法そのものはプラグインに書き写さず cairn schema から取得するため、cairn を更新してもプラグイン側の追随は不要です。
一点だけ注意があります。paste ステップの照合条件(contains / regex)が実際のログにマッチするかは、cairn validate では確認できません。 cairn run は TUI なので Claude 自身は実行できず、書かれた条件は推測のまま残ります。プラグインは想定するログの実物を尋ね、条件を緩めに倒し、最後に cairn run を勧めるように作ってありますが、実機で一度通すのは利用者の役目です。 途中で止まったら、そのとき貼ったログを Claude に渡せば条件を直せます。
プラグインの実体は skills/cairn-scenario/SKILL.md です。インストールせずに内容だけ読むこともできます。
開発
Go のバージョンは mise.toml で固定しています。make build はホスト向けバイナリを bin/cairn に、make cross は配布用バイナリを dist/ に作成します。設計方針とスキーマの詳細は docs/spec.md を参照してください。
リリース
リリースするには、次の手順を実行します。
VERSION を書き換える(例: 0.2.0 → 0.3.0)
main にマージする
- Actions が自動でタグを作り、リリースする
VERSION には先頭の v を付けず、セマンティックバージョニング形式(例: 0.3.0)で記載します。VERSION を変えずにマージした場合は、既に同じタグが存在するためリリースは作成されません。
ライセンス
MIT License。詳細は LICENSE を参照してください。