4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude CodeとCodexでskills・rulesを一元管理する

4
Last updated at Posted at 2026-07-14

はじめに

AIコーディングエージェントが増えて、同じskillsやrulesを複数の場所に置いていませんか?
更新するたびに全部直す運用では、どこかが古いまま残ります。

5人ほどの開発チームで、この問題に直面しました。
Claude Codeを使うメンバーもいれば、Codexを使うメンバーもいます。
同じファイルをエージェントごとにコピーする運用は、更新箇所を増やすだけでした。

そこで、実体を.agentsへまとめました。
skillsはsymlinkで共有できますが、rulesはCodex側に接続部分が必要です。

この記事では、pathsのないrulesをセッション開始時に読み込み、pathsのあるrulesを対象ファイルに応じて絞り込むところまで扱います。

結論

実体と参照方法を整理すると、次の構成になります。

対象 実体 Claude Code Codex
skills .agents/skills .claude/skillsからsymlink 直接読む
常時読む指示 AGENTS.md CLAUDE.mdからsymlinkまたはimport 直接読む
pathsのないrules .agents/rules .claude/rulesからsymlink SessionStartで読み込む
pathsのあるrules .agents/rules .claude/rulesからsymlink resolverで対象パスと照合する

実体を.agentsへ集約し、Claude CodeとCodexから参照する構成

skillsとrulesの実体を.agentsへ集約し、各エージェント固有の方法で参照する構成。画像をクリックすると拡大できます。

共通化の目的は、すべてのエージェントに同じディレクトリ名を読ませることではありません。
編集する実体を1箇所にして、エージェントごとの差を薄い接続部分へ閉じ込めることです。

skillsはsymlinkで共有する

Codexは、リポジトリの.agents/skillsとユーザーの~/.agents/skillsを読みます。
Claude Codeのプロジェクトskillsは.claude/skillsです。

そこで、実体を.agents/skillsに置き、Claude Code側からディレクトリごと参照します。

プロジェクトルート/
├── .agents/
│   └── skills/              # 実体
└── .claude/
    └── skills -> ../.agents/skills

新しく作る場合は、プロジェクトルートで次を実行します。

ln -s ../.agents/skills .claude/skills

Claude Codeはskillディレクトリのsymlinkをサポートしています。
Codexは.agents/skillsを直接読むため、以降は.agents/skillsだけを編集すれば両方へ反映されます。

AGENTS.mdとCLAUDE.mdも実体を揃える

プロジェクト全体で常に読ませたい指示は、CodexではAGENTS.md、Claude CodeではCLAUDE.mdに置きます。
ここもコピーは不要です。

プロジェクトルート/
├── AGENTS.md                # 実体
└── CLAUDE.md -> AGENTS.md
ln -s AGENTS.md CLAUDE.md

Claude Code専用の追記が必要なら、symlinkではなくCLAUDE.mdからimportします。

@AGENTS.md

# Claude Codeだけの指示

- ...

この併用方法は、Claude Codeの公式ドキュメントでも案内されています。

rulesは接続方法が異なる

Claude Codeは.claude/rules/*.mdを読み、YAML frontmatterのpathsで対象ファイルを絞れます。
pathsのないrulesはセッション開始時に読み込まれます。
rulesディレクトリのsymlinkも公式にサポートされています。

.agents/rules/  # 実体
.claude/rules -> ../.agents/rules

Codexの.codex/rulesへ同じMarkdownを置くことはできません。
.codex/rules/*.rulesは、コマンドをsandbox外で実行してよいか制御するための仕組みです。
Claude Codeの.claude/rules/*.mdとは、役割も形式も異なります。

この差を、Codex Hooksとresolverで吸収します。

pathsのないrulesはSessionStartで読み込む

Codex HooksのSessionStartは、startupresumeclearcompactで実行できます。
hookが返したadditionalContextは、追加の開発者向けコンテキストとしてCodexへ渡されます。

このタイミングで.agents/rulesを走査し、frontmatterにpathsがないrulesの本文を返します。

SessionStart
    └── .agents/rules/*.mdを走査
          ├── pathsなし:本文をadditionalContextへ追加
          └── pathsあり:この時点では追加しない

.codex/hooks.jsonでは、次のようにhookを登録します。

{
  "description": "Load shared workspace rules for Codex.",
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup|resume|clear|compact",
        "hooks": [
          {
            "type": "command",
            "command": "node \"$(git rev-parse --show-toplevel)/.codex/hooks/session-start-rules.mjs\"",
            "statusMessage": "Loading workspace rules"
          }
        ]
      }
    ]
  }
}

プロジェクト配下のhookは、信頼済みのリポジトリでのみ動きます。
追加後は、新しいセッションを開始して/hooksから登録内容を確認します。

SessionStart hookの実装

session-start-rules.mjsはresolverを呼び、pathsのないrulesをadditionalContextとして返します。

#!/usr/bin/env node

import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { resolveRules } from '../../.agents/scripts/resolve-rules.mjs'

const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..')

let input = ''
for await (const chunk of process.stdin) input += chunk
JSON.parse(input || '{}')

const rules = await resolveRules(repositoryRoot)
const contents = rules
  .map(({ name, body }) => `## .agents/rules/${name}\n\n${body}`)
  .join('\n\n')

const instruction = [
  '以下はpaths指定のない常時適用規則です。作業前にすべて従ってください。',
  '出力が上限でファイルへ退避された場合は、そのファイルを全文読んでから作業してください。',
  '対象パスが判明したら `node .agents/scripts/resolve-rules.mjs --paths <対象パス...>` を実行し、追加規則も確認してください。',
].join('')

process.stdout.write(JSON.stringify({
  hookSpecificOutput: {
    hookEventName: 'SessionStart',
    additionalContext: `${instruction}\n\n${contents}\n\n${instruction}`,
  },
}))

指示を本文の前後へ置いているのは、hook出力が長い場合への対策です。
Codexはモデルから見えるhook出力を約2,500トークンに制限し、超過分を一時ファイルへ保存して先頭と末尾のプレビューを渡します。
そのため、規則が多いリポジトリでは、Codexに保存先の全文を読ませる必要があります。

pathsのあるrulesはresolverで絞り込む

たとえば、次のruleがあるとします。

---
paths:
  - 'apps/*/src/**/*.tsx'
---

# UIルール

- UI部品は共通パッケージから利用する

編集対象がapps/client/src/pages/users.tsxなら、このruleが一致します。
resolverは、対象パスを--paths以降で受け取ります。

node .agents/scripts/resolve-rules.mjs \
  --paths \
  apps/client/src/pages/users.tsx

resolverの責務は次の3つです。

  1. .agents/rules/*.mdを読み込む
  2. YAML frontmatterのpathsを解析する
  3. 対象パスとglobが一致したrulesだけを標準出力する

--pathsを付けない場合は、pathsのないrulesだけを返します。
--pathsを付けた場合は、一致したパス別rulesだけを返します。
開始時に読んだ常時規則を再出力しないため、同じ本文でコンテキストを増やさずに済みます。

YAMLとglobを独自実装する場合は、配列、複数行、***.{ts,tsx}など、リポジトリで使う記法をテストしてください。
設定ファイルを正しく解析する必要があるなら、YAMLとglobの既存ライブラリを使うほうが安全です。

PreToolUseだけでは最初の編集に間に合わない

現在のCodex HooksにはPreToolUseがあり、shell、apply_patch、MCPなどの呼び出しを検知できます。
additionalContextを返すことも、ツール呼び出しを拒否することもできます。

ただし、PreToolUseが動く時点では、モデルは最初の編集内容をすでに生成しています。
追加規則を返すだけでは、その編集内容を規則に合わせて作り直せません。

最初の編集より前にパス別rulesを強制したい場合は、未読のruleがある編集をPreToolUseで拒否し、ruleを読んだ後に再実行させる設計が必要です。
公式ドキュメントもtool hookを完全な強制境界ではなく、補助的な防護として扱うよう説明しています。

必ず作業開始前から守らせたい規則は、AGENTS.mdへ置くほうが単純です。
パス別rulesは、対象外の作業へ余計な指示を混ぜないための補助として使います。

resolverをテストする

最低限、次の3ケースを固定します。

  • pathsを付けない実行では、常時規則だけを返す
  • 対象パスに一致するパス別rulesだけを返す
  • 対象パスに一致しないrulesは返さない

Node.jsの組み込みテストを使う場合は、次のコマンドで検証できます。

node --test .agents/scripts/resolve-rules.test.mjs

hook本体は、標準入力を渡してJSONを解析できることまで確認します。

printf '{"source":"startup"}' \
  | node .codex/hooks/session-start-rules.mjs \
  | jq -e '.hookSpecificOutput.hookEventName == "SessionStart"'

最終的な構成

プロジェクトルート/
├── .agents/
│   ├── skills/                       # skillsの実体
│   ├── rules/                        # rulesの実体
│   └── scripts/
│       ├── resolve-rules.mjs         # Codex用resolver
│       └── resolve-rules.test.mjs
├── .claude/
│   ├── skills -> ../.agents/skills
│   └── rules  -> ../.agents/rules
├── .codex/
│   ├── hooks.json
│   └── hooks/
│       └── session-start-rules.mjs
├── AGENTS.md                         # 常時読む共通指示
└── CLAUDE.md -> AGENTS.md

Windowsでsymlinkを復元するには、開発者モードなどの設定が必要です。
設定を揃えにくいチームでは、CLAUDE.md@AGENTS.md importなど、symlinkを使わない接続方法も選べます。

実体と接続部分を分ける

skillsはsymlinkで共有できます。
常時読む指示はAGENTS.mdへまとめられます。
rulesは.agents/rulesを実体とし、Claude Codeはsymlink、Codexはhookとresolverから参照します。

エージェントごとに違うのは、実体へつなぐ接続部分だけです。
規則の本文を直す場所は.agentsの1箇所に絞れます。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?