mirror of
https://github.com/itme-brain/agent-team.git
synced 2026-05-08 09:30:13 -04:00
feat: add Codex CLI compatibility layer
- flake.nix: devShell with yq-go for config generation - generate-codex.sh: generates Codex agent TOML, AGENTS.md, and config.toml from Claude source files (idempotent, yq-powered) - install.sh: optional Codex symlinks when ~/.codex exists (skills shared via ~/.agents/skills/, agents/config/AGENTS.md to ~/.codex/) - .gitignore: exclude generated codex/ directory - README.md: document Codex compatibility setup and model mapping
This commit is contained in:
parent
8d08f9650c
commit
d812c7f49a
6 changed files with 287 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -8,3 +8,6 @@ settings.local.json
|
|||
# OS noise
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Generated Codex CLI config (derived from Claude source files via generate-codex.sh)
|
||||
codex/
|
||||
|
|
|
|||
29
README.md
29
README.md
|
|
@ -59,6 +59,35 @@ For simple tasks, agents can be invoked directly:
|
|||
/agent worker Fix the broken pagination in the user list endpoint
|
||||
```
|
||||
|
||||
## Codex CLI compatibility
|
||||
|
||||
This project also generates configuration for [OpenAI Codex CLI](https://github.com/openai/codex). Claude Code config is the source of truth; Codex config is derived from it.
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
nix develop # enter devShell with yq
|
||||
./generate-codex.sh # generate Codex config from Claude source files
|
||||
./install.sh # installs both Claude and Codex (if ~/.codex exists)
|
||||
```
|
||||
|
||||
### What gets generated
|
||||
|
||||
| Source | Generated | Codex location |
|
||||
|---|---|---|
|
||||
| `agents/*.md` | `codex/agents/*.toml` | `~/.codex/agents/` |
|
||||
| `CLAUDE.md` + `rules/*.md` | `codex/AGENTS.md` | `~/.codex/AGENTS.md` |
|
||||
| `settings.json` | `codex/config.toml` | `~/.codex/config.toml` |
|
||||
| `skills/` | (shared as-is) | `~/.agents/skills/` |
|
||||
|
||||
### Model mapping
|
||||
|
||||
| Claude Code | Codex CLI |
|
||||
|---|---|
|
||||
| `opus` | `o3` |
|
||||
| `sonnet` | `o4-mini` |
|
||||
| `haiku` | `o4-mini` |
|
||||
|
||||
## Project-specific config
|
||||
|
||||
Each project repo can extend the team with local config in `.claude/`:
|
||||
|
|
|
|||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1775095191,
|
||||
"narHash": "sha256-CsqRiYbgQyv01LS0NlC7shwzhDhjNDQSrhBX8VuD3nM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "106eb93cbb9d4e4726bf6bc367a3114f7ed6b32f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
14
flake.nix
Normal file
14
flake.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
outputs = { nixpkgs, ... }:
|
||||
let
|
||||
systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
|
||||
in {
|
||||
devShells = forAllSystems (pkgs: {
|
||||
default = pkgs.mkShell {
|
||||
packages = [ pkgs.yq-go ];
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
184
generate-codex.sh
Executable file
184
generate-codex.sh
Executable file
|
|
@ -0,0 +1,184 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# generate-codex.sh — generates Codex CLI config from Claude source files.
|
||||
# Claude source files are the source of truth; this script derives Codex equivalents.
|
||||
# Idempotent: safe to run multiple times.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CODEX_DIR="$SCRIPT_DIR/codex"
|
||||
CODEX_AGENTS_DIR="$CODEX_DIR/agents"
|
||||
AGENTS_SRC="$SCRIPT_DIR/agents"
|
||||
RULES_DIR="$SCRIPT_DIR/rules"
|
||||
CLAUDE_MD="$SCRIPT_DIR/CLAUDE.md"
|
||||
SETTINGS_JSON="$SCRIPT_DIR/settings.json"
|
||||
|
||||
# Create output directories
|
||||
mkdir -p "$CODEX_DIR"
|
||||
mkdir -p "$CODEX_AGENTS_DIR"
|
||||
|
||||
# Clean existing generated agent TOMLs
|
||||
rm -f "$CODEX_AGENTS_DIR"/*.toml
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# map_model — maps Claude model name to Codex model name
|
||||
# ---------------------------------------------------------------------------
|
||||
map_model() {
|
||||
local model="$1"
|
||||
case "$model" in
|
||||
opus) echo "o3" ;;
|
||||
sonnet) echo "o4-mini" ;;
|
||||
haiku) echo "o4-mini" ;;
|
||||
*) echo "o4-mini" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# map_effort — maps Claude effort level to Codex model_reasoning_effort
|
||||
# ---------------------------------------------------------------------------
|
||||
map_effort() {
|
||||
local effort="$1"
|
||||
case "$effort" in
|
||||
low) echo "low" ;;
|
||||
medium) echo "medium" ;;
|
||||
high) echo "high" ;;
|
||||
max) echo "xhigh" ;;
|
||||
*) echo "medium" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# map_sandbox_mode — determines Codex sandbox_mode from agent frontmatter
|
||||
# $1 = permissionMode value (plan / acceptEdits / "")
|
||||
# $2 = tools list (comma-separated)
|
||||
# ---------------------------------------------------------------------------
|
||||
map_sandbox_mode() {
|
||||
local permission_mode="$1"
|
||||
local tools="$2"
|
||||
|
||||
# plan mode is read-only
|
||||
if [ "$permission_mode" = "plan" ]; then
|
||||
echo "read-only"
|
||||
return
|
||||
fi
|
||||
|
||||
# acceptEdits with Write or Edit tool → workspace-write
|
||||
if [ "$permission_mode" = "acceptEdits" ]; then
|
||||
if echo "$tools" | grep -qE '\b(Write|Edit)\b'; then
|
||||
echo "workspace-write"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
# Default: read-only
|
||||
echo "read-only"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# generate_agent_toml — converts a single agent .md file to Codex .toml
|
||||
# ---------------------------------------------------------------------------
|
||||
generate_agent_toml() {
|
||||
local src_file="$1"
|
||||
local agent_basename
|
||||
agent_basename="$(basename "$src_file" .md)"
|
||||
local dst_file="$CODEX_AGENTS_DIR/${agent_basename}.toml"
|
||||
|
||||
# Extract YAML frontmatter using yq
|
||||
local frontmatter
|
||||
frontmatter="$(yq --front-matter=extract '.' "$src_file")"
|
||||
|
||||
# Extract individual fields from frontmatter
|
||||
local name description model effort permission_mode tools disallowed_tools
|
||||
name="$(echo "$frontmatter" | yq '.name // ""')"
|
||||
description="$(echo "$frontmatter" | yq '.description // ""')"
|
||||
model="$(echo "$frontmatter" | yq '.model // ""')"
|
||||
effort="$(echo "$frontmatter" | yq '.effort // ""')"
|
||||
permission_mode="$(echo "$frontmatter" | yq '.permissionMode // ""')"
|
||||
tools="$(echo "$frontmatter" | yq '.tools // ""')"
|
||||
disallowed_tools="$(echo "$frontmatter" | yq '.disallowedTools // ""')"
|
||||
|
||||
# Map to Codex equivalents
|
||||
local codex_model codex_effort codex_sandbox
|
||||
codex_model="$(map_model "$model")"
|
||||
codex_effort="$(map_effort "${effort:-medium}")"
|
||||
codex_sandbox="$(map_sandbox_mode "$permission_mode" "$tools")"
|
||||
|
||||
# Extract markdown body (everything after the closing frontmatter ---)
|
||||
# The frontmatter block starts at line 1 with --- and ends at the second ---
|
||||
local body
|
||||
body="$(awk 'BEGIN{fm=0} /^---$/{if(fm==0){fm=1;next} if(fm==1){fm=2;next}} fm==2{print}' "$src_file")"
|
||||
|
||||
# Build developer_instructions: append disallowedTools note if present
|
||||
local developer_instructions
|
||||
developer_instructions="$body"
|
||||
if [ -n "$disallowed_tools" ] && [ "$disallowed_tools" != "null" ]; then
|
||||
developer_instructions="${developer_instructions}
|
||||
|
||||
You do NOT have access to these tools: ${disallowed_tools}"
|
||||
fi
|
||||
|
||||
# Write TOML output
|
||||
cat > "$dst_file" <<TOML
|
||||
name = "${name}"
|
||||
description = "${description}"
|
||||
model = "${codex_model}"
|
||||
model_reasoning_effort = "${codex_effort}"
|
||||
sandbox_mode = "${codex_sandbox}"
|
||||
developer_instructions = """
|
||||
${developer_instructions}
|
||||
"""
|
||||
TOML
|
||||
|
||||
echo "Generated: $dst_file"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Generate agents
|
||||
# ---------------------------------------------------------------------------
|
||||
echo "Generating Codex agent definitions..."
|
||||
for agent_file in "$AGENTS_SRC"/*.md; do
|
||||
[ -f "$agent_file" ] || continue
|
||||
generate_agent_toml "$agent_file"
|
||||
done
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Generate AGENTS.md — concatenate CLAUDE.md and rules/*.md (sorted)
|
||||
# ---------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "Generating codex/AGENTS.md..."
|
||||
{
|
||||
echo "# Agent Team Instructions"
|
||||
echo ""
|
||||
echo "Agent-team specific protocols live in skills (orchestrate, conventions, worker-protocol, qa-checklist, message-schema, project)."
|
||||
for rules_file in $(ls "$RULES_DIR"/*.md | sort); do
|
||||
echo ""
|
||||
cat "$rules_file"
|
||||
done
|
||||
} > "$CODEX_DIR/AGENTS.md"
|
||||
echo "Generated: $CODEX_DIR/AGENTS.md"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Generate config.toml — derive sandbox_mode from settings.json defaultMode
|
||||
# ---------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "Generating codex/config.toml..."
|
||||
|
||||
default_mode="$(yq -r '.permissions.defaultMode // "acceptEdits"' "$SETTINGS_JSON")"
|
||||
|
||||
# Map Claude defaultMode to Codex sandbox_mode
|
||||
case "$default_mode" in
|
||||
plan) config_sandbox="read-only" ;;
|
||||
acceptEdits) config_sandbox="workspace-write" ;;
|
||||
*) config_sandbox="workspace-write" ;;
|
||||
esac
|
||||
|
||||
cat > "$CODEX_DIR/config.toml" <<TOML
|
||||
model = "o4-mini"
|
||||
model_reasoning_effort = "medium"
|
||||
sandbox_mode = "${config_sandbox}"
|
||||
approval_policy = "on-request"
|
||||
TOML
|
||||
echo "Generated: $CODEX_DIR/config.toml"
|
||||
|
||||
echo ""
|
||||
echo "Done. Run ./install.sh to link generated files into ~/.codex/"
|
||||
30
install.sh
30
install.sh
|
|
@ -122,5 +122,35 @@ create_symlink "$RULES_SRC" "$RULES_DST" "rules"
|
|||
create_file_symlink "$CLAUDE_MD_SRC" "$CLAUDE_MD_DST" "CLAUDE.md"
|
||||
create_file_symlink "$SETTINGS_SRC" "$SETTINGS_DST" "settings.json"
|
||||
|
||||
# Codex CLI integration (optional — only if ~/.codex exists)
|
||||
CODEX_DIR="$HOME/.codex"
|
||||
CODEX_AGENTS_DIR="$HOME/.agents"
|
||||
|
||||
if [ -d "$CODEX_DIR" ]; then
|
||||
echo ""
|
||||
echo "Codex CLI detected at $CODEX_DIR"
|
||||
|
||||
# Skills shared via ~/.agents/skills/ (Codex discovery path)
|
||||
mkdir -p "$CODEX_AGENTS_DIR"
|
||||
create_symlink "$SKILLS_SRC" "$CODEX_AGENTS_DIR/skills" "codex skills"
|
||||
|
||||
# Generated agents
|
||||
if [ -d "$SCRIPT_DIR/codex/agents" ]; then
|
||||
create_symlink "$SCRIPT_DIR/codex/agents" "$CODEX_DIR/agents" "codex agents"
|
||||
else
|
||||
echo "Run ./generate-codex.sh first to generate Codex agent definitions"
|
||||
fi
|
||||
|
||||
# Generated AGENTS.md (symlink to project root for Codex discovery)
|
||||
if [ -f "$SCRIPT_DIR/codex/AGENTS.md" ]; then
|
||||
create_file_symlink "$SCRIPT_DIR/codex/AGENTS.md" "$CODEX_DIR/AGENTS.md" "codex AGENTS.md"
|
||||
fi
|
||||
|
||||
# Generated config.toml
|
||||
if [ -f "$SCRIPT_DIR/codex/config.toml" ]; then
|
||||
create_file_symlink "$SCRIPT_DIR/codex/config.toml" "$CODEX_DIR/config.toml" "codex config.toml"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Done. Open Claude Code and load the orchestrate skill to begin."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue