はじめに
Claude Code をチームで使っていると、配りたいものが2種類出てきます。
-
スキル(
/xxxで呼び出すカスタムワークフロー) - ナレッジ(LLM が知らないドメイン知識 ― マイナーな SDK のドキュメント、API リファレンス、実装で得たノウハウ)
どちらも素朴に配ると壁に当たります。スキルをファイルで配れば更新が行き渡らず、プロジェクトごとに置けばセットアップが増殖する。ナレッジに至っては「各自がその都度 AI に教える」「プロジェクトに資料をコピーする」運用になりがちで、チームの資産として蓄積されません。そもそもメンバーが Claude Code に慣れていないと、導入手順の時点で脱落します。
この記事では、私が実際に構築・運用している解決策を紹介します。骨子は次の3つです。
- スキルとナレッジを1つの git リポジトリに集約する
- リポジトリ内の各スキルを ユーザーレベル(
~/.claude/skills)へスキル単位のリンクとして注入する(実体はリポジトリの作業コピーのまま) -
post-merge フックで、
git pullのたびにリンクを自動同期する
結果として、メンバーの日常運用は git pull だけになります。スキルの追加・改善も、ナレッジの蓄積も、pull すれば全プロジェクトの Claude Code に即反映。導入も「clone して、Claude Code を起動して、セットアップスキルを1回実行するだけ」です。git さえ使えるメンバーなら、Claude Code のスキル機構を理解していなくても乗れます。
対象読者
- Claude Code を個人で使っていて、チームにも展開したい人
- LLM が知らないドメイン知識を、チーム全員の AI に与え続けたい人
- スキル・ナレッジの一元管理の設計例を探している人
前提として、スキル(SKILL.md)の基本は既知とします。
全体像
リポジトリ構成はこうです(名前は例です)。
team-ai-workflows/
├── .claude/skills/
│ └── team-setup/ # セットアップ自体もスキル(後述)
│ ├── SKILL.md
│ └── scripts/
│ ├── sync_user_skills.sh
│ └── post-merge
├── skills/ # チームに配布するスキル群(1スキル = 1フォルダ)
│ ├── docs-grep/
│ │ ├── SKILL.md
│ │ └── scripts/
│ ├── docs-semantic/
│ └── ...
├── sources/ # ナレッジベース(LLM が知らないドメイン知識)
│ ├── documentation/ # 公式ドキュメントの同期コピー
│ ├── api-reference/ # API リファレンス
│ └── tips/ # 実装経験から得た一次知識
└── README.md
ポイントは2つのスキル置き場の役割分担です。
| 置き場 | 見える範囲 | 役割 |
|---|---|---|
.claude/skills/ |
このリポジトリで Claude Code を起動したときだけ | セットアップ・メンテ用スキル |
skills/ |
リンク注入後、マシン上の全プロジェクト | チームに配布する本体 |
セットアップスキルをリポジトリスコープに置くことで、「clone した直後の状態でもう /team-setup が打てる」という導入動線が作れます。
この構成で動くサンプルリポジトリを公開しています。clone して /team-setup するだけで、この記事の仕組み一式(スキル注入・post-merge フック・ナレッジ検索)をそのまま試せます。
メンバーの体験
先に、メンバーから見た手順を示します。これが今回の設計のゴールです。
初回(マシンに1回だけ):
git clone <リポジトリURL>
cd team-ai-workflows
claude # Claude Code を起動
Claude Code のプロンプトで:
/team-setup
あとは AI が対話形式で案内します。終わったら、どのディレクトリで Claude Code を起動してもチームのスキルが補完に出ます。
日常:
git pull # これだけ。新スキルの追加・削除やナレッジベース更新も一括で自動反映される
Claude Code のスキル機構・ディレクトリ構成・リンクの仕組みを、メンバーは知らなくて構いません。README に書くべきことは「clone して claude を起動して /team-setup と打つ」だけです。
この記事では CLI の例で書いていますが、ツールは何でも構いません。clone や pull は Fork・SourceTree などの GUI クライアントで、/team-setup などのスキル実行は Claude Code のデスクトップ版アプリや VS Code 拡張でも同じように動きます。メンバーが普段使っているツールのままで導入できます。
この基盤の本命: ナレッジベースの同居
ここから仕組みの話に入りますが、その前に強調しておきたいことがあります。この基盤の一番のメリットは、実はスキル配布ではありません。ナレッジベース(sources/)をスキルと同じリポジトリで配れることです。
LLM が知らない領域では、ナレッジがないと AI は戦力にならない
私の開発対象は、LLM がほとんど学習していないマイナーな SDK です。素の Claude に聞くと、存在しない API を自信満々に答えてきます。AI を戦力にするには、正しい知識を渡し続ける仕組みが必須でした。
かといって「各自がその都度ドキュメントを貼る」「プロジェクトごとに資料をコピーする」運用では、知識が個人とプロジェクトに分散して腐っていきます。ほしいのはスキルと同じ性質 ― 一元管理されていて、更新が全員に行き渡る形です。
sources/ に集積し、検索スキルで引く
そこで、ナレッジをリポジトリの sources/ に集積します。
| ディレクトリ | 内容 |
|---|---|
sources/documentation/ |
公式ドキュメントの同期コピー |
sources/api-reference/ |
API リファレンス |
sources/tips/ |
実装経験から得た一次知識(外部のどこにも存在しないノウハウ) |
そして、これを引くための検索スキルを skills/ に置いて一緒に配ります。
-
/docs-grep <質問>… 質問から検索キーワードを複数自動生成し、sources/を横断 grep して関連度順にランキング表示 -
/docs-semantic <質問>… ベクトル類似度+キーワードのハイブリッド検索
検索スキルのスクリプトは、セットアップ時に設定される環境変数 TEAM_WORKFLOWS_DIR で sources/ の場所を解決します。どのプロジェクトで Claude Code を起動していても、チームのナレッジベースを引けるわけです。ベクトル DB もサーバーも立てない「リポジトリ型 RAG」で、git だけで回ります。
スキルと同じリポジトリにあるからこそ
ナレッジを Wiki や別リポジトリではなく、スキルと同じリポジトリに置いているのには理由があります。
-
配布経路が1本になる。 ナレッジの更新も
git pullに含まれる。「Wiki は更新したけど、AI が見る資料は古いまま」が起きない - スキル(検索ロジック)とナレッジ(データ)のバージョンが常に揃う。 検索スクリプトの改修とデータ構成の変更を同じ commit にできる
- 知識の出所が追える。 追記・修正は PR でレビューでき、「その知識がいつ・なぜ入ったか」が git log に残る
-
チームの学びがそのまま AI の学びになる。 誰かがハマって解決したら
sources/tips/に commit。翌日には全員の AI がその落とし穴を知っている
とくに最後の1点が効きます。ナレッジが書いた本人のメモで終わらず全員の AI の回答品質に直結するので、「知見を残す」という行為にチーム全体へのリターンが生まれます。
仕組み1: スキル単位のリンク注入
~/.claude/skills/(ユーザーレベル)に置いたスキルは、マシン上のどのプロジェクトから Claude Code を起動しても使えます。ここへリポジトリ内のスキルをコピーではなくリンク(Windows はジャンクション、macOS/Linux はシンボリックリンク)として注入します。
コピーしない理由は、リポジトリの作業コピーをそのまま実体にするためです。これで次が成立します。
-
git pullした瞬間に、全プロジェクトから見えるスキルが最新になる(同期処理すら本質的には不要。リンク先が更新されるだけ) - スキルを改善したいメンバーは、普段使っているスキルの実体をそのまま編集して commit → push できる。「開発用リポジトリと配布物の乖離」が構造的に発生しない
なぜ「スキル単位」でリンクするのか
~/.claude/skills フォルダ全体を1本のリンクにする方が楽に見えますが、スキル単位にしています。フォルダ全体を1本のリンクにすると、メンバーが個人で作ったスキルと同居できなくなるからです。
注入先をユーザーレベル直下にしているのにも理由があります。実は ~/work-a/・~/work-b/ のようにプロジェクト群をまとめる親フォルダへ .claude を置いて、フォルダごとにスキルを出し分ける形式も試しました。親フォルダ配下で Claude Code を起動すればそのスキルが見える想定でしたが、.git を持つプロジェクトでは親フォルダの .claude のスキルが認識されず、ユーザーレベル(~/.claude/skills)のスキルしか使えませんでした(実機で確認)。git 管理されたプロジェクトで確実に動かすなら、~/.claude/skills/<スキル名>/SKILL.md という素直な形が一番です。
同期スクリプト
同期処理は sh スクリプト1本です(Windows の Git Bash / macOS / Linux で動く想定。PowerShell を使わないので実行ポリシーの影響も受けません)。冪等に作ってあり、何度実行しても安全です。
- リンクなし → 作成
- 壊れたリンク(スキル削除・リポジトリ移動後)→ 除去(移動なら直後に新パスで再作成される)
- 既存エントリ → そのまま
sync_user_skills.sh 全文(クリックで展開)
#!/bin/sh
# Sync user-level skill links for the team workflow repo.
#
# Creates one link per skill:
# ~/.claude/skills/<name> -> <repo>/skills/<name>
#
# Idempotent: safe to run any number of times.
# - missing link -> created
# - broken link -> removed (and recreated if the skill still exists)
# - existing entry -> left untouched (a real folder with a skill name is a
# conflict - resolved interactively by the setup skill)
#
# NOTE: do NOT replace this with a single link over the whole skills folder.
# Nested skill dirs (~/.claude/skills/<dir>/<skill>/SKILL.md) may not be
# discovered depending on the session cwd.
set -u
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
REPO=$(cd "$SCRIPT_DIR/../../../.." && pwd)
SRC="$REPO/skills"
DST="$HOME/.claude/skills"
case "$(uname -s)" in
MINGW*|MSYS*|CYGWIN*) WIN=1 ;;
*) WIN=0 ;;
esac
if [ ! -d "$SRC" ]; then
echo "[error] source not found: $SRC"
exit 1
fi
mkdir -p "$DST"
created=0; removed=0; kept=0
# 1) Remove broken links (entry listed but target unreachable).
for name in $(ls -A "$DST"); do
entry="$DST/$name"
if [ ! -e "$entry" ]; then
if [ "$WIN" = 1 ]; then
win_entry=$(cygpath -w "$entry")
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL="*" cmd /c rmdir "$win_entry" > /dev/null 2>&1 \
&& { echo "[removed] $name (broken link)"; removed=$((removed + 1)); }
else
[ -L "$entry" ] && rm "$entry" \
&& { echo "[removed] $name (broken link)"; removed=$((removed + 1)); }
fi
fi
done
# 2) Create a link for every skill folder that has no entry yet.
for d in "$SRC"/*/; do
name=$(basename "$d")
entry="$DST/$name"
if [ -e "$entry" ]; then
kept=$((kept + 1))
elif [ "$WIN" = 1 ]; then
win_entry=$(cygpath -w "$entry")
win_target=$(cygpath -w "${d%/}")
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL="*" cmd /c mklink /J "$win_entry" "$win_target" > /dev/null 2>&1 \
&& { echo "[created] $name"; created=$((created + 1)); } \
|| echo "[error] $name (mklink failed)"
else
ln -s "${d%/}" "$entry" \
&& { echo "[created] $name"; created=$((created + 1)); } \
|| echo "[error] $name (symlink failed)"
fi
done
echo "sync done: created=$created removed=$removed kept=$kept"
exit 0
Windows では管理者権限不要のジャンクション(mklink /J)を使います。Git Bash から cmd /c を呼ぶ際は、MSYS のパス変換がスイッチ(/J)や Windows パスを壊すため、MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL="*" で無効化しています。筆者の環境は Windows なのでジャンクション側が実運用パス、symlink 分岐は同等処理として付けています。
リポジトリを別の場所へ移動した場合も、このスクリプトの設計なら自然に復旧します。全リンクが壊れる → 一括除去 → 新パスで再作成、が1回の実行で済むためです。
仕組み2: post-merge フックで「pull だけ」にする
リンクの同期が必要になるのは「スキルが増減したとき」です。これを意識させないために、git の post-merge フック(git pull のマージ後に走る)で同期スクリプトを呼びます。
#!/bin/sh
# Keep user-level skill links in sync after every pull/merge.
# Installed into .git/hooks/post-merge by /team-setup.
# Safe to delete; re-running /team-setup restores it.
echo "[team-ai-workflows] syncing user-level skills..."
"$(git rev-parse --show-toplevel)/.claude/skills/team-setup/scripts/sync_user_skills.sh"
exit 0
これをセットアップ時に .git/hooks/post-merge へコピーします(フックはリポジトリに commit できないので、配置はセットアップスキルの仕事です)。
これで、メンバーにとってのスキル更新は完全に git pull と同義になります。「pull したのにスキルが増えてない」という状態が仕組み上発生しません。
仕組み3: セットアップ自体をスキルにする
ここが「Claude Code に慣れていないメンバーでも導入できる」の核です。
セットアップ手順書を README に長々と書く代わりに、手順そのものを SKILL.md にして AI に実行させます。リポジトリの .claude/skills/team-setup/ に置いてあるので、clone 直後にリポジトリ内で Claude Code を起動すれば /team-setup が使えます。
---
name: team-setup
description: チームのスキル群をユーザーレベル(~/.claude/skills)に注入し、
このマシンの全プロジェクトで使えるようにする。マシンに1回実行すればよく、
以後は git pull だけで新スキルも自動反映される。
「セットアップ」「team-setup」といったリクエスト時に使用。
---
# チームAIワークフロー基盤のセットアップ
## Step 1. スキルリンクの同期(常に実行)
bash "<リポジトリ>/.claude/skills/team-setup/scripts/sync_user_skills.sh" を実行する。
同期後にリンク一覧を確認し、skills/ にあるスキル名がリンクになっていない場合は
「同名の個人スキルフォルダが既に存在する」競合。該当スキル名を提示し、
AskUserQuestion で「個人版を残す / リネーム退避してチーム版を注入」を確認する。
## Step 2. post-merge フックの設置(常に実行)
.git/hooks/post-merge が無ければ同梱の post-merge をコピーして chmod +x。
既に別の内容のフックが存在する場合は、上書きしてよいか AskUserQuestion で確認する。
## Step 3. 環境変数の設定(常に実行)
~/.claude/settings.json の env に TEAM_WORKFLOWS_DIR=<リポジトリの絶対パス> を設定する
(既存の設定は必ず保持して書き戻す)。各スキルのスクリプトが sources/ を解決するために使う。
## Step 4. 確認・報告
リンク一覧・フック設置状況・環境変数を確認して報告し、
「セッションを再起動すると全プロジェクトでスキルが補完に表示される」ことと
「以後は git pull だけで更新される」ことを案内する。
手順書ではなくスキルにする利点は、分岐や例外処理をコードで書き切らなくてよいことです。
- 同名の個人スキルと競合したら? → AI が検出して、退避するかスキップするか対話で聞いてくれる
- 既に別の post-merge フックが入っていたら? → AI が中身を見て、上書き確認してくれる
- 環境変数の JSON 書き換え → AI が既存設定を保持したままマージしてくれる
インストーラーを堅牢に作り込む代わりに、「判断が必要な場面では人に聞く」という運用をスキルの記述だけで実現できます。エラーが出てもメンバーが手順書と睨めっこする必要はなく、その場で AI が対処します。
逆に、毎回確実に同じ結果になってほしい処理(リンク同期そのもの)はスクリプトに固めて、スキルからはそれを呼ぶだけにしています。「決定的にやるべき部分はスクリプト、判断が要る部分は AI」という分担です。
この設計に至るまでの試行錯誤
現行の設計は2世代目です。最初の約2ヶ月半は、/team-setup <対象プロジェクトのパス> で対象プロジェクトの .claude/ をリポジトリへの丸ごと1本のジャンクションとして張る、プロジェクト個別注入でした。先に運用していた別の基盤の踏襲で、そちらではコード補完定義などプロジェクト内に置く必要のあるファイルも配るため、個別注入が必然だったのです。
しかし運用すると、プロジェクトが増えるたびにセットアップが必要で漏れた環境が生まれ、注入状態もプロジェクトごとにばらつきました。
転機は配布物の棚卸しです。この基盤で配るのはスキルとナレッジだけで、プロジェクト内に置く必然のあるファイルが1つもない。それなら注入先はユーザーレベルでよい ― こうして現行構成に移行しました。移行と同時に、使われなくなっていたスキル11個も削除しています(20個中、生き残りは9個)。スキルは思ったより死ぬので、配布の仕組みが軽いことは「消す」ためにも効きます。
判断基準としてまとめるとこうなります。
| 配るもの | 適した注入先 |
|---|---|
| スキル + マシン共通のナレッジだけ |
ユーザーレベル(~/.claude/skills) |
| プロジェクト内に置く必要があるファイルを含む(コード補完定義など) | プロジェクト個別注入 |
公式の plugin 機構との比較
Claude Code には公式の配布機構として plugin(marketplace)があります。「なぜ plugin にしなかったのか?」は当然の疑問なので、比較します。
| 観点 | plugin(marketplace) | 本方式(リポジトリ + リンク注入) |
|---|---|---|
| ナレッジの同居 | スキル等の配布が主目的 | 大容量の sources/ と同居し、スキルから参照できる |
| 更新の取り込み | インストール・更新の操作が必要 |
git pull だけ(フックで自動同期) |
| スキルの実体 | インストールされたコピー | 作業コピーそのもの。直したらそのまま commit → push |
| 導入手順 | marketplace 登録と plugin コマンドの理解が必要 | clone して /team-setup(対話式) |
| バージョン管理 | 配布物としてバージョンを切れる | 常にブランチの最新(= チームの今)を共有 |
| 対象 | 不特定多数への配布に向く | 特定チームの密な共同開発に向く |
決め手は2つありました。
第一に、ナレッジの同居です。この基盤の配布物の本体はスキルよりむしろナレッジベース(sources/)で、これは plugin の守備範囲ではありません。「スキルとナレッジを同じ入れ物で、同じ git pull で配る」には、素の git リポジトリが一番素直でした。
第二に、「開発と配布が同一リポジトリで完結する」ことです。plugin 方式では、スキルの実体は marketplace リポジトリにあり、各メンバーの手元にはそのコピーがインストールされます。スキルを改善するには、開発リポジトリを直して、配布物を更新して、各自が更新操作をする、という流れになります。本方式では、メンバーが普段使っているスキルの実体がそのまま git 作業コピーなので、「使っていて気になったところを直して push」までの距離が最短です。
逆に言うと、不特定多数に配る・バージョンを固定して配りたい・チーム外の利用者がいるなら plugin が適しています。本方式は「全員が同じリポジトリを clone できる、密なチーム」向けの設計です。
なぜアップロード型(Gem / Custom GPT)ではなくリポジトリ型か
ナレッジ共有だけなら、Gemini Gem や Custom GPT のように「ファイルをアップロードして共有アシスタントを作る」方式もあります。ブラウザだけで完結し、非エンジニアにも配りやすい選択肢です。
それでもリポジトリ型にしている一番の理由は容量とファイル数です。公式ドキュメントや社内ドキュメントを丸ごと持たせるとファイル数は数百〜数千になり、Gem / Custom GPT / NotebookLM のアップロード上限ではそもそも収まりません。リポジトリ型なら丸ごと管理できます。
運用面での利点も大きいです。
- 更新し続ける仕組みを作れる。 ナレッジは「配る」より「更新し続ける」方が大変ですが、取り込み自体をスキル化しておけば(公式ドキュメントの同期スキル、チャットログの同期スキルなど)、管理者の更新作業も AI に任せられる
- 何を RAG に使っているかが一目瞭然。 GitHub を見ればナレッジの全体像と差分が見えるので、更新の速いナレッジベースでもメンバーが変化を追える
- 根拠を行リンクで共有できる。 AI の回答の参照元を GitHub の該当行リンクとして出力させ、そのまま Discord などでチームに共有できる
| 観点 | アップロード型 | リポジトリ型(本方式) |
|---|---|---|
| 容量・ファイル数 | 上限あり | 実質無制限。ドキュメントを丸ごと置ける |
| 更新 | 管理者が手動で差し替え | commit → 全員 git pull。取り込みもスキル化できる |
| 履歴・レビュー | なし | PR と git log で追える |
| 検索 | 組み込み RAG 固定 | 検索スキルを自分で改善できる |
| 開発との距離 | チャット単体 | コードのすぐ隣で使える |
| 導入 | ブラウザだけ。非エンジニアに強い | git と Claude Code が必要 |
小さく更新の少ないナレッジベースならアップロード型でも回るかもしれません。しかし、大きなナレッジベースを使う開発では、Gem / Custom GPT / NotebookLM は現実的な選択肢になりません。
運用してみて
- スキルが育つようになった。 使っている実体=リポジトリなので、気づいた人がその場で直して push できる。Claude Code に慣れていないエンジニアだけでなく、デザイナーも Claude Code を使ってスキルを push するようになった
- 新プロジェクトのセットアップコストがゼロになった。 ユーザーレベル注入なので、プロジェクトを新規作成してもスキルは最初から使える
まとめ
- チームの Claude Code スキルとナレッジは 1つの git リポジトリに集約する
- LLM が知らないドメイン知識は
sources/に集積し、検索スキルとセットで配る。ベクトル DB 不要の「リポジトリ型 RAG」が全員の AI の回答品質を支える -
~/.claude/skillsへスキル単位のリンクで注入し、実体はリポジトリの作業コピーのままにする -
post-merge フックで同期し、メンバーの運用を
git pullだけにする - セットアップ自体をスキル化し、導入の分岐・例外処理は AI との対話に任せる
- 注入レベルは「配るもの」で決める。プロジェクト内に置く必然のあるファイルがないなら、ユーザーレベル注入で足りる
- 公式 plugin は不特定多数への配布向き。密なチームには「開発 = 配布」のリポジトリ方式が短い改善ループを作る
git さえ使えるチームなら、この仕組みはそのまま持ち帰れるはずです。記事内のスクリプト一式はサンプルリポジトリとして公開しているので、clone して試すところから始めてみてください。fork して skills/ と sources/ を入れ替えれば、そのまま自分のチームの「AI ワークフロー基盤」になります。