longrun
英語版がソースであり、このページより新しい場合があります。修正の指摘は歓迎です。リポジトリのdocs/TRANSLATION.mdをご覧ください。
Claude Codeセッションのための記憶と協調。プロジェクトは自分の状態をディスクに持ち、それを書いて整えるのはエージェント自身です。だからどのセッションも、プロジェクトが何を知っていて、ほかに誰が作業しているかを見られます。そこから先は、仕事はすでにコンテキストを持っているセッションへ渡り、イベントを待つのにtokenはかからず取りこぼしもなく、1つのセッションがほかをまとめ、人間にしか決められないときは人間に届きます。コースは、おもちゃのプロジェクトshopの上で、この4つをそれぞれ一歩ずつ見せます。中身に興味がなければ、第0章だけで足ります。
1. ディスク上の共有ドキュメント
プロジェクトごとに1つの.longrun/に全セッションから見えるメモがあり、さらにセッションごとに自分のメモがあります。hookはcompaction(会話履歴が自動で要約されること)、/clear、resumeのたびに両方を戻し、毎ターン他のセッションが何を変えたかを見せます。第3章、5章、6章。
2. 委譲:メッセージとタスク
他のセッション宛のメッセージやタスクは、相手のセッションにユーザーのターンとして届きます。動いていればsocket経由、止まっていれば次のターンに受信箱経由です。セッションの名前は、サイドバーに表示されているタイトルです。第7章。
3. イベント駆動:取りこぼしのない待機
ウォッチとは、タイマーが5分ごとにモデルなしで実行するチェックです。条件が成立すると、セッションは渡しておいた文面とともに目を覚まします。ポーリングループはなく、待つ間のtokenもかからず、決めた時間だけ待って遅すぎたり早すぎたりするsleepもありません。第7章。
4. 1つのセッションが他をまとめ、人間に届く
1つのセッションが、すでに開いているセッションのためにボードを持ちます。タスクを配り、詰まりを解消し、停滞しているセッションを名指しし、人間にしか決められないときは全ウィンドウの手前にダイアログを出します。自律ではありません。1つのセッションを、確かめられる1つの条件へ向けて動かすのは/goalの役目です。第8章。
クイックスタート:入れて、あとはふつうに使うだけ
このskillは、人間がいつもどおりセッションで作業することを前提にしています。メモ、ダイジェスト、メッセージの配送はhookと、指示に従うモデルが引き受けます。以下が、手でやることのすべてです。
- 1度だけインストール。1行で済み、checkoutも要りません。インストーラーがソースを自分で取ってきます:
入るのはskill、curl -fsSL https://krllx.github.io/longrun/install.sh | bash~/.claude/settings.jsonの12個のhook、CLIの~/.local/bin/longrun、longrunMCPサーバー、そしてチェックと監視役を5分ごとに走らせるタイマーです。尋ねられるのは1つだけ、次の項目のデスクトップ通知です。cloneから入れる場合も同じinstall.shで、--uninstallが元に戻します。 - 通知(任意)。
install.shは通知を設定するかを尋ね、この項目が必要かどうかは、その答えで決まります。longrunが通知に依存することはありません。全停止も発火したウォッチも、いずれにせよsocketか受信箱を通ってセッションに届くので、断っても他には何も変わりません(--no-notifyで先に答えておくこともでき、あとからbrew install terminal-notifierで有効にもできます)。macOSでは、terminal-notifierがなければインストーラーがbrew install terminal-notifierを実行し(Homebrewが前提です。なければその旨を伝えて先へ進みます)、テスト通知を1つ送ります。macOSはterminal-notifierからの通知を許可するかを1度だけ尋ねることがあるので、許可してください。macOS標準の手段でこの手順を置き換えることはできません。osascript -e 'display notification'はScript Editorの名義で通知を出しますが、Script Editorは通知権限を持たないため、システムは通知を記録するだけで何も表示せず、終了コードは0を返します(macOS 15で25回中25回。Script Editorを先に起動しても権限は付きません)。そのためバナーにはterminal-notifier自身の名前とアイコンが出ます。macOSはこの2つを通知を出したバンドルから取るので、通知ごとに差し替える方法はありません。Linuxではnotify-send(libnotify)で、たいていのデスクトップ環境にはすでに入っています。どちらでもlongrun notify --testで確かめられます。テスト通知を1つ送り、システムが実際に表示したかを読み返し、クリックするとどのセッションが開くかを出力します。絶対に見逃したくないセッションが1つあるならlongrun important on(またはnext、あるいは数字)です。そのセッションのターンの終わりは、notify_turn_endがどう設定されていようと、どのウィンドウが前面だろうと必ず通知されます。別のClaudeセッションで入力している間は、前面ウィンドウを見る通常の判定ではこの通知を出せません。 - フォルダをプロジェクトにする。longrunにとってのプロジェクトは、Claude Codeで開くフォルダです。リポジトリのルートである必要はありません。複数のリポジトリを含むフォルダ、monorepoのサブディレクトリ、空の司令塔フォルダでもかまいません。そこで1度
longrun initを実行します。ターミナルでも、Claude Codeのセッションの中でもよく、頼めばエージェントが代わりに実行します。.longrun/ディレクトリができます。そのフォルダがリポジトリの中にあるなら、ignoreファイルに追加してください(またはlongrun init --externalで、ディレクトリを~/.claude/longrun/の下に置きます)。同じプロジェクトの各worktreeからはlongrun link <path to the project>。確認はlongrun whereです。 - 設定する。セッションでエージェントに「set up longrun」と言います(または
/longrun onboard)。エージェントはlongrun onboardを実行し、skillが何をするかを手短に説明し、主な設定について尋ねます。autocompactのウィンドウ、停滞のしきい値、メモのサイズ、通知です。答えはエージェントがlongrun config setで適用します。例外が1つ。hookはautocompactのウィンドウを設定できないので、エージェントはClaude Codeで/autocompact 300k(または選んだ値)と入力するよう頼みます。そのしきい値の5万token手前で、hookがcompactionの前にメモを書くようセッションに促します。キーの詳細は下の第9章。 - 作業する。呼ぶものは何もありません。開始時にセッションはダイジェスト(共有メモ、自分のメモ、他に誰が作業中か)を受け取り、compactionの後はすべて自動で戻り、他のセッションの変更は次のターンで届きます。行き止まりと決定のメモは、エージェントが自分で書きます。言葉で頼めます。「記録しておいて」「これまで何を試したか」「セッションの状況」「別のセッションに渡して」「何が残っているか」「PRがマージされたら教えて」。
- 複数のセッションと共通の目標。そのうちの1つで「オーケストレーターの役を引き受けて、目標は……」と言います。タスクボードを作って仕事を配り、他のセッションはタスクをターンとして受け取ります。覚えることはありません。「全員止めて」「続けて」も言葉で、オーケストレーターのセッションで言います(下の第8章)。
longrun where(どのプロジェクトとセッションか)、longrun status(各セッションが何をしているか)、longrun watch status(タイマーは生きているか)、longrun notify --test(通知は画面に届くか)、longrun config(実効設定)。なぜ
プロジェクトの本当の状態、つまり何を試して失敗したか、何を決めたか、何が誰待ちかは、1つの会話の中にだけあり、その会話とともに消えます。次のセッション、明日のセッションや隣のウィンドウのセッションは、何も知らないところから始まり、ほかのセッションの存在も知りません。だからプロジェクトはその状態をディスクに置き、エージェントがそれを保ちます。compactionは同じ問題のいちばん鋭い形であって、問題そのものではありません。履歴は要約に圧縮され、次のcompactionはその要約をさらに圧縮します。
/clear、resumeのたびにメモを戻し、要約をそのままアーカイブし、要約するモデル自身にも何を残すかを伝えます。.longrun/があります。中身は全セッションから見える共有メモ、状態つきのセッション一覧、ユーザーのターンとして配送されるメッセージとタスクです。下の図は問題1についてです。上段はモデルがコンテキストに持っているもので、左から右へ時間が進みます。最初は完全な履歴、compactionの後は要約だけ、そしてその要約を読むエージェント。下段は、エージェントがいちばん最初にメモを1行書いたディスク上のファイルです。点線の矢印は、そのメモが開始時と、compactionの後にもう1度コンテキストへ入ることを示します。
skillは何でできているか
機械層:hook、CLI、タイマー
Claude Codeのhookが12個(下の第4章)、longrunコマンド、そしてタイマー(macOSではlaunchd agent、Linuxではsystemd user timerかcron)。機械層はモデルなしで動きます:
- セッション開始時と毎回のcompactionの後にダイジェストを出力します。
- compactionの要約をすべてそのままアーカイブします。
- 失敗したコマンドをジャーナルへ書きます。
- compactionの前にHANDOFFスナップショットを取ります。ユーザーの直近のリクエストと編集したファイルで、後からセッションが同じ場所から続けられるようにするためです。
- セッション間のメッセージを配送します。
- モデルなしで遅延チェックを走らせます。PRがマージされた、URLが応答する、ファイルができた、といったチェックです。
- オーケストレーター、つまりプロジェクトを目標へ導くセッションのために、セッションを見張ります(下の第8章)。
モデルへの指示:SKILL.md
SKILL.mdでそう指示されているから、モデルがすることです。行き止まりに当たったとき、決定をしたとき、環境の事実を知ったときに1行のメモを書きます。コンテキストに足りないものがあればrecallを呼びます。より多くのコンテキストを持つセッションへ仕事を渡します。何を書くかは下の第5章。
実体は3つ、それだけ
プロジェクト
セッション群の共有記憶。longrun initがプロジェクトのフォルダに作る.longrun/ディレクトリです(--externalならツリーの外)。中身は:
- 共有メモ
[n1]、[n2]。1行が1つの事実で、全セッションから見えます。 - 受信箱。いま動いていないセッション宛のメッセージ。
- オーケストレーターのタスクボード。
- compactionの要約とスナップショットのアーカイブ。
詳しくは下の第3章。
セッション
Claude Codeの会話1つ、アプリではサイドバーの1行。セッション固有のものは:
- 自分のメモ
[s1]。共有メモと同じですが、このセッションからしか見えません。 - ジャーナル。時系列、マイルストーン、失敗、compaction。
- meta。カウンターと最後の状態。
置き場所は~/.claude/longrun/の下で、リポジトリの中ではありません。
ディレクトリ
セッションが始まったフォルダ。ルート、worktree、サブディレクトリ。何も保存しません。そのセッションがどのプロジェクトに属するかを示すだけです。
ここで言う「プロジェクト」は.longrun/ディレクトリのことだけを指します。monorepoの中のプロジェクトでも、Claude Codeのtranscriptフォルダでもありません。worktreeはlongrun linkでプロジェクトに紐づけます。worktree自体はメモを持ちません。セッションが属するプロジェクトは1つです。resumeするとアプリはセッションに新しいCLI idを与えますが、longrunはpriorCliSessionIdsの連なりをたどるので、自分のメモは続きます。
ディスク上のファイル
どのファイルも、特定の問題から生まれています:
- セッションのnotes.md:問題1。compactionを生き延びるべき、このセッションの行き止まりと決定。
- プロジェクトのNOTES.md:問題2。どのセッションにも必要な事実。PR番号、決定、環境の癖。
- journal.md:tokenを使わない時系列で、書くのは機械層だけです。開始、終了、失敗したコマンド、compaction、送信。transcriptを読まずに、セッションが何をしたかが分かります。
- archive/compact/とarchive/precompact/:compactionの要約すべてをそのまま、そしてその前のスナップショット(HANDOFF)。前者は
recallで見つかり、後者はcompactionの後のダイジェストで戻ってきます。 - inbox/:いま動いていないセッション宛のメッセージが、次のターンを待ちます。
- meta.json:カウンター、最後の回答、実行中のツール。SESSIONSの行とオーケストレーター向けのフラグは、このファイルから組み立てられます。
- board.json、stale.json、watch/、halt.json:オーケストレーターのボード、「古くなった」印、遅延チェック、全停止。第7章と第8章。
共有のものはすべてプロジェクトの中にあります。自分のものはすべて、リポジトリのツリーの外、同期フォルダの外にあります。ツール呼び出しのたびに書き換わるからです。ファイルをクリックしてください。
| ファイル | 誰が書くか | いつ消えるか |
|---|---|---|
プロジェクトのNOTES.md | エージェント:add、rm、replace、stale、prune | 14日より古いエントリはアーカイブへ(pinは除く)。rmはその行をarchive/notes.mdへ移します |
セッションのnotes.md | エージェント:add --own、rm、replace、prune | 7日間動きのないセッションとともに(archive/sessions/へ) |
journal.md | hook | 200行を超えた分はアーカイブへ |
meta.json | 毎イベントのhook | セッションとともに |
archive/compact/*.md | PostCompact hook | 30日より古いもの、または40件を超えた分 |
inbox/*.md | send、watch、board、ask | 配送時に.archive/へ、そこからは30日後 |
watch/w*.json | watch add、タイマーのティック | 発火から1週間後 |
hook:機械層のありか
Claude Codeはセッションのイベントごとに外部コマンドを呼びます。longrunはそうしたコマンドを12個入れますが、実体はどれも1つのpythonスクリプトです。hookはイベントごとに別プロセスなので、インストールの直後から新しいコードがすべてのセッションで同時に効きます。ループの中のhookをクリックしてください。
1つのセッションのループ
メモ:何をどこへ書くか
1行、英語で、400文字まで(同じ事実を他の言語で書くとtokenが約1.5倍かかり、上限は動かせないからです)。判断基準は1つ。コマンド1回、Read1回、grep1回で取り戻せるか?取り戻せるなら書きません。
| タグ | 何を | たいていどこへ |
|---|---|---|
| dead | 失敗したアプローチと、その理由 | 自分のメモ。他のセッションも同じ行き止まりに突き当たりそうなら共有 |
| decision | 選択と、その理由 | 他のセッションに関わるなら共有 |
| fact | 手間をかけて分かった環境の事実 | 共有 |
| ctx | 人間から与えられたタスクの前提 | 自分のメモ |
| pin | 期限のない事実。PR番号、ブランチ、ホスト | 共有 |
| doc | 1行に収まらないファイルを指し示す1行 | 共有 |
メモは何も指定しなければプロジェクトの共有メモへ入ります。この会話の中だけに留めたいときは--ownです。1行に収まらないほど長いものは、メモではなくファイルにします。longrun doc add research/plan.md "the rollout plan and what is open"が共有メモに指し示す1行だけを残し、どのセッションも必要になったときだけそのファイルを開きます。進捗(「pushした」「テストが緑」)はどこにも書きません。hookがすでにジャーナルに残しているからです。タスクより長く残るもの(ユーザーが誰か、どう働くか)は、ここではなくClaude Codeの自動メモリへ。
確認:これはどこへ入るか
compactionを生き延びる1つのセッション
プロジェクトshop、セッションA。「次へ」「戻る」のボタンか、矢印キーで進みます。左はこのステップで誰が誰と話しているか、右はコマンドとその出力、下はディスク上で何が変わったかです。
recallで見つかります。2つのセッション:共有記憶
セッションBが同じフォルダで開きます。
仕事の受け渡しとイベント待ち
他のセッション宛のメッセージは、相手のセッションにユーザーのターンとして届きます。イベントを待つのにtokenはかかりません。チェックを実行するのはタイマーです。
cmdのチェックはタイマーから実行され、その環境はほとんど空です。絶対パスだけで、Touch IDもsshもaliasも使えません。まずlongrun watch test -- cmd '...'で試してください。オーケストレーター:1つのセッションが他をまとめる
メモとメッセージの上に載る層です。1つのセッションが目標とボードを持ち、ほかは3つのコマンド、board take、board done、board blockだけを覚えます。オーケストレーターに必要なものはすべて状態ファイルにあり、transcriptは読みません。これは複数のウィンドウをまたぐ協調と、人間への連絡線であって、自律的に目標へ向かって走ることではありません。1つのセッションを、評価役が確かめられる1つの条件へ向けて動かすのは、Claude Code自身の/goalの役目です。
誰が何をしてよいか
監視役とオーケストレーターは提案するだけです。動いているツールを殺すものは、ここには何もありません。詰まったウィンドウを止めるのは人間の役目で、Escで止めます。全停止をかける(halt)、その停止を解く(resume)が起きるのは、この会話で人間がそう言ったときだけで、他のセッションの依頼では決して起きません。
ダイアログかボードか
全ウィンドウの手前に出るダイアログは、待てないことのためのものです。確認、権限、人間にしかできない操作です。目標や優先順位についての質問はboard blockでボードへ送り、オーケストレーターがさばきます。
設定
2階層あります。グローバルのファイル~/.claude/longrun/config.jsonと、プロジェクトのファイル.longrun/config.jsonで、プロジェクトの値がグローバルを上書きします。JSONを手で編集する必要はありません:
longrun config # effective values and where each comes from: default / global / project
longrun config set stuck_tool_min 60 --global # for every project
longrun config set notes_max_bytes 8000 # for this project
longrun config unset notes_max_bytes # back to the default
キーは40個ほどあります(完全な一覧はdocs/REFERENCE.mdの第6節)。インストール直後に見ておく価値があるのは、この辺りです:
| キー | デフォルト値 | いつ、どう変えるか |
|---|---|---|
notes_max_bytes、session_notes_max_bytes | 5000, 3000 | 共有メモと自分のメモの予算。毎回の開始時に読まれるので、大きければよいわけではありません。セッションが4つ以上あり、ダイジェストがPRUNEを求め続けるプロジェクトなら8000と4000。 |
notes_max_age_days | 14 | これより古いエントリはアーカイブへ(pinは除く)。セッションがたまにしかないプロジェクトなら30。 |
nudge_tools、nudge_turns | 40, 8 | メモなしで何回の呼び出し、何ターンが過ぎたら促すか(編集か失敗があった場合だけ)。うるさければ80と16。 |
ctx_warn_before | 50000 | autocompactのウィンドウの何token手前でメモを促すか。Claude Codeの/autocompact 300kと組み合わせて働きます。50kで足ります。 |
stuck_tool_min、stuck_wait_min | 30, 10 | オーケストレーター向けの監視役の2つのしきい値。まだ動き続けているツールと、答えのない権限の確認(分)。40分のビルドが普通ならstuck_tool_minを60に。 |
ask_wait_sec、ask_expire_min | 90, 360 | ダイアログがその場の回答を何秒待つか、何分で自分で閉じるか。ふつうはそのままで。 |
watch_ttl_days | 7 | チェックのデフォルトの寿命(グローバルのみ)。リリースを何週間も待つなら30か、そのチェックに--for 30d。 |
autocompact_window | 0 | Claude Codeがどこでcompactionするか。/autocompact Nで設定した値で、300kや1Mを受け付けます。0はClaude Codeに従うという意味です。hookは/autocompactを実行できないので、この値は意図の表明です。onboardがClaude Codeの設定と見比べ、コマンドの入力を頼みます。1Mウィンドウのモデルでの推奨は300k。 |
pr_tool | auto | pr-mergedのチェックがPRの状態をどう問い合わせるか。gh(GitHub CLI)かarc(Arcadia)です。autoはウォッチを登録したフォルダを見て決めます。 |
watch_timer | auto | ウォッチのティックを何が動かすか。launchd(macOS)、systemd(user timer)、cron、none。autoはこのマシンにあるものを選びます。 |
notify_turn_end | off | セッションがターンを終えたときにバナーを出すか。off、unfocused(Claudeのウィンドウが前面にないときだけ)、always。グローバルのみ。絶対に見逃したくないセッションが1つあるならlongrun important onで、こちらはどちらの条件も飛び越えます。 |
longrun onboardが、すべてのキーの現在値と意味をまとめた説明をエージェントへ出力し、エージェントは1つずつ尋ねて答えを適用します。最小構成は、autocompactのウィンドウを300kにすること(/autocompact 300kは自分で入力します)、ビルドが長いならstuck_tool_min 60、セッションが終わったことを知らせてほしいならnotify_turn_end unfocusedです。残りは、ダイジェストか監視役が邪魔になってきたときに触ります。チートシートと限界
# install
curl -fsSL https://krllx.github.io/longrun/install.sh | bash
# skill, 12 hooks, CLI, MCP server, the 5-minute timer, notifications
longrun watch install # the timer alone (the installer already did it)
longrun notify --test # optional: does a notification reach the screen
longrun init [--external] # in the project folder
longrun link <project> # from every worktree
longrun where # which project, which session
# notes
longrun add [--own] -t TAG "..."
longrun doc add path "what is in it" | doc ls
longrun rm s3 n12 | replace n12 "..."
longrun stale n12 "why" | mute n12
longrun notes | prune [--auto] [--shared]
longrun recall term
# sessions
longrun status
longrun send [--list] [--resume] WHO "text"
longrun important on|next|N|off [--to WHO]
longrun watch add --to WHO --then "..." -- pr-merged ID
longrun watch ls | test -- CHECK | sessions
# orchestrator
longrun orchestrate start --goal "..."
longrun board | board add|assign|take|done|block T7
longrun board add --fact "..." --task T7 | board ls --facts | board ack F1
longrun halt "why" | resume
longrun ask "question" --options "Yes,No"
# settings
longrun onboard [done]
longrun config
longrun config set KEY VALUE [--global]
longrun config unset KEY [--global]
機械層が保証すること、モデルに依存すること
| 機械層が保証する | モデルとその指示に依存する |
|---|---|
| compactionの要約すべてのアーカイブ、失敗のジャーナル、HANDOFFスナップショット、メモがコンテキストへ戻ること、メッセージの配送、共有メモの差分、全停止中のツール拒否、ウォッチのチェック | メモが書かれること、そして要点を突いていること、調べ直す前にrecallが実行されること、他のセッションからのメッセージを人間の言葉と取り違えないこと |
限界
- ダイジェストは最大9000バイトです。あふれたときに落とす順番は、ウォッチ、ジャーナルの末尾、オーケストレーターの務め、セッション一覧、ボード、HANDOFF。メモがゆずるのは最後で、しかも
pin以外のいちばん古いエントリから1件ずつ落とすのであって、新しいほうを末尾で切り捨てることはありません。 - アプリのresumeは
priorCliSessionIdsでつながります。CLIの/clearは経験則で、「同じフォルダ、3分以内に理由clearで終了」です。 - socketとtranscriptの形式は文書化されていません。Claude Codeのバージョンが変わると、動いているセッションへの
sendが真っ先に壊れます。受信箱のキューは動き続けます。 - macOSのタイマーの下では、pythonが
~/Documentsにアクセスできないことがあります(TCC)。チェックはそこに依存しません。アクセスできない場合、メッセージは、~/.claude以下のセッションディレクトリに置かれます。 - サブエージェントはダイジェストを受け取りません。
/rewindはメモを巻き戻しません。
詳しくはリポジトリのREADME.md、docs/REFERENCE.md、docs/ORCHESTRATOR.md、そしてlongrun help。