iOS&Androidスマートフォン開発(Swift/Kotlin/React-Native) および Next.js/LaravelをはじめとしたWeb開発ならば、ぜひ創業13年の弊社にお任せください。ワンストップでお届けします。お問合せはこちらから

Claude Codeを4セッション並列で回すために、開発環境の排他ロックをAI自身に作らせた話

  2026年08月31日 10:20 / - PV

yuku_tasのアイコン

こんにちは、Webサービス開発者のyuku_tasです。

簡単なプロフィール: MoldSpoon Inc.代表。開業から15年、業界に携わって20年。Webサイト/iOS/Androidアプリ開発から、データ分析業務・コンサル業務、ベンチャーから保険会社まで様々な案件を個人会社の形で請け負ってまいりました。詳しくはこちら

夏の終わりに、エアコンの効いた部屋でAIとずーっと戯れています。
電気代が心配なyuku_tasです。

Hackerの皆様はいかがお過ごしでしょうか。

経緯

Claude Codeを使い始めて、しばらくすると誰もが同じ場所に行き着きます。

「1セッションだと、待ち時間がもったいない」

考えている間、ビルドを待っている間、こちらは手が空いています。ならば2つ目のセッションを立てて別のタスクをやらせよう——ここまでは自然な発想。

ところが、同じマシンの同じローカル開発環境を2つのセッションが同時に触ると、何かが壊れることがあります。

  • 片方が docker compose down した瞬間、もう片方の動作確認が全部落ちる
  • 片方が php artisan migrate:fresh してDBを吹き飛ばす
  • 同じリポジトリで別々のブランチにチェックアウトし合って、作業が混ざる

しかも厄介なのは、壊れたことにAIが気づかない点です。「テストが落ちました。原因を調査します」と言って、別セッションが落としたコンテナを ループでデバッグし始めたときは、さすがに頭を抱えました。

というわけで、ガード機構を作りました。正確には「作らせた」ですが。

何を作ったか

envguard という名前の小さなツールです。npm依存はなく、Node単体で動くスクリプト1本と、短いHTMLファイルを一つ。丸ごとClaude Codeに書かせています。

やっていることは単純で、「1つの開発環境は、同時に1セッションしか書き込めない」 という排他ロックを、Claude Codeのhooksに割り込ませているだけです。

Claude Code hooks (~/.claude/settings.json / 全セッション共通)
  SessionStart / PreToolUse / UserPromptSubmit / Stop / SessionEnd
        │ stdin JSON → node envguard.mjs hook <event>
        ▼
  state/
    locks/envN.writer.json      ← 排他ライタロック(fsの'wx'で原子的に作成)    sessions/<session_id>.json  ← どのセッションがどこにいるか
    events.jsonl                ← acquire / deny / steal / release の履歴
        ▲                  ▲
  メニューバー表示        ダッシュボード(localhost:8899)

手元の環境は env1env4 の4面あり、それぞれ独立したDocker Composeで ポートをずらして動いています(env1が8001-8003、env2が9001-9003…といった具合)。この「面」の単位でロックを取ります。

気に入っている設計

作らせる過程で、いくつか方針を修正させました。実際に運用してみて効いているのは次の3つです。

1. セッション開始ではロックを取らない(lazy writer lock)

最初は「セッションが始まったら環境を確保する」という素直な作りだったのですが、これは失敗でした。ログを読むだけ・コードを眺めるだけのセッションが、環境を占有してしまうからです。

そこで、最初の書き込み系ツール(Bash / Edit / Write)が走った瞬間に初めてロックを取るよう変更しました。読むだけのセッションは、何面同時に立てても誰の邪魔もしません。

2. 読み取り専用のコマンドは素通しする(拒否リスト方式)

git statusgrep までブロックされると、ロック待ちのセッションが何もできなくなります。かといって許可リスト方式にすると、未知のCLIを使うたびに引っかかって邪魔になる。

結局、「環境を変えうるコマンドだけ」を書き込み扱いにする拒否リスト方式に落ち着きました。rm / mv / git commitpush 系 / npm / composer / php / docker up 系 / sed -i あたりです。出力リダイレクトの >xargs rm のようなラッパー越しの書き込みも拾いますが、2>/dev/null は無害なので判定前に除去しています。

これは事故防止のヒューリスティックであって、セキュリティ境界ではありません。そこは割り切っています。

3. ブロックされたら、人間が明示的に奪う

ロックが取れないとき、AIには理由付きで拒否が返ります。

env1 は session b46bcf5e が使用中です(cwd: ~/dev/hrd_laravel_projects/sc_dev_laravel)。奪取するには: envguard steal env1

重要なのは、AIが自分で steal を実行しないことです。奪取はメニューバーかダッシュボードのボタン、あるいは人間が打つCLIからのみ。「詰まったから力技で解決する」という判断を、AIに握らせないようにしています。

(たまにstealを何度も促されるので、ちょっとこの点はストレスかもしれない笑)

あとは、プロセスの生死を見てクラッシュしたセッションのロックを自動回収したり、30分書き込みがないロックは競合時に自動で明け渡したり(一度書いたきりのセッションが 後続を飢えさせないため)といった細かい調整が入っています。

状態はメニューバーに 1🔴 2🟢 3⚪ 4🟢 と出るだけなので、視線を動かせば今どこが空いているか分かります。

メリット

複数環境を同時に確認できる

一番大きいのはこれです。

以前は「AIに作業させる → 動作確認する → 次の指示を出す」を直列でやっていました。確認している間、AIは止まっています。

今は、env1でAIに改修させながら、env2で別ブランチの動作確認を自分でやり、env3では別セッションが調査を回している、という状態が普通に成立します。それぞれが自分のポートとDBを持っているので、干渉しません。

https://localhost:8002/devhttps://localhost:9002/dev を2つのタブで並べて、改修前後を見比べる、みたいなこともできます。地味ですが、これが効きます。

作業が衝突せず、1つのブランチに複数の文脈が混ざらない

こちらは、体感としてはもっと重要かもしれません。

同じリポジトリを2セッションが触ると、片方のコミットにもう片方の変更が巻き込まれます。 「バグ修正のコミット」に、無関係なリファクタの差分が混ざる。レビューするときに文脈が読めなくなるし、切り戻しもできなくなる。

環境の面が分かれていれば、リポジトリのクローンも分かれています。env1はバグ修正、env2は機能追加、と文脈が物理的に隔離されるので、コミットが自然と1つの意図だけを持つようになりました。

AIは指示すれば何でもやりますが、「今どの文脈で作業しているか」を 勝手に守ってはくれません。作業場所を分けてしまうのが、結局いちばん確実でした。

感想

作ってみて意外だったのは、「AIを制御するツールをAIに作らせる」ことに、ほとんど違和感がなかったことです。

このツールの要件は、私が普段Claude Codeを使っていて踏んだ地雷です。

「セッション開始でロックを取ると読むだけのセッションが邪魔になる」という気づきも、実際に1日運用してみて出てきたもので、机上では出てこなかったと思います。つまり使いながら直すサイクルが要るわけですが、これはAIが得意な領域でした。state/events.jsonl に溜まったログ(今のところ563行)を読ませて、「この拒否は過剰では?」と聞くと、その場で判定ロジックを直してきます。

一方で、設計判断はこちらがやらないとダメでした。 放っておくとAIは「安全側に倒す」ので、許可リスト方式にして何もかもブロックしようとします。それだと運用が回らない、という判断は使う人間にしかできません。steal をAIに握らせないのも同じで、これは技術的な最適解ではなく、「どこまでAIに任せるか」という線引きの問題です。

道具そのものより、その線引きを毎回自分で決めなければならないのが、今の面白いところだと思います。

余談: この仕組み、たぶんもうすぐ要らなくなるなー

ここまで書いておいてなんですが。

この手のローカル多面環境は、今まさに置き換えが進んでいます。

Claude CodeにもGitHub上で直接動く仕組み(code)が入り、ブラウザから投げたタスクが クラウド側のサンドボックスで完結するようになりました。成果物はプルリクエストとして上がってきて、お願いをすれば確認するURLをくれる。

つまり、

・   環境の取り合い → セッションごとに使い捨てのサンドボックスが立つので、そもそも起きない

・   作業の混在 → タスクごとにブランチとPRが切られるので、構造的に混ざらない

・   動作確認 → プレビューURLを開けば済む。ローカルにDockerを4面持つ必要がない

私が数百行かけて解いた問題が、プラットフォーム側で丸ごと消えつつあるわけです。

もちろん、手元のレガシーな環境(PHPのバージョンが古い、外部システムとVPNで繋がっている等)が すぐクラウドに乗るわけではないので、当面この仕組みは使い続けます。ただ、新規のプロジェクトでこれを作るかと言われたら、たぶん作りません。

ぶっちゃけ、進化が早すぎるなと。

数ヶ月前の「ベストプラクティス」が、次のリリースで丸ごと不要になってしまう。このツールを作ったのが今年の6月で、8月にはもう「これ要らなくなるな〜」と思っている。ツールを整備した労力が無駄になる=サンクコストと化すのは悔しくないと言えば嘘になりますが、それ以上に**「その問題はもう解いておいたよ」と言われる感覚**が新鮮です!

対策としては、「作り込まない」「捨てる前提で作る」くらいしか思いつきません。今回のツールがNode単体・依存ゼロ・1ファイルなのは、半分はそういう意図です。消すときは rm -rf 一発で済みます。

まとめ

Claude Codeを並列で回すなら、環境の排他制御は早めに入れておくと事故が減ります。

  • ロックは「セッション開始」ではなく「最初の書き込み」で取る
  • 読み取り専用コマンドは通す。じゃないと待ち側が何もできない
  • ロックの奪取は人間の判断で。AIに逃げ道を与えない

そして、これを作りながら「もうすぐ要らなくなるだろうな」と思っている、というのが2026年8月の実感です。

AIが爆速で進化している現状では、道具は捨てる前提で作るのが、たぶんいちばん割に合います。


この記事が何かのお役に立てれば幸いです。
最後までお読みいただきありがとうございました!

Share Me!