Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .agents/skills/manage-agent-config/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: manage-agent-config
description: Use whenever creating, editing, renaming, or deleting any file under .claude/skills/, .claude/agents/, .agents/skills/, or .codex/agents/. Teaches the dual-tool Claude/Codex layout and reminds to run `make sync-agent-config`.
---
Comment thread
Miyamura80 marked this conversation as resolved.

# Managing Claude ↔ Codex skills and subagents in this repo

This repo is dual-tool. Before you create or edit anything under `.claude/`, `.agents/`, or `.codex/`, read this and the detailed rule at `.claude/rules/codex-claude-sync.md`.

## Decision tree

**Creating a new skill?**

1. Does it need Claude-only features (`allowed-tools`, `$ARGUMENTS`, `` !`shell` `` preprocessing, `${CLAUDE_SKILL_DIR}`)?
- **Yes** → `.claude/skills/<name>/SKILL.md` (real directory, no symlink). Claude-only.
- **No** → `.agents/skills/<name>/SKILL.md`. Shared; `make sync-agent-config` creates the `.claude/skills/<name>` symlink.

**Creating a new subagent?**

- Always edit `.claude/agents/<name>.md` (markdown + YAML frontmatter). That is the source of truth.
- `.codex/agents/<name>.toml` is **generated** - never hand-edit.
- Run `make sync-agent-config` - the TOML appears.

**Renaming or deleting?**

- Rename or delete the source file (under `.agents/skills/` or `.claude/agents/`).
- Run `make sync-agent-config` - stale symlinks and orphaned TOMLs are pruned automatically.

## Frontmatter rules for shared skills

`.agents/skills/<name>/SKILL.md` must only use:

- `name` (required, lowercase-hyphens, ≤64 chars)
- `description` (required, ≤250 chars - Codex and Claude use this for implicit matching)
- Plain markdown body

Do **not** use any of these in a shared skill:

- `allowed-tools`, `disable-model-invocation`, `user-invocable`, `context`, `agent`, `model`, `effort`, `hooks`, `paths`, `shell`, `argument-hint`
- `$ARGUMENTS`, `$1`…`$N`, `${CLAUDE_SKILL_DIR}`, `${CLAUDE_SESSION_ID}` substitutions
- `` !`cmd` `` or ```` ```! ```` shell preprocessing blocks

All of those are Claude-only. In Codex they pass through literally and confuse the model. If you need them, make the skill Claude-only (see decision tree above).

## Subagent format notes

Claude `.md` frontmatter keys that don't exist in Codex (`tools`, `model`, `color`) are preserved as TOML comments in the generated `.codex/agents/<name>.toml` for human reference. They do not affect Codex behavior. If tool restrictions matter to the agent's job, describe them in the prose body so both tools read them.

## After any change

Always run `make sync-agent-config`. The prek pre-commit hook will block the commit otherwise. The script is idempotent and silent when there's nothing to do.
77 changes: 77 additions & 0 deletions .claude/rules/codex-claude-sync.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
paths:
- ".claude/skills/**"
- ".claude/agents/**"
- ".agents/skills/**"
- ".codex/agents/**"
---

# Codex ↔ Claude skill & subagent sync

This repo is dual-tool: both Claude Code and Codex CLI are expected to work. Skills and subagents are shared where possible. Read this before creating, editing, or moving any skill or subagent in this repo.

## Layout

```
.agents/skills/<name>/SKILL.md # single source - both tools auto-discover
.claude/skills/<name> # symlink -> ../../.agents/skills/<name>
.claude/agents/<name>.md # source of truth (markdown + YAML frontmatter)
.codex/agents/<name>.toml # GENERATED from the .md; commit it
scripts/sync_agent_config.py # converter (uv run)
```

Codex auto-scans `.agents/skills/` walking up from cwd to repo root. Claude auto-scans `.claude/skills/`. The symlink is the only reason both find the same file.

## Skills: the shared-frontmatter rule

Every `SKILL.md` under `.agents/skills/` MUST be readable by both tools. The overlap is narrow - stick to it:

**Always safe (both tools):**
- `name` - required, lowercase-hyphens, ≤64 chars
- `description` - required, ≤250 chars, written for implicit matching
- Plain markdown body

**Claude-only - DO NOT use in shared skills:**
- `allowed-tools:` - Codex has no equivalent
- `context: fork`, `agent:`, `model:`, `effort:`, `hooks:`, `paths:`, `shell:`, `argument-hint`, `disable-model-invocation`, `user-invocable`
- `$ARGUMENTS`, `$1`, `$2`, ... - Claude substitutes these at runtime; Codex passes them through literally
- `` !`shell command` `` and ```` ```! ```` blocks - Claude preprocesses; Codex does not
- `${CLAUDE_SKILL_DIR}`, `${CLAUDE_SESSION_ID}` - Claude-only interpolations

**Codex-only - OK to include (Claude ignores unknown keys):**
- Sibling `agents/openai.yaml` for Codex UI metadata, invocation policy, tool dependencies

If a skill genuinely needs Claude-only features, keep it at `.claude/skills/<name>/` as a real directory (no symlink) and do not mirror it to `.agents/skills/`. Note this with a `<!-- claude-only -->` comment at the top of the body.

## Subagents: convert, don't symlink

The formats are structurally different:
- Claude: `.claude/agents/<name>.md` - YAML frontmatter (`name`, `description`, `tools`, `model`) + markdown body as system prompt
- Codex: `.codex/agents/<name>.toml` - TOML with `name`, `description`, `developer_instructions = """..."""` (body as triple-quoted string)

Rules:
- `.claude/agents/*.md` is the **source of truth**. Never hand-edit `.codex/agents/*.toml`.
- Run `make sync-agent-config` after editing a subagent. The pre-commit hook will refuse the commit if the generated TOML is out of date.
- Claude-only frontmatter keys (`tools`, `model`) don't translate - document tool expectations in the prose body instead so both sides pick them up.
- Inside the body, avoid literal `"""` sequences (they'd close the TOML string); the converter escapes them but it's easier to just not use them.

## Do not try to sync these

- `.claude/rules/*.md` vs `.codex/rules/*.rules` - different languages (prose vs permission DSL). Maintain separately.
- `.claude/commands/*.md` - Claude-only; Codex has no slash-command runtime.
- `CLAUDE.md` vs `AGENTS.md` - both auto-read by their respective tool; keep them as separate documents, though content may overlap.

## Tooling

- `make sync-agent-config` - idempotent. Creates missing `.claude/skills/` symlinks for every shared skill under `.agents/skills/`, regenerates `.codex/agents/*.toml` from `.claude/agents/*.md`, auto-prunes dangling symlinks and orphan TOMLs silently.
- Pre-commit: [`prek`](https://prek.j178.dev/installation/), configured in `prek.toml` at repo root. Register once per clone with `prek install`. Runs `make sync-agent-config` then fails the commit if it produced drift.
- Python scripts in `scripts/` use `uv` and PEP 723 inline metadata for standalones.

## When adding a new skill or subagent

The `manage-agent-config` skill (at `.agents/skills/manage-agent-config/`) has the full decision tree and is invoked automatically when an agent touches any of these directories. The short version:

1. Shared skill (works in both tools) → `.agents/skills/<name>/SKILL.md`. Run `make sync-agent-config`.
2. Claude-only skill (uses `$ARGUMENTS`, `allowed-tools`, etc.) → `.claude/skills/<name>/SKILL.md` as a real directory. No symlink.
3. Subagent → edit `.claude/agents/<name>.md`. Never hand-edit `.codex/agents/*.toml`. Run `make sync-agent-config`. Commit both files.
4. Delete or rename → edit/remove the source, then `make sync-agent-config` cleans up the mirror.
1 change: 1 addition & 0 deletions .claude/skills/manage-agent-config
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ docs: ## Run docs with bun
@cd docs && bun run dev
@echo "$(GREEN)✅ Docs run completed.$(RESET)"

.PHONY: sync-agent-config
sync-agent-config: ## Sync Claude ↔ Codex skills & subagents (regenerates symlinks and .codex/agents/*.toml)
@uv run scripts/sync_agent_config.py

ralph: check_jq ## Run Ralph agent loop
@echo "$(RED)⚠️ WARNING: Ralph is an autonomous agent that can modify your codebase.$(RESET)"
@echo "$(RED)⚠️ It is HIGHLY RECOMMENDED to run Ralph in a sandboxed environment.$(RESET)"
Expand Down
1 change: 1 addition & 0 deletions prek.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ hooks = [
{ id = "ruff-tech-debt", name = "Check TODO/FIXME markers", entry = "uv run ruff check --select FIX", language = "system", pass_filenames = false, always_run = true },
{ id = "pylint-duplicate-code", name = "Detect duplicate code", entry = "uv run pylint --disable=all --enable=R0801 src common utils", language = "system", pass_filenames = false, always_run = true },
{ id = "ai-writing-check", name = "AI writing check", entry = "uv run python scripts/check_ai_writing.py", language = "system", pass_filenames = false, always_run = true },
{ id = "sync-agent-config", name = "sync Claude ↔ Codex skills & subagents; fail if drift was fixed", entry = "uv run scripts/sync_agent_config.py --check", language = "system", pass_filenames = false, always_run = true },
]
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies = [
"typer",
"questionary",
"rich>=14.3.1",
"tomli-w>=1.0",
]
readme = "README.md"
requires-python = ">= 3.12"
Expand Down Expand Up @@ -62,6 +63,9 @@ max-complexity = 10

[tool.ty]

[tool.ty.src]
exclude = ["scripts/sync_agent_config.py"]

[tool.ty.rules]
possibly-unresolved-reference = "error"

Expand Down
Loading
Loading