リポジトリごとに散らばるAIドキュメント
ClaudeやCodexを使っていると、AIエージェントをディレクトリごと、リポジトリごとに起動することになります。AIを初めて導入するときや新しいリポジトリを作るとき、エージェントをスムーズに使うためにいろいろなドキュメントを設定するのですが、リポジトリが分かれていると、このドキュメントを整備するのがかなり面倒に感じられました。
特に不便だった点は次のとおりです。
- 良いスキルやエージェントがあっても、別のリポジトリで使いたければ一つずつコピーしなければなりません。
- そのため修正が出るたびに、リポジトリごとに別々に直す必要があります。
- リポジトリの作業履歴(Gitヒストリー)にAIドキュメントが混ざり始めます。
- AIドキュメントも定期的に更新が必要ですが、作業リポジトリに混ざっていると、AIドキュメントの修正を機能のPRに含めるべきか、別のPRに分けるべきかといった問題が出てきます。
- ドキュメント作業もPRレビューの対象になるので、だんだんAIドキュメントの更新が遅れ、使い勝手も悪くなっていきます。
- リポジトリAとリポジトリBを行き来しながらお互いを確認する必要があるとき、ドキュメントの整備が難しくなります。
- FEとBEのリポジトリが分かれていたり、BEもAPIごとにリポジトリを分けて管理していたりするケースです。毎回
ghで別のリポジトリを読み、そのリポジトリのAIドキュメントを確認するためにいくつもの手順を踏む必要があり、速度にもトークン使用量にも悪影響がありました。
- FEとBEのリポジトリが分かれていたり、BEもAPIごとにリポジトリを分けて管理していたりするケースです。毎回
人が気をつけて直せばいいんじゃないか…と言われるかもしれませんが、私は基本的に、人の善意や意識的な努力に頼るのはあまり良い方法ではないと考えています。
面倒だからやらない、忘れてしまう、実際の開発業務が忙しい、といった理由で、優先度の低い作業は後回しにならざるを得ないですよね?
では、ドキュメントの構成をどう整えれば、人の認知負荷を減らせるでしょうか?
どうやって管理するか
求めていた条件は次のとおりです。
- 設定の原本は一か所だけで管理する。
- 共通の設定とリポジトリごとの設定を分けられる。
- リポジトリをクローンした場所が人によって違っても動く。
- 別途インストールが必要な依存関係がない。
この条件をもとに、いくつかの方法を検討してみました。
Gitサブモジュール
最初に思いついたのはサブモジュール(git submodule)です。サブモジュールで管理すれば、上の条件は満たせます。ただ、次の二つのデメリットがかなり大きく感じられ、結局採用しませんでした。
一つ目は、AIドキュメントの更新を取り込むために、サブモジュールを定期的に最新化しなければならないことです。サブモジュールは特定のコミットを指す仕組みなので、AIドキュメントが更新されたらサブモジュールを最新のコミットに上げ、その変更もまた作業リポジトリにコミットする必要があります。
二つ目は、AIエージェントが使うワークツリー(git worktree)との相性です。ワークツリーとサブモジュールの相性が良くないことは、エージェントを使う中ですでに知っていました。AIドキュメントをサブモジュールとして取り込むと、ワークツリーを作るたびに追加の設定が必要になるだろうと判断しました。
シンボリックリンク
シンボリックリンクで管理しようというのは会社で出たアイデアで、良さそうに見えました。デメリットはWindows環境で使いにくい可能性があることでしたが、会社の作業環境は全員Macだったので、この方法で導入しました。
詳しい構成
ディレクトリ構成
ai-documents/
repo.yaml # 管理するリポジトリの一覧(リモートURL基準)
install.sh # リポジトリ検索 → _commonのミラーリング → シンボリックリンク作成
update.sh # git pullしてからinstall.shを再実行
uninstall.sh # 作成したシンボリックリンクを削除
projects/ # 共通ドキュメントとリポジトリごとのドキュメント(後述)
リポジトリをパスではなくリモートURLで探す
repo.yamlには、この共有AIドキュメントをインストールするリポジトリを登録します。このとき、ローカルパスではなくGitのリモートURL(remote)で書きます。
anchor: /opt/ai-documents
search_paths:
- ~/Develop
repos:
- name: portfolio
remote: https://github.com/DeveloperRyou/portfolio.git
そのあとai-documentsでinstall.shを実行すると、search_pathsの下を探してリモートURLが一致するクローンを見つけ、見つけたパスをマシンごとにキャッシュします。ノートPCとデスクトップでリポジトリの場所が違っても、チームメンバーごとにリポジトリの場所や名前が違っても、search_pathsの中にあれば使えるようにするためです。
install.shでシンボリックリンクを二段階にしている理由
最初は各リポジトリのCLAUDE.mdがai-documentsのクローンを直接指すようにしていましたが、これだとai-documentsを別の場所にクローンし直した瞬間、すべてのリンクが壊れてしまいます。
しかも、このリンクは実際の作業リポジトリにコミットされるパスです。開発者ごとに異なるローカルパスをコミットするわけにはいかないので、間に固定のアンカーディレクトリを一つ置きました。
<portfolio>/CLAUDE.md
→ /opt/ai-documents/checkout/projects/portfolio/CLAUDE.md
→ (checkoutは実際のai-documentsクローンを指すリンク)
各リポジトリのリンクは必ず/opt/ai-documents/checkoutを経由するので、ai-documentsを移動してもcheckoutのリンクを一つ張り直すだけで済み、管理対象のリポジトリ側は何も変える必要がありません。
こうして作ったリンクは、管理対象のリポジトリにコミットしておきます。portfolioを新しくクローンしてもCLAUDE.mdと.claudeがリンクとして付いてくるので、アンカーさえ用意されていればすぐに動きます。
_commonとリポジトリごとのフォルダ
projects/
_common/.claude/ # 全リポジトリ共通:RULES.md、フック、共通スキル
portfolio/ # portfolio専用:CLAUDE.md、専用スキル
ai-documents/ # ai-documents自身のCLAUDE.md
install.shはまず_common以下のファイルを各リポジトリのフォルダに一つずつミラーリングし、そのあとリポジトリのフォルダを丸ごと実際のリポジトリにリンクします。ミラーリングされたリンクはai-documentsリポジトリの.git/info/excludeに入れて、コミットされないようにしています。
名前が重なるファイルは別に扱う必要がありました。CLAUDE.mdはリポジトリごとに内容が違うので、_commonで上書きしてはいけません。そこで共通ルールは_common/.claude/RULES.mdに置き、各リポジトリのCLAUDE.mdの先頭で一行で読み込むようにしました。
@.claude/RULES.md
settings.jsonにも同じ問題があります。共通で有効にしておきたいプラグインやフックがある一方で、特定のリポジトリでしか使わないプラグイン(Playwright、frontend-design)もあります。そこでリポジトリのフォルダにsettings.override.jsonを置くと、共通のsettings.jsonの上にディープマージ(deep merge)して最終的なファイルを作るようにしました。
ルール:mainに直接コミット
ai-documents自体は、ブランチもPRも使わずにmainに直接コミットしてプッシュします。コードではなくドキュメントを直すのにPRまで開くのはやりすぎですし、レビューの負担があるとドキュメントの更新は優先度が下がって、なかなか最新化されません。
特に、AIエージェントを起動するたびにドキュメントが最新かどうかを確認してから実行しなければならないとしたら、それはありえない作業フローだと思いました。
このルールもai-documentsのCLAUDE.mdに書いてあるので、Claude Codeが設定を直すときは自分でmainにコミットします。
会社では、状況に応じてPRを開く形にしています。ドラフト(draft)のままのPRもあれば、機能開発に長い時間がかかる場合もあるので、ドキュメントもPRで保留にしておくことを許可していました。ここは作業の状況に合わせて柔軟に運用すればいいと思います。
AIエージェントのセッション開始時に自動で更新
共通のsettings.jsonにSessionStartフックを設定して、Claude Codeのセッションが開くたびにupdate.shが走るようにしました。update.shはai-documentsをgit pullしてインストールを再実行するので、別のリポジトリで、別の開発者が直したルールも次のセッションからすぐに反映されます。
自分で何も実行しなくていいというのが、このドキュメント管理方法のポイントです。
スキル
_commonにたまってきたスキルはこちらです。
backlog-issue:Why / What / Acceptance形式でGitHubのissueを作成resolve-issue:issue一つを、ブランチ作成、実装、ローカルモデルによるレビューを経てPRまでissue-status:オープン中のPRとissueを確認し、次にやることを整理handoff:セッションを終える前に10行の引き継ぎメモを作成
ほかにもスキルを追加し続けていますが、スキルの話は別の記事で詳しく書こうと思います。
メリットだと感じたところ
共有ドキュメントを別に管理してみて感じたメリットは、やはりドキュメントや設定を更新する負担が減ったことです。ルールを一か所で直してコミットすれば終わりなので、「これ不便だな」と思ったらすぐにルールやスキルにできます。
実際の作業リポジトリのGitヒストリーが汚れなくなったのも、個人的に挙げたいメリットです。最近はAIエージェントが作業するときに、Gitヒストリーを読んでコードの変更履歴も把握しますからね。
ほかの解決方法はないのか
実は、マルチリポではなくモノレポで作業していれば、AIドキュメントを整備するためにシンボリックリンクを導入したり…といったことは必要なく、もっとすっきり解決できるのかもしれません。
ただ、すでにマルチリポで構築されたプロジェクトをモノレポに変えるのは、CI/CDも絡んでいていろいろと手間がかかりそうです。そういう意味で、ai-documentsは今のリポジトリ体制を維持しながら、ドキュメントを手軽にまとめて管理できる方法なのではないかと思います。