OpenRigなら、Claude CodeとCodexの引き継ぎ記録は再起動しても残るのか?

gen
gen

@gennnn ・ 39本

サムネイル

OpenRigの引き継ぎ記録は、再起動のあとどうなったか?

OpenRigの引き継ぎキューは、端末を落としたあとも残るのか。Claude CodeとCodexの引き継ぎを手書きのメモやAGENTS.mdで回していると、渡したつもりの作業がどうなったか分からなくなります。何が残るかは、メモを書いた側のまめさで決まるからです。使い捨てのコンテナで止めては起こし、何が残って何が届かなかったかを確かめました。

デーモンの正常停止、kill -9での強制終了、rig downでのチームの停止。どのあとも、pendingの項目は消えていませんでした。ただし、止まっている相手に出した依頼は、最初の通知が届かないまま残りました。復元のあとに届いたのも、催促の1回だけです。記録が残ることと、受け取る側が気づくことは、別の話でした。

今回動かしたのは、AIを載せないruntime: terminalのシート2つです。Claude CodeとCodexのシートは、CLIを入れておらず認証も渡していないため、起動できていません。確かめたのはrig queueに積んだ記録が残るかどうかまでで、AIの会話の続きが戻るかは、この記事からは言えません。

OpenRigとは

YAMLに「Claude Codeが作業の持ち主、Codexが確認役」のような役割と、誰が誰に仕事を渡すかを書くと、そのチームをtmuxのセッション群として立ち上げるOSSです。READMEによると、載せられるのはClaude Code・Codex・Pi(とOh My Pi)、それに素のterminalで、ライセンスはApache 2.0。チーム全体をrig、その中で役割と宛先を持つ1席をseatと呼び、この記事ではseatをシートと書きます。

GitHubには同じ名前のリポジトリがほかにもあります。本体はmvschwarz/openrig、npmのパッケージは@openrig/cliです。

OpenRigはClaudeもCodexも未認証だとカーネルが起動しない

試した環境は、node:22-bookwormの使い捨てコンテナ(Node v22.23.3)にapt-getでtmux 3.3aを足しただけのものです。ClaudeもCodexもCLIは入れておらず、認証情報も渡していません。npm install -g @openrig/cliは7.6秒で終わり、入ったのは0.6.5 (5ea35e93)でした。READMEに出てくる版は0.6.0(アップグレードの案内)で、npmの最新はそれより先の0.6.5でした。

rig preflightは、Nodeのバージョン、tmux、ホームへの書き込み、ポートの4項目がすべて通過。ところがrig startを叩くと、3.4秒でこう返ってきました。

Kernel failed to start: state=auth_blocked, detail=Error: Kernel rig cannot boot — no AI runtime is authenticated.
Reason: Kernel rig requires at least one of Claude Code or Codex authenticated. Both are unavailable.

デーモン自体は動いていて、rig statusにはKernel: auth_blockedと出ます。ClaudeかCodexのどちらかが認証済みでないと、カーネルと呼ばれる組み込みのrigが立ち上がらず、claude auth loginかcodex loginを実行するよう案内されます。止まるのはカーネルだけで、認証のいらないterminalシートのrigは動きました。

rig preflightが全部通ったあとで止まるので、環境を疑いたくなります。READMEの最初のコマンド2行(npm install -g @openrig/cliとrig setup --dry-run)には、この前提が出てきません。ログインの記載はそのすぐ下の段落にありますが、コマンドを順に打つだけだと、rig startで初めてぶつかります。

ツールを入れた直後の最初のコマンドで止まって、原因が環境ではなく認証だったと分かるまで時間を使った経験はありませんか? 先にClaude CodeかCodexのログイン状態を確認しておくのが近道です。

組み込みのrig first-project-mixed(Claude Codeが持ち主、Codexが確認役)は、起動を試していません。Claude CodeもCodexも認証が要りそうなので、未認証の今回は避け、認証のいらないruntime: terminalのシート2つでrigを自作しました。ownerからcheckへ仕事を渡す関係(delegates_to)だけを書いたYAMLです。

version: "0.2"
name: handoff-test
summary: >
  Two plain terminal seats to test queue handoff persistence without any AI runtime.
pods:
  - id: dev
    label: Dev
    members:
      - id: owner
        agent_ref: "builtin:terminal"
        runtime: terminal
        profile: none
        cwd: "/work/proj"
      - id: check
        agent_ref: "builtin:terminal"
        runtime: terminal
        profile: none
        cwd: "/work/proj"
    edges:
      - kind: delegates_to
        from: owner
        to: check
edges: []
rig up /work/handoff.yaml --plan
rig up /work/handoff.yaml --yes

--planでStatus: planned、--yesでStatus: completedになり、tmuxにはdev-owner@handoff-testとdev-check@handoff-testの2セッションができました。

rig queue handoff は、引き継ぎの何を記録に残すのか

存在しないrigのシートを宛先にすると、unknown_destination_rigで弾かれました。rigは合っていてシート名だけ違う場合は試していません。rig名の書き間違いがその場で分かるのは助かります。

実在する2シートの間では、次の順に打ちました。

rig queue create --source dev-owner@handoff-test --destination dev-check@handoff-test \
  --summary "authモジュールの差分を確認" --body "認証モジュールのリファクタが終わった。tests/auth を通して差分を確認して"
rig queue claim <qitemId>
rig queue handoff <qitemId> --to dev-owner@handoff-test --summary 差分確認済み --body "差分は問題なし"
rig queue transitions <qitemId>

createした項目はpendingになり、宛先のcheckの画面に、Queue handoff: qitem-... - check your queue.という1行と返信用のrig sendの例が届きます。checkの中でclaimするとin-progressに変わり、続けてhandoffでownerに戻すと、元の項目はhanded-offで閉じ、owner宛ての新しい項目がpendingで作られました。

rig queue transitionsには、created → claimed → handed-offの3件が順に残ります。手書きのメモに「受け取りました」と書き足してもらうのは、相手のまめさ頼みです。claimはその書き足しを操作に置き換えたもので、誰が受け取って誰に渡したかを後から追えます。OpenRigを検討する一番の理由は、ここだと思います。

つまずきも1つありました。terminalシートの中身は素のbashなので、届いた通知の各行がコマンドとして実行され、command not foundが並んだのです。AIのシートならプロンプトへの入力になる想定ですが、今回は確かめられていません。

OpenRigを再起動しても強制終了しても、引き継ぎの項目は残るのか

pendingの項目を1件置いたまま、止め方を3通りと、同じYAMLでの作り直しを1通り試しました。1行目だけはclaimの前、check宛ての最初の項目で確かめています。2行目以降は、handoffで作られたowner宛ての項目です。

操作
項目の状態
画面に出たこと
rig daemon stop → rig daemon start
pendingのまま
rig psのWORK列も1のまま
デーモンをkill -9 → rig daemon start
pendingのまま
⚠ no clean shutdown recorded
rig down handoff-test
pendingのまま
2 session(s) killed.、スナップショットを作成、tmuxのセッションも消えた
同じYAMLでrig up /work/handoff.yaml --yes
pendingのまま
旧rigはアーカイブされ、新しいrigとして作られた

kill -9は、終了処理を一切させない乱暴な止め方です。それでも項目はpendingのままで、rig daemon startが前回の異常終了を警告しただけでした。公式ドキュメントでは、キューの項目はデーモンのデータベースの1行とされています。~/.openrig/にはopenrig.sqliteというファイルがあり、項目はデーモンのプロセスの外に保存されているのでkill -9のあとも残ったのだろうと思います。ファイルの中身までは開いていません。プロセスを落としても記録が残るのは、引き継ぎの土台として心強い点です。

4行目では、同じYAMLでrig upしても、止まっていた旧rigには戻らず、旧rigをアーカイブして新しいrigが作られました。それでも項目が見えたのは、宛先がdev-owner@handoff-testというシートの名前で指定されているからだと見ています。チームを作り直しても、同じ名前のシートを置いたら、積まれた依頼はそのまま見えました。

rig downには--yesがありません。rig upの感覚で付けるとerror: unknown option '--yes'で止まり、rigは動いたままです。

残った項目が、止まっている相手にまで届くとは限りません。次の節で、届かなかったほうを見ます。

OpenRigの復元で戻らなかったのは、止まっているシート宛ての通知

もう一度rig downしてから、止まっているcheck宛てに、external-humanを送り主として依頼を作りました。作成は通ってpendingになります。ただ、通知の結果はこうでした。

lastNudgeResult: unroutable: 'dev-check@handoff-test' has no terminal transport on this daemon ...

作る側から見ると、errorは出ず、出力のJSONにlastNudgeResultとしてunroutableと載るだけで、pendingのまま終わります。手紙で言えば、手紙は受取人宛ての私書箱に入っているのに、届いたことを知らせる呼び鈴が鳴らなかった状態です。依頼そのものは消えず、rig queue undeliveredの一覧に出ます。

最初にrig downしたときは、最後にTo restore: rig up handoff-testと出ていました。2回目のrig downはrig restore <snapshotId> --rig <rigId>の案内でしたが、最初の案内のとおり名前で起動すると、止める前と同じrig IDで復元されました。結果はpartially_restoredで、両シートともfresh-primedで、元のセッションは再開されず、新しく立ち上げられました。terminalシートにはAIの会話がないので当然ですが、Claude Codeのシートで会話が戻るかは、ここからは判断できません。

YAMLのパスを渡すと新しいrig、名前を渡すと同じrigに戻る。見た目はほぼ同じコマンドなのに結果が分かれるので、復元したいときはrigの名前を渡します。

復元してもunroutableの記録は変わらず、最初の通知は、復元の約23秒後まで再送されませんでした。代わりに、復元から20秒待ってcheckの画面を見ると、ウォッチドッグ(parked-owner-consumer)の通知が入っていました。

You are parked (arbitrated: idle at prompt) while holding 1 open obligation: qitem-... Resume the work or update each row honestly (close, park-with-wake, or hand off). This is the one wake for this park episode; the wake-or-escalate ladder owns anything further.

「手が空いているのに、抱えたままの依頼が1件ある。再開するか、閉じる、保留する、渡すのどれかに正直に更新して」という催促です。文面には、この停止の間に起こすのはこの1回で、その先はwake-or-escalate ladderという別の仕組みが持つ、とあります。

あなたの運用では、止まっている相手に渡した依頼を、誰が拾いますか? 復元から20秒の間に来た知らせは、このウォッチドッグの1回だけでした。それ以降は見ていないので、その先でどう通知が続くかは分かりません。rig queue undeliveredを見る役を決めておかないと、この知らせを見逃したときに依頼が埋もれかねない、と僕は見ています。

OpenRigを入れる前に知っておく制約と、向かない人

READMEにある前提は、Node 22か24、tmux、macOSかLinuxです。ネイティブWindowsは未対応で、WSL2は未検証とREADMEにあります。ここに、今回確かめた「ClaudeかCodexのどちらかの認証」が加わります。

バージョンはまだ0.xで、npmの最新(0.6.5)がREADMEの案内(0.6.0)より先に進んでいて、更新が速いです。チームの大きさについては、Show HNで作者が、自分が人として見守れるのは4〜5エージェントまでと答えています。これは作者個人が見守れる数の話です。見る対象を減らすためにオーケストレーター役を置く運用も説明していますが、半年前の発言なので、今の版では事情が違うかもしれません。

今回試せていないのは、次の3つです。

  • Claude CodeとCodexのシートでの引き継ぎ。CLIを入れておらず、認証情報もコンテナに渡さない方針で、カーネルが起動しなかったため
  • AIのシートが通知を受けて、自分でrig queue claimを打つかどうか
  • rig send、rig broadcast、rig chatroom。公式ドキュメントのメッセージの項では、rig chatroomはデータベースに保存される一方、rig sendは記録を残さず、残したい依頼はキューに載せるよう書かれています。どれも今回は試していません

仕様を追うなら、OpenRigのドキュメントが入口です。

同時に動かすエージェントが1〜2体で、引き継ぎを手書きのメモで回して困っていないなら、OpenRigは見送ってかまいません。tmuxとNodeを入れ、認証を通し、YAMLを書く手間に見合うのは、僕の感覚では3体以上で依頼が行き来し、誰が何を持っているかを見失い始めてからです。

terminalシートで、復元後20秒まで見た範囲では、OpenRigが残してくれるのは記録と、復元後の催促1回までです。止まっている相手に気づかせ続ける役は、自分で置く必要があると考えています。その役を誰が持つか、先に決められるなら、入れる価値があります。

入れる前にできる点検が1つあります。いまの引き継ぎで、渡した依頼がpendingのように「まだ誰も受け取っていない」状態として見えるか。相手が受け取ったことを、後から追えるか。この2点を自分の運用で見るだけで、OpenRigで何が増えるのかが具体的に見えてきます。