実現したいこと
Claude Code にこう頼む
Rust で “Hello, World!” と表示するプログラムを作って。Issue 作成から実装、PR、マージまでやって。進め方はこのリポジトリのルールに従って
Claudeに伝えるのはそれだけ
- コミットメッセージの形式を指示しない
- ブランチ名も指示しなくても良い
- Issue と PR の紐付け方法も指示しない
それでも Claude Code は次の開発の流れを 開発チームのルールを守って 自動で実行する。
しかも AWS キーのような秘密情報をコミットしようとすると、今度は機械が止める。
- ブランチ運用を覚える必要がない
- コミット規約を暗記する必要もない
- レビュアーは毎回同じ規約違反を指摘しなくていい
ルールを README や Wiki に書いて、人が読んで覚えて守る運用をやめる。代わりに Claude Code の Skill と Hook に移し、AI と機械が毎回適用する。人が細かなルールを端から端まで覚えて運用しなくてもいい。間違えても止まる。だから初日から正しく開発できる。
このような仕組みを構築する
はじめに
チームの開発ルールは、たいてい README や社内 Wiki に文章として書かれている。
そしてチームが成長するとルールは増える。ルールが増えると資料も増える。そして誰も全部は覚えられないレベルの量のドキュメントが整備される。
「コミットメッセージはこの形式で」「main に直接 push しない」「PR は必ず立てる」「API キーをコミットするな」といった具合だ。確かに書いてはあるのだが、新しく入った人がそれを全部読むかというと読まないし、読んだとしても覚えていられないレベルになっていないだろうか?
結局はレビューで「ここが規約違反です」と指摘し、直してもらい、次に入った人にまた同じ指摘をすることになる。人が入れ替わるたびに、同じやりとりを延々と繰り返す。
この記事で紹介する team-dev-kit は、その繰り返しをやめるための道具として構築した。ルールを「人が読んで覚えて守るドキュメント」から、「Claude Code が毎回自動で適用する Skill」と「commit の瞬間に機械が止める Hook」に置き換える。clone した瞬間からチームのルールが効いている状態をつくる。
「覚えなくていい。間違えても自動で止まる。だから初日から正しく開発できる。」を実現する
誰のための道具か
一人で趣味のリポジトリをいじっている人にはあまり意味がない。
刺さるのは、複数人・複数リポジトリで同じ規約を回しているチームだ。とくに、新しいメンバーの出入りがあって、入るたびに同じオンボーディング説明を繰り返しているチーム。レビューで規約違反の指摘が毎回出ているチーム。そして、秘密情報をうっかりコミットする事故を「気をつけよう」ではなく仕組みで止めたいチーム。
前提として Claude Code をチームで使っている、あるいはこれから使い始めるのが条件になる。ルールの適用を担うのが Claude Code だからだ。
「ドキュメント」から「Skill / Hook」
ドキュメントに書く運用は、「人が読んで、覚えて、守る」という前提に立っている。
この前提の弱いところは、守るためのコストがすべて人間の側に乗ってしまうことだ。読む時間も、覚える負担も、毎回思い出して適用するための注意力も、結局は人が払うことになる。新しいメンバーが増えれば、そのぶん全員が同じコストを払い直す。しかも人間は忘れるし、急いでいるときには手順を飛ばす。ルールが立派に書かれていることと、それが実際に守られていることは、まったく別の話になってしまう。
Skill と Hook での運用に移行すると、この「Claudeが呼んで、覚えて、守る」に代わる。
ルールを覚えて適用するのが人ではなく Claude Code になり、絶対に超えてはいけない一線を見張るのが人の注意力ではなく機械になる。新人は規約を暗記してから開発を始める必要がなくなる。「ログイン画面に入力チェックを足したい、Issue を立てて取りかかって」と目的だけ言えば、ブランチの切り方もコミットメッセージの形式も PR の紐付けも Claude Code が勝手に正しくやる。
| これまで(ドキュメント運用) | これから(Skill 運用) | |
|---|---|---|
| ルールの置き場所 | README / Wiki に散らばる | Skill / Hook に集約される |
| 守るのは誰か | 人(記憶と注意力) | AI(毎回自動で適用)と機械(commit 時に検査) |
| 事前に必要な知識 | 全ルールを読んで覚える | ほぼ不要(目的を伝えるだけ) |
| ミスしたとき | レビューで指摘 → やり直し | その場で Hook が止める/Skill が直す |
Skill はこれまでと同じ「自然言語のドキュメント」
「Skill に移す」と聞くと、ルールをプログラムに書き直す難しい作業を想像するかもしれない。そうではない。
Skill の中身は Markdown のテキストだ。これまで README に日本語で書いていた「コミットメッセージは type(scope): subject の形式で」という一文が、ほぼそのまま Skill の中の一文になる。実行コードは持たない。Claude Code がその文章を読んで振る舞いを変える。だから移行というより、書く場所と読み手が変わるだけと言ったほうが近い。これまで人に読ませていた文章を、これからは AI に読ませる。
保守も同じだ。ルールを変えたければ Markdown を書き換える。git で履歴が残るのも、PR でレビューするのも、これまでのドキュメント運用とまったく変わらない。実際 team-dev-kit の Skill は、移行元になった「人が読んで守る前提のルールドキュメント」を docs/legacy-manual-rules/ に保存してある。何を Skill に移し替えたのかを見比べられる。
具体的にどの文章がどの Skill / Hook になったかはこうだ。
| 旧ドキュメント(人が読む) | 置き換えた Skill / Hook(AI が運用) | 守られ方 |
|---|---|---|
| コミット規約 |
git-commit skill |
「コミットして」で正しい形を自動生成 |
| ブランチ運用・Issue/PR 運用 |
github-workflow skill |
ブランチ作成・Closes #N 紐付け・直 push 禁止を自動適用 |
| Issue 作成ガイド・テンプレート |
ticket-* skill 群 |
会話・計画から下書き生成 → 発行 |
| 設計ドキュメント記述ルール |
doc-writing skill |
設計文書の文体・構造を自動で適用 |
| 秘密情報取り扱いルール | pre-commit hook + PreToolUse hook(gitleaks) | commit 前・発行前に機械検査し、危険ならブロック |
Skill と Hook はどう使い分けるのか
team-dev-kit はルールを Skill だけで実装していない。一部を Hook に置いている。この線引きには理由がある。
Skill は自然言語の手続き指示で、Claude Code がそれを読んで「こう書きましょうか」と提案し、実行する。文脈によって正解が変わるもの、判断を伴うものに向く。たとえばコミットメッセージの scope に何を書くかは変更内容しだいで変わる。これを機械で固定の形に強制すると、かえって不自然なメッセージが量産される。だから Skill にして、AI に文脈を読ませて柔らかく決めさせる。ただし Skill が守られるかどうかは確率的だ。AI が指示を見落とす可能性はゼロではない。
Hook はそこが違う。commit や発行の瞬間に走る決定的なプログラムで、条件に合えば曖昧さなく止める。秘密情報の漏洩のように「一度でも通したら取り返しがつかない」一線に向く。ここを Skill で「気をつけてコミットしてね」と書いても、AI が見落とせば漏れる。人間が git commit する経路には、そもそも AI がいない。だから秘密情報のチェックは Skill ではなく Hook に置き、人間の commit(pre-commit)と Claude の外部発行(PreToolUse)の両方を機械で塞いでいる。
一言でいえば、正しいやり方に導くのが Skill、絶対に超えさせないのが Hook だ。確率的に効けば十分なものは Skill に、確定的に止めなければ困るものは Hook に置いている。
実例:目的を伝えるだけで開発が一周する
理屈を並べるより、実際に動いている様子を見せたほうが早い。team-dev-kit を導入済みの検証用リポジトリ sandbox-team-dev-kit で、実際に Claude Code へ依頼を投げたときの記録を紹介する。ブランチ運用もコミット規約も Issue と PR の紐付けも、こちらからは一切指示していない。伝えたのは「やりたいこと」だけだ。
渡したプロンプトはこれだ。
Rust で "Hello, World!" と標準出力するだけの小さなプログラムを作りたい。Issue を立てるところから、実装、PR 作成、マージまで一通りやってほしい。細かい進め方(ブランチ運用・コミット規約・Issue と PR の紐付け)はこのリポジトリのルールに従って。
この一文を投げただけで、Claude Code が自動でやってくれたことを順に挙げていく。
| 段階 | 自動でやったこと | 実物 |
|---|---|---|
| Issue 作成 | feature テンプレートに沿って作成 | #5 |
| ブランチ |
feature/5-rust-hello-world を作成(main 直接コミットなし) |
— |
| 実装 |
Cargo.toml / src/main.rs / .gitignore を生成し cargo run で検証 |
— |
| コミット | feat(hello-rs): Rust で "Hello, World!" を標準出力するサンプルを追加 |
— |
| PR 発行 | 本文に Closes #5 を入れ、Issue と双方向リンク |
#6 |
| マージ | squash マージ → Issue #5 が自動クローズ、ブランチも自動削除 | — |
type(scope): subject のコミット形式も、feature ブランチを切る運用も、Closes #N による Issue と PR の双方向リンクも、マージ時の Issue 自動クローズも、全部 Skill が裏で適用した結果だ。人間が覚えていたら毎回手で確認していた工程が、目的を伝えた時点で確定している。
ついでに秘密情報のガードも試した。本物に近いランダムな AWS キーらしき文字列をわざとコミットしようとしたところ、pre-commit hook が止めた。実際の出力がこれだ。
WRN leaks found: 1
✋ 秘密情報または個人情報の疑いを検出しました。コミットを中止します。
対応: 該当箇所を削除・マスキング・匿名化してから再コミットしてください。
誤検知の場合: .gitleaks.toml の [allowlist] に例示値を追加してください。
ここでひとつ注意しておきたい。AKIAIOSFODNN7EXAMPLE のようにドキュメントでよく使われる例示キーは、わざと素通りさせている。誤検知でいちいち止まると、かえって邪魔になるからだ。つまり「ブロックされない=壊れている」というわけではない。動作を試したいときは、本物に近いランダムな値を使ってほしい。
Quick Start
導入の手間は、あなたの立場で大きく変わる。すでに team-dev-kit が入っているリポジトリに参加しただけなら、ほぼ何もしなくていい。
git clone <リポジトリURL>
cd <リポジトリ>
このあと Claude Code を起動して Trust(信頼)を許可すれば、それで終わりだ。この時点でチームのルールはもう効いている。ちゃんと効いているか不安なときは、git config --local core.hooksPath(→ .githooks と出れば pre-commit が有効)と ls .claude/skills(→ git-commit などの skill が並ぶ)で確認できる。
自分のチームのリポジトリに初めて導入する場合だけ、一度だけの作業が要る。これはチームで誰か一人がやれば、以後の参加者は上の clone だけで済む。前提として git / python3 / gitleaks がインストール済みで、Claude Code が使えること。導入は、リポジトリのルートでブートストラップを一度実行するだけだ。
cd <リポジトリ>
curl -fsSL https://raw.githubusercontent.com/aRaikoFunakami/team-dev-kit/main/bootstrap.sh | sh
これで必要なファイルが、すべてこのプロジェクト配下だけに自動配置される($HOME には何も置かない。他プロジェクトに影響しない)。
.claude/skills/ ← 業務 skill(このプロジェクトでだけ有効)
.claude/settings.json ← PreToolUse 秘密情報フック
.team-dev-kit/ ← ルール本体 + egress スクリプト(編集禁止)
.githooks/ ← commit 時の自動検査
AGENTS.md ← プロジェクト固有ルールを書く場所(編集OK)
.gitleaks.toml ← 秘密情報の検出ルール(編集OK)
.github/ ← Issue / PR テンプレート(編集OK)
すでに独自の AGENTS.md や .gitleaks.toml がある場合も、あなたの記述はそのまま保持される。共通契約を読み込む @.team-dev-kit/contract.md(AGENTS.md)と、基盤検出ルールを継承する [extend](.gitleaks.toml)の繋ぎ込みだけが冪等に追記される(再実行しても重複しない)。全プロジェクトで効かせたいときだけ --global を付ける。
配置できたら動作確認する。次のように出れば導入完了だ。
$ git config --local core.hooksPath
.githooks
$ ls .claude/skills
doc-writing git-commit github-workflow ticket-draft ticket-publish ...
仕上げに、本物に近いランダムな秘密情報をわざと commit してみて pre-commit が止まれば、ガードレールも効いている(AKIAIOSFODNN7EXAMPLE のような例示キーは誤検知回避のため素通りする)。配置したファイルはチームへ共有する必要があるが、その commit & PR こそ、次に紹介する「目的を伝えるだけ」の流れで Claude Code に頼むのにちょうどいい最初の練習になる。
実装の詳細
ここまでで「何ができるか」は伝わったと思う。なぜこの形になっているか、配るものをどう層に分けているか、秘密情報チェックをなぜ二か所に置いているかといった設計の中身は、docs/architecture.md に書いてある。
ひとつだけ核心を引いておくと、この kit が配るものは「Claude Code に渡す道具(A層)」と「リポジトリに置いて人間の commit と GitHub に効かせるファイル(B層)」の二層に分かれている。A層は履歴に残したくない一方、B層は clone した全員のリポジトリに残らないと意味がない。要求が正反対なので、まとめずに最初から別々に配っている。この判断の経緯やトレードオフは architecture.md に詳しい。
カスタマイズ例:誤検知を黙らせる、独自ルールを足す
秘密情報スキャンを実運用に入れると、最初にぶつかるのが誤検知だ。team-dev-kit はこれを各プロジェクトが自分で調整できるようにしている。仕組みはこうだ。共通の検出ルールは .team-dev-kit/base.gitleaks.toml にあり、これは編集禁止(更新時に置き換えられる)。各プロジェクトはそれを継承([extend])した .gitleaks.toml に、自分の事情だけを足す。base は触らず、上に薄く重ねる。
ここに書く内容が本当に効くのか、実際に gitleaks 8.30.1 で動かして確かめた。題材は、base ルールがプライベート IP アドレスを個人情報として検出する挙動だ。
正しいのに止められるケースを許可する
社内ツールの README に、参照先となる NTP サーバの固定 IP 192.168.10.50 を書きたいとする。これは秘密でも何でもないのだが、base ルールはプライベート IP として拾ってしまう。starter のまま(allowlist なし)でスキャンすると、次のようになる。
$ gitleaks detect --no-git --source README.md -c .gitleaks.toml --redact
INF scanned ~80 bytes (80 bytes) in 22.5ms
WRN leaks found: 1
この状態では commit が止まる。そこで .gitleaks.toml に、このプロジェクトだけの許可を書き足す。
title = "secret & PII scan (project overlay)"
[extend]
path = ".team-dev-kit/base.gitleaks.toml"
[allowlist]
description = "社内ドキュメントに記載する固定の内部ホスト"
regexTarget = "match"
regexes = [
'''\b192\.168\.10\.50\b''',
]
同じファイルをもう一度スキャンすると、通る。
$ gitleaks detect --no-git --source README.md -c .gitleaks.toml --redact
INF scanned ~80 bytes (80 bytes) in 17.8ms
INF no leaks found
leaks found: 1 が no leaks found(終了コード 0)に変わった。base のルールはそのまま、この IP だけをピンポイントで許可している。ひとつ気をつけたいのは、192.168.10.50 のように具体値を狭く書くこと。192.168. のように広く許可すると、本当に隠したい内部アドレスまで素通りしてしまう。誤検知を消すたびに穴を最小にするのがコツだ。
このプロジェクトだけの秘密情報を検出する
逆方向のカスタマイズもできる。自社固有のトークン形式を検出に足す例を考える。ACME- で始まる 12 桁の社内サービストークンを拾いたいとする。overlay にルールを一本追加する。
title = "secret & PII scan (project overlay)"
[extend]
path = ".team-dev-kit/base.gitleaks.toml"
[[rules]]
id = "acme-internal-token"
description = "ACME 社内サービストークン"
regex = '''ACME-[A-Z0-9]{12}'''
service_token = ACME-7H3K9Q2M5P8W を含むファイルをスキャンすると、ちゃんと拾う。
$ gitleaks detect --no-git --source config.txt -c .gitleaks.toml --redact
INF scanned ~34 bytes (34 bytes) in 19.7ms
WRN leaks found: 1
base の標準ルール(API キー・秘密鍵など)はそのまま生きていて、その上にプロジェクト独自のルールが乗っている。共通の土台を全リポジトリで揃えつつ、各プロジェクトが自分の事情を足せる。この分離があるから、共通ルールを更新(ブートストラップを --force 付きで再実行)してもプロジェクト固有の調整は消えない。
cd <リポジトリ>
curl -fsSL https://raw.githubusercontent.com/aRaikoFunakami/team-dev-kit/main/bootstrap.sh | sh -s -- --force
--force は skill / framework / egress を最新版で置換するが、AGENTS.md や .gitleaks.toml などプロジェクト所有の config は既存をそのまま残す。
プロジェクト固有の規約そのもの(「このリポジトリでは API ドキュメントを必ず更新する」など)を足したいときは、AGENTS.md の「プロジェクト固有の規約」の節に日本語で書き足す。ここは team-dev-kit が触らない領域なので、更新で上書きされる心配なく書ける。共通ルールのほうを直したくなったら、その場で書き換えるのではなく、本体リポジトリへ Issue / PR を出して提案を戻す。マージされれば、各プロジェクトがブートストラップを再実行するだけで全リポジトリに広がる。
ルールを育てる:最低限の次に何を足すか
team-dev-kit が Skill / Hook にしているのは、チーム開発で「これだけは」という最低限のルールだけだ。
実際の案件では、ここをベースに各プロジェクトが自分の事情に合わせてルールを足していくことになる。では、何から足すといいのか。そして、足すときに Skill にするのか Hook にするのか。
足すときの判断は、記事前半とまったく同じ
新しいルールを足すときも、判断軸は変わらない。文脈で正解が変わる・判断を伴うものは Skill、絶対に超えさせたくない・確定的に止めたいものは Hook だ。追加とは、この線引きをもう一回やるだけのことだ。
何から足すか(効果が見えやすい順)
一般的なソフトウェア開発を念頭に、最低限の次に効くものを並べるとこうなる。
| 順 | 足すルール | Skill / Hook | 具体例 |
|---|---|---|---|
| 1 | lint / format | Skill(導く)+ Hook(強制) | commit 前に eslint / ruff / gofmt。自動修正できるものは Hook で確定的に強制 |
| 2 | テスト通過 | Hook(pre-push 寄り)+ Skill | push 前に cargo test など。重いので pre-commit より pre-push や CI が向く |
| 3 | コーディング規約・命名 | Skill | 「公開関数には docstring を書く」のように判断を伴うものは Skill |
| 4 | ドキュメント更新義務 | Skill | 「API を変えたら docs も更新する」 |
| 5 | 依存・ライセンス審査 | Hook | 禁止ライセンスの混入を機械検査(秘密スキャンと同じ型) |
| 6 | レビュー必須・承認数 | kit の外(GitHub branch protection) | これは Skill / Hook ではなく GitHub 側の設定で縛る |
最初に足すなら lint が定石だ。効果が目に見えてわかりやすいうえ、多くは自動修正できるので、ルールを足したときの摩擦がいちばん小さい。
ルールの追加(拡張のしかた)
-
Skill を足す: ルールを自然言語で 1 枚書くだけだ。実行コードは要らない。既存の
git-commitskill などと同じ形式で、プロジェクト固有ならAGENTS.mdの「プロジェクト固有の規約」に日本語で書き足せば、それだけで Claude Code が読んで効かせる。 -
Hook を足す: commit や push の瞬間に機械で止めたいものは Hook にする。ただし team-dev-kit が配る
.githooks/pre-commitは共通の framework(編集禁止・更新で置換される)なので、ここを直接いじるのではなく、プロジェクト側で lint やテストの hook を持つのが基本になる。team-dev-kit はあくまで土台で、案件ごとのコーディングルールは各プロジェクトがカスタマイズする、という分担だ。
具体例:コミット前に lint を通す(Skill + Hook の二段)
いちばん最初に足すであろう lint を例に、Skill と Hook を両方使う形を見せる。秘密情報ガードとまったく同じ二段構えだ。
Skill 側(導く) ―― AGENTS.md に一文足すだけでいい。
## プロジェクト固有の規約
- コードを変更したら、commit する前に lint をかける。失敗したら直してから commit する。
Hook 側(確定的に止める) ―― プロジェクトの pre-commit に lint ステップを足す。エラーが残れば commit を止める。
#!/bin/sh
# プロジェクト独自の lint ゲート(例: JS/TS なら eslint)
if ! npx eslint --max-warnings=0 $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.[jt]sx?$'); then
echo "✋ lint エラーが残っています。修正してから commit してください。"
exit 1
fi
なぜ両方なのか。Skill は「lint してね」と導くが、見落とす可能性はゼロではない(確率的)。Hook は人間が git commit する経路にも確定的に効く。秘密情報を Skill と Hook の二重で守っているのと、まったく同じ論法だ。導くのが Skill、最後に止めるのが Hook。
Hookを足しすぎない
最後にひとつ。Hook を増やしすぎると commit が遅く・うるさくなり、結局 --no-verify で外されて誰も使わなくなる。自動修正できる確定的なルールだけ Hook に、判断が要るものは Skill に――これが安全な線だ。誤検知を最小に保ち、摩擦を増やさないという姿勢は、秘密スキャンの allowlist を狭く書く話とまったく地続きになっている。team-dev-kit が最低限のルールしか持たないのも、同じ理由からだ。
おわりに
team-dev-kit がやっているのは、ルールを消すことでも、増やすことでもない。「誰がルールを守るコストを払うか」を、人から AI と機械へ移しただけだ。これまで新人が暗記し、レビュアーが毎回指摘し、全員が注意力で払っていたコストを、Claude Code と pre-commit hook が肩代わりする。
- 文脈で正解が変わるもの(コミット規約・PR 運用・文書の文体)は Skill が導く
- 越えてはいけない一線(秘密情報・個人情報の混入)は Hook が確定的に止める
- 新人は「やりたいこと」を言うだけでいい。ブランチ運用も
Closes #Nの紐付けも規約形式も、勝手に効く
逆に言えば、効くのは前提が噛み合うチームだけだ。Claude Code をチームで使っていて、規約が明文化されていて、複数人・複数リポジトリで同じルールを回している——そこでオンボーディング説明や規約違反の指摘を毎回繰り返しているなら、効果は大きい。一人の趣味リポジトリには、正直あまり意味がない。
試すのは難しくない。まずは1リポジトリのルートで bootstrap を実行し、その「team-dev-kit を入れた変更」自体を Claude Code に頼んで Issue → PR → マージしてみてほしい。仕組みが効いていることを、最初のコミットで体験できる。