parallel-setup
Skill1 starsChanged 58 days agoMITView on GitHub
並走 clone(worktree でない独立 clone を 4〜7 本)を役割別に立てる pattern と手順。 「parallel セットアップして」「並走環境について教えて」のような自然言語で起動。
- Reads credentials
- Deletes or force-pushes
In this repository27 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- add-hookSkill
- affected-area-testingSkill
- commit-workflowSkill
- create-issueSkill
- create-manualSkill
- create-prSkill
- debug-bar-investigationSkill
- documentation-standardsSkill
- edit-issueSkill
- handoffSkill
- large-feature-executionSkill
- livewire-v3-syntaxSkill
- pdf-readSkill
- pdfSkill
- playwright-error-detectionSkill
- pre-implementation-researchSkill
- questionnaireSkill
- resolve-issueSkill
- review-permissionsSkill
- review-prSkill
- route-managementSkill
- systematic-debuggingSkill
- tailwind-enforcementSkill
- tddSkill
- ui-approvalSkill
- writing-skillsSkill
The file
Files
並走開発環境(Parallel Development)
git worktree ではなく、独立した clone を複数(典型的に 4〜7 本)並走 させて、 role 別に作業を割り当てるパターン。docker-compose ベースの開発で特に有効。
本 skill はフレームワーク非依存です。考え方(命名規約・isolation・ 通知 hook の wiring 等)は docker-compose で動く任意のスタック(Node / .NET / Go / Rails / Laravel 等)に適用できます。本文中のコマンドは 素の
docker composeで書いていますが、Laravel Sail なら./vendor/bin/sail、その他のラッパーがあればそれぞれに読み替えてください。
なぜ worktree でなく独立 clone か
worktree は .git 本体 + 場合により vendor/ / node_modules/ / DB volume を
共有する設計。共有していると、ある clone で
- 破壊的マイグレーション
- 依存パッケージの大幅更新
- DB schema の実験
を試そうとした瞬間に他の clone が壊れる。
並走 clone は 完全独立。各 clone が独自の docker-compose stack を持ち、 ある clone での実験が他に波及しない。
代償:
- ディスク使用量増(並走数倍)
- メモリ使用量増(並走数分の DB コンテナ等)
- 同期作業が必要(一括 git pull / 再ビルド)
費用対効果が合う条件:
- 開発機が SSD 1TB クラス + RAM 32GB 以上
- 短期間に複数の異なる文脈(feature / hotfix / PoC)を切り替える必要がある
- DB / 依存 / インフラに破壊実験を伴う作業が出てくる
ディレクトリ命名規約
~/repos/
├── <project>-parallel-1/ # role: feature
├── <project>-parallel-2/ # role: hotfix
├── <project>-parallel-3/ # role: poc
├── <project>-parallel-4/ # role: issue-authoring
├── <project>-parallel-5/ # role: feature (本流 2 本目)
├── <project>-parallel-6/ # role: refactor
└── <project>-parallel-7/ # role: docs-curation(7本目以降は 6 ペイングリッド外 → Phase 4 参照)<project>-parallel-N 形式。同梱の permission-request-logger.py /
tmux-pane-awaiting.sh が -parallel-(\d+) でディレクトリ名から N を抽出する
設計。命名を変える場合は hook 側の正規表現も合わせて書き換える。
役割テンプレ (CLAUDE.local.md)
各 parallel に CLAUDE.local.md を置き、その clone の役割と運用ルールを宣言する。
役割例(自プロジェクトに合わせて取捨選択):
| 役割 | 用途 |
| feature | 通常の機能開発・改修・PR 作成。本流が忙しいときは複数 parallel に同じ feature 役割を割り当てて 2 本走らせることもある(上のツリー例の parallel-1 と parallel-5) |
| hotfix | 緊急バグ対応。最小 diff の原則 |
| poc | PoC・実験。マージしない前提、破壊的変更 OK |
| issue-authoring | Issue 起票・調査専用 |
| refactor | リファクタ専用 |
| docs-curation | ドキュメント整備専用 |
| reviewer | 他 parallel の PR レビュー専用 |
CLAUDE.local.md テンプレ:
## このワークスペースの役割
ここは **<役割>** の作業ディレクトリです。parallel-N。
### 開発URL
http://localhost:<port> # 例: parallel-1 なら http://localhost:8081
### 構成上の注意
- Compose Project 名: `<project><N>`
- ホスト側ポート: app=<app-port>, vite=<vite-port>, db=<db-port>
### 行動原則
- <役割固有のルールを書く>CLAUDE.local.md は git 管理外 (.gitignore) に置き、各 parallel 専用。
.local.md は Claude Code が CLAUDE.md と並んで読む「マシン別 / clone 別の
上書きファイル」用の命名 convention で、.gitignore に登録すれば各 parallel
で異なる内容を持てる。配布時に sed で <project><N> / <port> / <役割>
等のプレースホルダーを置換する想定。
Isolation のコツ
並走 clone が互いに干渉しないための要素を 4 点に整理:
1. COMPOSE_PROJECT_NAME を機械式に固定
各 parallel で <project><N> を使う(例: myapp1, myapp2, ...)。
推奨: .claude/settings.local.json の env.COMPOSE_PROJECT_NAME で設定。
{
"env": {
"COMPOSE_PROJECT_NAME": "myapp1"
}
}インライン指定(COMPOSE_PROJECT_NAME=... ./vendor/bin/sail ...)は同梱の
sail-env-inline-block.py hook がブロックする。インライン指定は
Bash(./vendor/bin/sail *) 等の permission rule にマッチせず毎回許可確認が
出るためで、settings.local.json で env 固定する方が摩擦が少ない。
2. ポート番号を機械式に割り当て
サービスごとにベースポートを決め、parallel 番号 N をオフセットとして 加える。例:
| parallel | APP_PORT (8080+N) | VITE_PORT (5270+N) | DB_PORT (3400+N) | MAILPIT_SMTP (1120+N) | MAILPIT_UI (8120+N) |
| 1 | 8081 | 5271 | 3401 | 1121 | 8121 |
| 2 | 8082 | 5272 | 3402 | 1122 | 8122 |
| 3 | 8083 | 5273 | 3403 | 1123 | 8123 |
| ... | ... | ... | ... | ... | ... |
各 parallel の .env / .env.testing をこのルールで機械式に生成する。
ベースポートは自プロジェクトのデフォルトに合わせる(上の例は Laravel Sail
の標準ポート APP_PORT=80 / VITE_PORT=5173 / FORWARD_DB_PORT=3306 を
それぞれ 8080+N / 5270+N / 3400+N 形式に置き換えたもの)。
3. .mcp.json は各 parallel で実体化
.mcp.json はプロジェクト直下に置く Claude Code の project-scope MCP
設定。Claude Code がセッション開始時に読み込み、その内容に従って MCP
サーバー群を起動する。中身には serena の --project <絶対パス> 引数や、
laravel-boost の env.COMPOSE_PROJECT_NAME=<projectN> のように
各 parallel で違う値 が含まれるため、リポジトリ追跡せず各 parallel
で実体化 する。
プロジェクトの .gitignore に以下を追記:
.mcp.jsonテンプレ .mcp.json.example のみ追跡し、各 parallel で cp + sed で
プレースホルダーを置換して生成:
sed \
-e "s|<ABSOLUTE_PATH_TO_THIS_PARALLEL>|/home/$USER/repos/myapp-parallel-1|g" \
-e "s|<COMPOSE_PROJECT_NAME>|myapp1|g" \
.mcp.json.example > .mcp.jsonテンプレ変更(.mcp.json.example 編集)は PR 経由で全 parallel に届くが、
.mcp.json 実体は各 parallel で個別に再生成する必要がある(git pull
だけでは更新されない)。
4. 役割テンプレに特定 N をハードコードしない
複数 parallel で同じ役割(例: parallel-1 と parallel-5 がどちらも feature)を
共用するときは、role-templates 内に COMPOSE_PROJECT_NAME=myapp1 のような
特定 N をハードコードしないこと。
これは事故の温床になる。実例: 共用テンプレに myapp1 がハードコードされて
いて、parallel-5 で Claude Code が CLAUDE.local.md を読んだ結果
COMPOSE_PROJECT_NAME=myapp1 docker compose down を parallel-5 のディレクトリで
実行し、parallel-1 のコンテナを意図せず停止する という事故が起きうる。
回避策: テンプレはプレースホルダー(<COMPOSE_PROJECT_NAME>、<APP_PORT> 等)
で書き、各 parallel に配布する時点で sed で具体値に置換する。
通知の wiring(tmux ペインボーダー + 通知音)
並走中に「どの parallel が完了したか」「どれがユーザー応答待ちか」を区別する 仕組みは、同梱の 2 つの hook + ランチャで構成する:
tmux-pane-awaiting.sh(視覚・tmux 限定)—tmux-grid.shで 6 ペイン グリッドを立てて並走する場合、発火ペインのボーダー色で状態を示す (応答待ち=赤 / 完了=緑 / 作業中=無印)。各ペインの statusline は最下部に 埋もれて「どのペインが呼んでいるか」が分かりにくいため、ボーダー側に出す。 tmux 外では何もしない。notify-sound.sh(音・クロスプラットフォーム)— Notification / PermissionRequest / Stop で通知音を鳴らす。WSL2 は powershell.exe で Windows 音、native Linux はpaplay/pw-play/ffplay/aplay。 再生手段が無ければ無音で no-op。tmux の有無に関わらず鳴る。
設定ポイント:
- 6 ペイングリッドの起動・ボーダー書式は
tmux-grid.sh側で定義する。DIR_PREFIX/NAME_PREFIX/PARALLELSを環境変数で自プロジェクトに 合わせて上書きする(後述 Phase 4 参照)。 - N の抽出は cwd の
-parallel-(\d+)に依存する。命名規約を変えるならtmux-pane-awaiting.sh/permission-request-logger.pyの正規表現も合わせる。 - Linux / macOS の音源は
CLAUDE_NOTIFY_SOUND環境変数で差し替えできる。
セットアップフロー
新規プロジェクトで初めて parallel を立てる場合の最小手順。
Phase 0: 前提確認
- Docker Desktop / Docker Engine が動く OS(本 skill の例は WSL2 + Docker Desktop を想定。Linux / macOS ネイティブでも動作する)
- ペイングリッド表示を使う場合は
tmux(tmux-grid.sh/tmux-pane-awaiting.sh) - 開発機のメモリ余裕(負荷時最大で 並走数 × 3GB 程度。idle 時はもっと少ない。 詳細は後述「メモリ使用量の目安」参照)
- ディスク余裕(並走数 × プロジェクトの clone サイズ)
Phase 1: 全 parallel の clone + 設定生成
各 parallel を for ループで一括生成 する。各イテレーションをサブ
シェル (...) で囲み、末尾に & を付けてバックグラウンド並列実行する。
N=1 を「先に動かして動作確認したい」ときは下記 for N in 1 2 3 4 5 6 7
を for N in 1 に絞って先に流すと良い。
cp -r ~/repos/<project>-parallel-1 ...で.gitごと複製する方法は、 remote tracking branch や git hooks の状態が共有されてしまう副作用がある ため非推奨。各 parallel は新規git cloneする方が安全。
PROJECT=myapp
REPO_URL=<repo-url>
for N in 1 2 3 4 5 6 7; do
(
# 新規 clone
git clone "${REPO_URL}" ~/repos/${PROJECT}-parallel-${N}
# Compose Project 名の固定
mkdir -p ~/repos/${PROJECT}-parallel-${N}/.claude
cat > ~/repos/${PROJECT}-parallel-${N}/.claude/settings.local.json <<EOF
{
"env": {
"COMPOSE_PROJECT_NAME": "${PROJECT}${N}"
}
}
EOF
# ポート番号を BASE_PORT + N で書き換え
cd ~/repos/${PROJECT}-parallel-${N}
sed -i "s|^APP_PORT=.*|APP_PORT=$((8080 + N))|" .env
sed -i "s|^VITE_PORT=.*|VITE_PORT=$((5270 + N))|" .env
sed -i "s|^DB_PORT=.*|DB_PORT=$((3400 + N))|" .env
# ... 他ポートも同様の式で
# .mcp.json の実体化(テンプレ .mcp.json.example から sed で生成)
sed \
-e "s|<ABSOLUTE_PATH_TO_THIS_PARALLEL>|$HOME/repos/${PROJECT}-parallel-${N}|g" \
-e "s|<COMPOSE_PROJECT_NAME>|${PROJECT}${N}|g" \
.mcp.json.example > .mcp.json
) &
done
waitサブシェル化により各イテレーションの cd は外側に漏れず、ループ終了時に
ユーザーは元のディレクトリに残る。
git サーバーへの並列 fetch に注意: 同じリポを 7 本同時に clone すると、 自前 git サーバーの rate-limit や GitHub の abuse detection に引っかかる 可能性がある。引っかかったら
) &を)に変更し末尾waitを削って シリアル実行に戻す。
Phase 2: 全 parallel の起動
各 parallel を直列に起動すると 1 つあたり 30〜90 秒、7 並走で 3〜10 分の シリアル実行になる。バックグラウンド並列起動 → 最後に一括で health 確認 する方が速い:
PROJECT=myapp
# 1. 全 parallel をバックグラウンドで起動(並列)
for N in 1 2 3 4 5 6 7; do
(cd ~/repos/${PROJECT}-parallel-${N} && docker compose up -d) &
done
wait
# 2. 全コンテナの health 状態をまとめて確認
docker ps --format 'table {{.Names}}\t{{.Status}}' \
| grep -E "^${PROJECT}[0-9]+-"(... ) & でサブシェル化してバックグラウンド実行、最後に wait で全完了
を待つ。docker daemon 側で並列にイメージビルド・コンテナ起動が走る。
Phase 3: 役割テンプレ配布
各 parallel に CLAUDE.local.md を配置する。テンプレ自体(プレースホルダー
入りの .md 雛形群)は プロジェクトリポの .claude/role-templates/
等に置く想定。役割テンプレ自体は branch 共有で全 parallel に届くが、
どの parallel にどの役割を割り当てるかは parallel 固有:
# 例: parallel-N に role 'feature' を割り当てる
ROLE=feature
sed \
-e "s|<COMPOSE_PROJECT_NAME>|${PROJECT}${N}|g" \
-e "s|<APP_PORT>|$((8080 + N))|g" \
-e "s|<役割>|${ROLE}|g" \
.claude/role-templates/${ROLE}.md > CLAUDE.local.mdCLAUDE.local.md は git 管理外(前述)なので、各 parallel で自由に書き
換えてよい。テンプレ側(role-templates/)を変更した場合は各 parallel
で再生成が必要(git pull だけでは CLAUDE.local.md は更新されない)。
Phase 4: tmux グリッドで一覧表示
並走中の視認性を上げるため、各 parallel を 1 つの tmux セッションの
3×2 グリッドで開く。同梱の tmux-grid.sh がこれを自動化する:
# DIR_PREFIX / NAME_PREFIX を自プロジェクトに合わせて起動
DIR_PREFIX=myapp-parallel NAME_PREFIX=myapp PARALLELS=6 ./tmux-grid.sh~/repos/<DIR_PREFIX>-Nの各 clone ディレクトリでペインを開き、claude --name <NAME_PREFIX>-Nを起動する- 各ペインのボーダーが
tmux-pane-awaiting.shにより状態を示す (応答待ち=赤 / 完了=緑 / 作業中=無印)ので、どのペインが呼んでいるか一目で分かる - グリッドは常に 3×2(6 ペイン)。
PARALLELSが 6 未満なら余りは空ターミナル - ペインID で位置を確定させているため、ターミナルの縦横比に関係なく必ず 3 列×2 行になる
tmux-grid.shが可視化できるのは最大 6 ペイン。推奨の「4〜7 本」運用などで 7 本目以降を立てる場合、その clone は グリッド外(tmux-grid.shでは開かれない)。 グリッド外でもclaudeは通常どおり動作しnotify-sound.shの音通知は鳴るが、 ペインボーダー通知(tmux-pane-awaiting.sh)は出ない。ボーダー書式 (pane-border-format)はtmux-grid.shが作る 6 ペインセッションにのみ設定される ため、別ターミナル / 別 tmux セッションで起動した 7 本目には反映されない (6 ペイン上限は、グリッドの位置確定設計を保つため意図的に固定)
Phase 5: 動作確認
各 parallel が isolation されていることを機械的に確認:
PROJECT=myapp
# 1. 各 parallel が割り当てたポートで応答する
for N in 1 2 3 4 5 6 7; do
PORT=$((8080 + N))
echo -n "parallel-${N}: "
curl -sI -o /dev/null -w "http://localhost:${PORT} → %{http_code}\n" \
"http://localhost:${PORT}"
done
# 2. 全 parallel のコンテナが見える
docker ps --format '{{.Names}}' | grep -E "^${PROJECT}[0-9]+-"
# 3. isolation テスト: 適当な 1 parallel を止めても他は動く
TARGET_N=3 # 検証対象(自由に選ぶ)
EXPECTED=$(docker ps --filter "name=${PROJECT}${TARGET_N}-" -q | wc -l)
BEFORE=$(docker ps -q | wc -l)
(cd ~/repos/${PROJECT}-parallel-${TARGET_N} && docker compose stop)
AFTER=$(docker ps -q | wc -l)
DIFF=$((BEFORE - AFTER))
echo "停止前: ${BEFORE} 件、停止後: ${AFTER} 件、差分: ${DIFF}"
echo "期待値: ${EXPECTED}(parallel-${TARGET_N} のコンテナ数)"
[ "${DIFF}" -eq "${EXPECTED}" ] && echo "✅ isolation OK" || echo "❌ 想定外: 他 parallel に影響が出ている"運用 Tips
master / main 直接 push 禁止 + PR フロー徹底
並走中は どの parallel でどのブランチを触っているか が混乱の元。
master / main への直 push は禁止し、必ず PR 経由でマージするルールを敷く。
同梱の git-push-merged-pr-check.py hook が「MERGED PR を持つ branch への
追加 push」をブロックする。
parallel 切替前の clean 確認
ある parallel に入る前に必ず git status で clean 確認、どのブランチに
いるかを確認する習慣。feature/hotfix 作業中の parallel に間違って入って
別ブランチを切ると、後で「あれ、この変更はどの parallel で作ったんだっけ」
となる。
docker compose down -v 禁止
-v オプションは named volume を削除する。共有 DB(後述)を持つ構成では
他 parallel のデータを巻き込んで消し飛ばす事故になる。停止は
docker compose stop または docker compose down(オプションなし)のみ。
共有 DB の扱い
各 parallel で完全独立 DB を持つ前提なら、自 parallel 内では破壊操作
(migrate:fresh / TRUNCATE / DROP DATABASE)は自由。
共有 DB(例: 共通マスタを別コンテナで持つ場合)を持つ構成では、共有 DB に 対する破壊操作は禁止。共有 DB を持つ構成は 共有 DB 専用コンテナ + 各 parallel 専用コンテナ の二段配置にすると安全:
<shared>-db ← 全 parallel で共有(マスタデータ等)
<project>1-db ← parallel-1 専用(トランザクション・実験データ)
<project>2-db ← parallel-2 専用
...メモリ使用量の目安
実測値はプロジェクト構成(DB / app のメモリプロファイル)に大きく依存 する。Laravel + MySQL + 共有 SQL Server 構成での観測例: 7 並走で idle 時 総コンテナメモリ 1〜3GB、負荷時に parallel あたり 3GB 程度。WSL2 の 総メモリ予算が 64GB の環境なら余裕がある。
自プロジェクトでは初回構築後に docker stats で実測し、並走数の上限を
逆算すること。
create-pr / review-pr の worktree と serena のメモリ肥大
create-pr / review-pr はレビュー用に各リポの .claude/worktrees/agent-*
に一時 git worktree(リポ丸ごと + vendor/ 等の複製)を作る。これが
serena の index 対象に入ると、worktree 数に比例して serena プロセスの
メモリが膨張し OOM を誘発する(観測例: worktree 7 個で serena 単体 6.6GB
→ swap 枯渇 → OOM kill)。二段で除外する:
machine 単位(主・全プロジェクトに効く):
~/.serena/serena_config.ymlのignored_pathsに worktree パターンを追加。global のignored_pathsは 各プロジェクトに加算適用され、project.ymlが serena 起動時に自動 再生成されても影響を受けない。ignored_paths: - "**/.claude/worktrees/**" # 任意階層配下の worktree を網羅(主) - ".claude/worktrees" # ルート直下ケースの保険(任意。1 行目で概ね網羅されるため省略可)(README の例は 1 行目のみに簡略化している。実用上は 1 行目で足り、 2 行目はディレクトリ実体マッチの保険。)
repo 単位(従・belt-and-suspenders): 各 parallel の
.gitignoreに追加。 per-repo 任せだと repo ごとに設定が漏れるため、machine 単位を主とする。.claude/worktrees/
既存環境への反映(既存の汚染キャッシュは必ず purge する): ignored_paths の
追記は今後の index 対象を絞るだけで、追記前に worktree を index 済みのリポには
肥大した .serena/cache/ がそのまま残る。serena は起動時にこの既存キャッシュ
(document_symbols.pkl 等)をメモリへ展開し、キャッシュがある限り cold index
(再構築)は走らないため、serena を再起動するだけではメモリは解放されない
(肥大した pkl を再ロードしてしまう)。したがって汚染リポでは cache の purge が
必須(ディスク回収のためではなくメモリ解放のため)。.serena/cache/ は派生データ
なので、削除して失われるのは index キャッシュのみ(次回 index で ignored_paths
準拠の小さなキャッシュに再構築される)。
手順は必ず「停止 → 削除 → 起動」の順で行う:
各 parallel リポの cache サイズを比較し、桁違いに大きい outlier(= 汚染キャッシュ)を特定:
ここで対象にするのは 各 parallel clone 直下の
.serena/cache(= 親リポが.claude/worktrees/配下を index して肥大したキャッシュ)であり、worktree ディレクトリ内部ではない点に注意。for d in ~/repos/*-parallel-*; do [ -d "$d/.serena/cache" ] && printf '%s\t%s\n' "$(du -sh "$d/.serena/cache" | cut -f1)" "$d" done | sort -h- 汚染リポの serena を 停止 →
rm -rf <repo>/.serena/cache→ 起動する(<repo>は 手順 1 の outlier の絶対パス)。停止を先にするのは、in-memory の肥大分が再起動でしか 解放されないことに加え、万一 serena が停止時に cache を flush する実装でも削除が 無効化されないようにするため(安全側)。
異常終了 (harness ごとの落ち) で残った過去セッションの孤児 worktree は、
review-pr Step 8 の防御的 sweep が次回実行時に掃除する。
並走数の上限
ディスクとメモリの制約で 8〜10 が現実的。それを超えると Docker のネット ワーク(特に external network)が増え過ぎて管理が破綻する。役割と並走数を 最初に決めてから着手することを推奨。
parallel 削除の手順
不要になった parallel は以下の順で削除:
# 1. コンテナ停止 + 削除
cd ~/repos/<project>-parallel-N
docker compose down # -v は付けない
# 2. ディレクトリ削除
cd ~
rm -rf ~/repos/<project>-parallel-N
# 3. tmux グリッドを使っている場合は該当ペインを閉じる
# (または tmux-grid.sh の PARALLELS を調整して開き直す)注意事項
- 本 skill は 方法論を説明するもの。具体的な構築スクリプトは自プロジェクト 固有なので、本 skill は雛形を示すだけ
- 完全な自動化スクリプトを作るなら、プロジェクト側に
docs/parallel-setup-runbook.mdのような手順書を別途用意する(本 skill 名と同名docs/parallel-setup.mdは紛らわしいので避ける) - ペインボーダー通知(
tmux-pane-awaiting.sh)は tmux 6 ペイングリッド運用が 前提。tmux を使わない場合や、6 を超える parallel(7 本目以降)はグリッド外と なり、音通知(notify-sound.sh)のみになる
関連 skill / hook
tmux-pane-awaiting.shhook +tmux-grid.sh(同梱)— 並走ペインのボーダーで応答待ち/完了を表示notify-sound.shhook(同梱)— クロスプラットフォームな通知音sail-env-inline-block.pyhook(同梱)— COMPOSE_PROJECT_NAME のインライン 指定を blockgit-push-merged-pr-check.pyhook(同梱)— MERGED PR ブランチへの追加 push を block
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

