diff --git a/.gitignore b/.gitignore index c3bcec779..b98569d79 100644 --- a/.gitignore +++ b/.gitignore @@ -75,4 +75,6 @@ integrations/aider/CONVENTIONS.md integrations/windsurf/.windsurfrules integrations/openclaw/* integrations/qwen/agents/ +integrations/codex/* !integrations/openclaw/README.md +!integrations/codex/README.md diff --git a/README.md b/README.md index 73d50391f..152c73605 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Each agent file contains: Browse the agents below and copy/adapt the ones you need! -### Option 3: Use with Other Tools (Cursor, Aider, Windsurf, Gemini CLI, OpenCode) +### Option 3: Use with Other Tools (Cursor, Aider, Windsurf, Gemini CLI, Codex, OpenCode) ```bash # Step 1 -- generate integration files for all supported tools @@ -58,6 +58,7 @@ Browse the agents below and copy/adapt the ones you need! ./scripts/install.sh --tool copilot ./scripts/install.sh --tool aider ./scripts/install.sh --tool windsurf +./scripts/install.sh --tool codex ``` See the [Multi-Tool Integrations](#-multi-tool-integrations) section below for full details. @@ -509,12 +510,13 @@ The Agency works natively with Claude Code, and ships conversion + install scrip - **[GitHub Copilot](https://github.com/copilot)** — native `.md` agents, no conversion needed → `~/.github/agents/` + `~/.copilot/agents/` - **[Antigravity](https://github.com/google-gemini/antigravity)** — `SKILL.md` per agent → `~/.gemini/antigravity/skills/` - **[Gemini CLI](https://github.com/google-gemini/gemini-cli)** — extension + `SKILL.md` files → `~/.gemini/extensions/agency-agents/` +- **Codex** — skill directories (`SKILL.md` + `agents/openai.yaml`) → `./.codex/skills/` - **[OpenCode](https://opencode.ai)** — `.md` agent files → `.opencode/agents/` - **[Cursor](https://cursor.sh)** — `.mdc` rule files → `.cursor/rules/` - **[Aider](https://aider.chat)** — single `CONVENTIONS.md` → `./CONVENTIONS.md` - **[Windsurf](https://codeium.com/windsurf)** — single `.windsurfrules` → `./.windsurfrules` - **[OpenClaw](https://github.com/openclaw/openclaw)** — `SOUL.md` + `AGENTS.md` + `IDENTITY.md` per agent -- **[Qwen Code](https://github.com/QwenLM/qwen-code)** — `.md` SubAgent files → `~/.qwen/agents/` +- **[Qwen Code](https://github.com/QwenLM/qwen-code)** — `.md` SubAgent files → `./.qwen/agents/` --- @@ -545,14 +547,15 @@ The installer scans your system for installed tools, shows a checkbox UI, and le [x] 2) [*] Copilot (~/.github + ~/.copilot) [x] 3) [*] Antigravity (~/.gemini/antigravity) [ ] 4) [ ] Gemini CLI (gemini extension) - [ ] 5) [ ] OpenCode (opencode.ai) - [ ] 6) [ ] OpenClaw (~/.openclaw) - [x] 7) [*] Cursor (.cursor/rules) - [ ] 8) [ ] Aider (CONVENTIONS.md) - [ ] 9) [ ] Windsurf (.windsurfrules) - [ ] 10) [ ] Qwen Code (~/.qwen/agents) - - [1-10] toggle [a] all [n] none [d] detected + [ ] 5) [ ] Codex (.codex/skills) + [ ] 6) [ ] OpenCode (opencode.ai) + [ ] 7) [ ] OpenClaw (~/.openclaw) + [x] 8) [*] Cursor (.cursor/rules) + [ ] 9) [ ] Aider (CONVENTIONS.md) + [ ] 10) [ ] Windsurf (.windsurfrules) + [ ] 11) [ ] Qwen Code (.qwen/agents) + + [1-11] toggle [a] all [n] none [d] detected [Enter] install [q] quit ``` @@ -562,6 +565,7 @@ The installer scans your system for installed tools, shows a checkbox UI, and le ./scripts/install.sh --tool opencode ./scripts/install.sh --tool openclaw ./scripts/install.sh --tool antigravity +./scripts/install.sh --tool codex ``` **Non-interactive (CI/scripts):** @@ -648,6 +652,27 @@ On a fresh clone, generate the Gemini extension files before running the install See [integrations/gemini-cli/README.md](integrations/gemini-cli/README.md) for details. +
+Codex + +Each agent becomes a Codex skill directory containing `SKILL.md` and `agents/openai.yaml`. +Codex is installed project-scoped into `.codex/skills/`, matching the repo's +other project-local integrations. Chinese description text (`description`, +`vibe`, and body) is supported, while `name` should remain English/slug-friendly +for stable folder naming. If `name` is non-ASCII or derives an invalid slug, +Codex conversion fails fast. + +```bash +# Generate Codex integration files +./scripts/convert.sh --tool codex + +# Install to current project (.codex/skills/) +./scripts/install.sh --tool codex +``` + +See [integrations/codex/README.md](integrations/codex/README.md) for details. +
+
OpenCode @@ -780,7 +805,7 @@ When you add new agents or edit existing ones, regenerate all integration files: - [ ] Interactive agent selector web tool - [x] Multi-agent workflow examples -- see [examples/](examples/) -- [x] Multi-tool integration scripts (Claude Code, GitHub Copilot, Antigravity, Gemini CLI, OpenCode, OpenClaw, Cursor, Aider, Windsurf, Qwen Code) +- [x] Multi-tool integration scripts (Claude Code, GitHub Copilot, Antigravity, Gemini CLI, Codex, OpenCode, OpenClaw, Cursor, Aider, Windsurf, Qwen Code) - [ ] Video tutorials on agent design - [ ] Community agent marketplace - [ ] Agent "personality quiz" for project matching diff --git a/integrations/README.md b/integrations/README.md index c909700ff..4217ef28b 100644 --- a/integrations/README.md +++ b/integrations/README.md @@ -9,6 +9,7 @@ supported agentic coding tools. - **[GitHub Copilot](#github-copilot)** — `.md` agents, use the repo directly - **[Antigravity](#antigravity)** — `SKILL.md` per agent in `antigravity/` - **[Gemini CLI](#gemini-cli)** — extension + `SKILL.md` files in `gemini-cli/` +- **[Codex](#codex)** — `SKILL.md` + `agents/openai.yaml` skills in `codex/` - **[OpenCode](#opencode)** — `.md` agent files in `opencode/` - **[OpenClaw](#openclaw)** — `SOUL.md` + `AGENTS.md` + `IDENTITY.md` workspaces - **[Cursor](#cursor)** — `.mdc` rule files in `cursor/` @@ -30,11 +31,15 @@ supported agentic coding tools. # Gemini CLI needs generated integration files on a fresh clone ./scripts/convert.sh --tool gemini-cli ./scripts/install.sh --tool gemini-cli + +# Codex is project-scoped +./scripts/convert.sh --tool codex +./scripts/install.sh --tool codex ``` -For project-scoped tools such as OpenCode, Cursor, Aider, and Windsurf, run -the installer from your target project root as shown in the tool-specific -sections below. +For project-scoped tools such as Codex, OpenCode, Cursor, Aider, Windsurf, +and Qwen, run the installer from your target project root as shown in the +tool-specific sections below. ## Regenerating Integration Files @@ -103,6 +108,42 @@ See [gemini-cli/README.md](gemini-cli/README.md) for details. --- +## Codex + +Each agent becomes a Codex skill with: + +- `SKILL.md` +- `agents/openai.yaml` + +Generate Codex integration files first: + +```bash +./scripts/convert.sh --tool codex +``` + +Then install it from your project root: + +```bash +# project-scoped -> ./.codex/skills/ +./scripts/install.sh --tool codex +``` + +Chinese explanation content is supported in Codex description fields and body. +Keep `name` English/slug-friendly to preserve stable directory naming. +Codex converter fails fast when `name` is non-ASCII or produces an invalid slug. + +Recommended pattern: + +```yaml +name: Frontend Developer +description: Frontend specialist focused on modern web apps +vibe: Detail-oriented and maintainability-focused +``` + +See [codex/README.md](codex/README.md) for details. + +--- + ## OpenCode Each agent becomes a project-scoped `.md` file in `.opencode/agents/`. diff --git a/integrations/codex/README.md b/integrations/codex/README.md new file mode 100644 index 000000000..defadae83 --- /dev/null +++ b/integrations/codex/README.md @@ -0,0 +1,94 @@ +# Codex Integration + +Converts all Agency agents into Codex skills. + +Each converted skill includes: + +- `SKILL.md` +- `agents/openai.yaml` + +Conversion output is written to: + +```text +integrations/codex/ + AGENTS.md + skills/ + frontend-developer/ + SKILL.md + agents/openai.yaml + backend-architect/ + SKILL.md + agents/openai.yaml + ... +``` + +## Chinese Description Support + +Codex integration follows a simple rule: keep identifiers stable, but allow +human-readable description fields to use Chinese when needed. + +Identifier layer (keep English / slug-friendly): + +- `name` +- the slug derived from `name` +- the skill directory name (for example `frontend-developer`) +- the installation target directory name + +Description layer (Chinese is allowed): + +- `description` +- `vibe` +- the `SKILL.md` body +- description fields in `agents/openai.yaml` such as `short_description` + +Why: the converter depends on `slugify(name)` to generate directories and +install paths. If `name` is changed to Chinese, the slug may become invalid or +empty, which would break directory naming and installation stability. +`./scripts/convert.sh --tool codex` fails fast in that case, so keep Chinese +content in `description`, `vibe`, and the body instead. + +### Recommended Pattern + +```yaml +name: Frontend Developer +description: Frontend specialist focused on modern web apps, React/Vue, and performance optimization +vibe: Detail-oriented, maintainability-focused, and accessibility-aware +``` + +### Not Recommended + +```yaml +name: Frontend Specialist CN +description: Responsible for frontend architecture and implementation +``` + +Note: changing `name` away from a stable English slug-friendly value can break +slug generation and installation paths. Put localized content in `description`, +`vibe`, and the body instead. + +## Convert + +```bash +./scripts/convert.sh --tool codex +``` + +## Install + +Codex is installed project-scoped to `./.codex/skills/`, matching the repo's +other project-local integrations. + +```bash +# Project-scoped +./scripts/install.sh --tool codex +``` + +## Notes + +- `integrations/codex/AGENTS.md` is generated as an index and usage guide. +- The installer does not copy `AGENTS.md` by default, so it will not overwrite + an existing project-level `AGENTS.md`. +- Codex installation currently installs the full skill set (no agent filter). +- Codex follows the same project-scoped install pattern as Cursor, OpenCode, + Aider, Windsurf, and Qwen in this repository. +- UTF-8 Chinese content is written to `SKILL.md` and `agents/openai.yaml` + as-is, with no extra transcoding step. diff --git a/scripts/convert.sh b/scripts/convert.sh index 27d2f66e4..48c6f39a3 100755 --- a/scripts/convert.sh +++ b/scripts/convert.sh @@ -12,6 +12,7 @@ # Tools: # antigravity — Antigravity skill files (~/.gemini/antigravity/skills/) # gemini-cli — Gemini CLI extension (skills/ + gemini-extension.json) +# codex — Codex skills (skills//SKILL.md + agents/openai.yaml) # opencode — OpenCode agent files (.opencode/agent/*.md) # cursor — Cursor rule files (.cursor/rules/*.mdc) # aider — Single CONVENTIONS.md for Aider @@ -67,7 +68,7 @@ AGENT_DIRS=( # --- Usage --- usage() { - sed -n '3,26p' "$0" | sed 's/^# \{0,1\}//' + sed -n '3,28p' "$0" | sed 's/^# \{0,1\}//' exit 0 } @@ -103,6 +104,31 @@ slugify() { echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//' } +# Codex requires a stable ASCII/slug-friendly name because install paths and +# skill directory names are derived from slug(name). +validate_codex_name_and_slug() { + local name="$1" slug="$2" file="$3" + + if printf '%s' "$name" | LC_ALL=C grep -q '[^ -~]'; then + error "Codex: invalid name '$name' in $file" + error "Codex: keep name English/ASCII for slug stability; put Chinese in description/vibe/body." + return 1 + fi + + if [[ -z "$slug" || ! "$slug" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then + error "Codex: invalid slug '$slug' derived from name '$name' in $file" + error "Codex: keep name English/slug-friendly; put Chinese in description/vibe/body." + return 1 + fi +} + +# YAML-safe single-quoted scalar. +# YAML single quote escaping rule: ' -> '' +yaml_squote() { + local value="$1" + printf "'%s'" "$(printf '%s' "$value" | sed "s/'/''/g")" +} + # --- Per-tool converters --- convert_antigravity() { @@ -154,6 +180,58 @@ ${body} HEREDOC } +convert_codex() { + local file="$1" + local name description vibe color slug outdir skillfile agentfile body + local q_name q_description q_prompt q_skill_name q_skill_description q_vibe + + name="$(get_field "name" "$file")" + description="$(get_field "description" "$file")" + vibe="$(get_field "vibe" "$file")" + color="$(get_field "color" "$file")" + slug="$(slugify "$name")" + validate_codex_name_and_slug "$name" "$slug" "$file" || return 1 + body="$(get_body "$file")" + + outdir="$OUT_DIR/codex/skills/$slug" + skillfile="$outdir/SKILL.md" + agentfile="$outdir/agents/openai.yaml" + mkdir -p "$outdir/agents" + + q_name="$(yaml_squote "$name")" + q_description="$(yaml_squote "$description")" + q_prompt="$(yaml_squote "Use the \$$slug skill to help with this task.")" + q_skill_name="$(yaml_squote "$slug")" + q_skill_description="$(yaml_squote "$description")" + if [[ -n "$vibe" ]]; then + q_vibe="$(yaml_squote "$vibe")" + fi + + cat > "$agentfile" < "$skillfile" <> "$CODEX_INDEX_TMP" +} + # Map known color names and normalize to OpenCode-safe #RRGGBB values. resolve_opencode_color() { local c="$1" @@ -373,11 +451,13 @@ HEREDOC fi } -# Aider and Windsurf are single-file formats — accumulate into temp files -# then write at the end. +# Aider, Windsurf, and Codex index are single-file formats — accumulate into +# temp files then write at the end. AIDER_TMP="$(mktemp)" WINDSURF_TMP="$(mktemp)" -trap 'rm -f "$AIDER_TMP" "$WINDSURF_TMP"' EXIT +CODEX_TMP="$(mktemp)" +CODEX_INDEX_TMP="$(mktemp)" +trap 'rm -f "$AIDER_TMP" "$WINDSURF_TMP" "$CODEX_TMP" "$CODEX_INDEX_TMP"' EXIT # Write Aider/Windsurf headers once cat > "$AIDER_TMP" <<'HEREDOC' @@ -443,6 +523,39 @@ ${body} HEREDOC } +write_codex_agents_md() { + cat > "$CODEX_TMP" <<'HEREDOC' +# The Agency Codex Skills Index + +This file documents the generated Codex skills in `integrations/codex/skills/`. + +Use these skills from Codex by name, for example: + +```text +Use the $frontend-developer skill to review this component. +``` + +> Note: this file is informational only and is not installed by default to avoid +> overwriting a project's existing `AGENTS.md`. + +## Available Skills +HEREDOC + + if [[ -s "$CODEX_INDEX_TMP" ]]; then + while IFS=$'\t' read -r slug name description color; do + cat >> "$CODEX_TMP" <> "$CODEX_TMP" <<'HEREDOC' +- No skills were generated in this run. +HEREDOC + fi +} + # --- Main loop --- run_conversions() { @@ -464,14 +577,15 @@ run_conversions() { [[ -n "$name" ]] || continue case "$tool" in - antigravity) convert_antigravity "$file" ;; - gemini-cli) convert_gemini_cli "$file" ;; - opencode) convert_opencode "$file" ;; - cursor) convert_cursor "$file" ;; - openclaw) convert_openclaw "$file" ;; - qwen) convert_qwen "$file" ;; - aider) accumulate_aider "$file" ;; - windsurf) accumulate_windsurf "$file" ;; + antigravity) convert_antigravity "$file" || return 1 ;; + gemini-cli) convert_gemini_cli "$file" || return 1 ;; + codex) convert_codex "$file" || return 1 ;; + opencode) convert_opencode "$file" || return 1 ;; + cursor) convert_cursor "$file" || return 1 ;; + openclaw) convert_openclaw "$file" || return 1 ;; + qwen) convert_qwen "$file" || return 1 ;; + aider) accumulate_aider "$file" || return 1 ;; + windsurf) accumulate_windsurf "$file" || return 1 ;; esac (( count++ )) || true @@ -500,7 +614,7 @@ main() { esac done - local valid_tools=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "all") + local valid_tools=("antigravity" "gemini-cli" "codex" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "all") local valid=false for t in "${valid_tools[@]}"; do [[ "$t" == "$tool" ]] && valid=true && break; done if ! $valid; then @@ -519,7 +633,7 @@ main() { local tools_to_run=() if [[ "$tool" == "all" ]]; then - tools_to_run=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen") + tools_to_run=("antigravity" "gemini-cli" "codex" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen") else tools_to_run=("$tool") fi @@ -543,12 +657,15 @@ main() { done rm -rf "$parallel_out_dir" local idx=7 - for t in aider windsurf; do + for t in codex aider windsurf; do progress_bar "$idx" "$n_tools" printf "\n" header "Converting: $t ($idx/$n_tools)" local count - count="$(run_conversions "$t")" + if ! count="$(run_conversions "$t")"; then + error "Conversion failed for $t" + exit 1 + fi total=$(( total + count )) info "Converted $count agents for $t" (( idx++ )) || true @@ -561,7 +678,10 @@ main() { printf "\n" header "Converting: $t ($i/$n_tools)" local count - count="$(run_conversions "$t")" + if ! count="$(run_conversions "$t")"; then + error "Conversion failed for $t" + exit 1 + fi total=$(( total + count )) # Gemini CLI also needs the extension manifest (written by this process when --tool gemini-cli) @@ -591,6 +711,12 @@ HEREDOC cp "$WINDSURF_TMP" "$OUT_DIR/windsurf/.windsurfrules" info "Wrote integrations/windsurf/.windsurfrules" fi + if [[ "$tool" == "all" || "$tool" == "codex" ]]; then + mkdir -p "$OUT_DIR/codex" + write_codex_agents_md + cp "$CODEX_TMP" "$OUT_DIR/codex/AGENTS.md" + info "Wrote integrations/codex/AGENTS.md" + fi echo "" if $use_parallel && [[ "$tool" == "all" ]]; then diff --git a/scripts/install.sh b/scripts/install.sh index 9bc4f1d89..1786fe5a6 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -14,12 +14,13 @@ # copilot -- Copy agents to ~/.github/agents/ and ~/.copilot/agents/ # antigravity -- Copy skills to ~/.gemini/antigravity/skills/ # gemini-cli -- Install extension to ~/.gemini/extensions/agency-agents/ +# codex -- Copy skills to ./.codex/skills/ in current directory # opencode -- Copy agents to .opencode/agent/ in current directory # cursor -- Copy rules to .cursor/rules/ in current directory # aider -- Copy CONVENTIONS.md to current directory # windsurf -- Copy .windsurfrules to current directory # openclaw -- Copy workspaces to ~/.openclaw/agency-agents/ -# qwen -- Copy SubAgents to ~/.qwen/agents/ (user-wide) or .qwen/agents/ (project) +# qwen -- Copy SubAgents to .qwen/agents/ in current directory # all -- Install for all detected tools (default) # # Flags: @@ -101,13 +102,15 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" INTEGRATIONS="$REPO_ROOT/integrations" -ALL_TOOLS=(claude-code copilot antigravity gemini-cli opencode openclaw cursor aider windsurf qwen) +ALL_TOOLS=(claude-code copilot antigravity gemini-cli codex opencode openclaw cursor aider windsurf qwen) +CODEX_SRC_SKILLS_DIR="$INTEGRATIONS/codex/skills" +CODEX_SKILLS_DIR="${PWD}/.codex/skills" # --------------------------------------------------------------------------- # Usage # --------------------------------------------------------------------------- usage() { - sed -n '3,32p' "$0" | sed 's/^# \{0,1\}//' + sed -n '3,34p' "$0" | sed 's/^# \{0,1\}//' exit 0 } @@ -141,7 +144,8 @@ detect_opencode() { command -v opencode >/dev/null 2>&1 || [[ -d "${HOME}/.c detect_aider() { command -v aider >/dev/null 2>&1; } detect_openclaw() { command -v openclaw >/dev/null 2>&1 || [[ -d "${HOME}/.openclaw" ]]; } detect_windsurf() { command -v windsurf >/dev/null 2>&1 || [[ -d "${HOME}/.codeium" ]]; } -detect_qwen() { command -v qwen >/dev/null 2>&1 || [[ -d "${HOME}/.qwen" ]]; } +detect_qwen() { command -v qwen >/dev/null 2>&1 || [[ -d "${PWD}/.qwen" ]]; } +detect_codex() { command -v codex >/dev/null 2>&1 || [[ -d "${PWD}/.codex" ]]; } is_detected() { case "$1" in @@ -155,6 +159,7 @@ is_detected() { aider) detect_aider ;; windsurf) detect_windsurf ;; qwen) detect_qwen ;; + codex) detect_codex ;; *) return 1 ;; esac } @@ -171,7 +176,8 @@ tool_label() { cursor) printf "%-14s %s" "Cursor" "(.cursor/rules)" ;; aider) printf "%-14s %s" "Aider" "(CONVENTIONS.md)" ;; windsurf) printf "%-14s %s" "Windsurf" "(.windsurfrules)" ;; - qwen) printf "%-14s %s" "Qwen Code" "(~/.qwen/agents)" ;; + qwen) printf "%-14s %s" "Qwen Code" "(.qwen/agents)" ;; + codex) printf "%-14s %s" "Codex" "(.codex/skills)" ;; esac } @@ -468,6 +474,47 @@ install_qwen() { warn "Tip: Run '/agents manage' in Qwen Code to refresh, or restart session" } +install_codex() { + local src="$CODEX_SRC_SKILLS_DIR" + local dest="$CODEX_SKILLS_DIR" + local count=0 + + [[ -d "$src" ]] || { err "integrations/codex missing. Run ./scripts/convert.sh --tool codex first."; return 1; } + if [[ -f "$src/SKILL.md" || -f "$src/agents/openai.yaml" ]]; then + err "Codex: invalid root-level artifacts detected in $src" + err "Codex: keep name English/slug-friendly and rerun ./scripts/convert.sh --tool codex." + return 1 + fi + + mkdir -p "$dest" + + local d src_name src_skill src_agent + while IFS= read -r -d '' d; do + src_name="$(basename "$d")" + + src_skill="$d/SKILL.md" + src_agent="$d/agents/openai.yaml" + if [[ ! -f "$src_skill" ]]; then + warn "Codex: missing SKILL.md for '$src_name', skipped." + continue + fi + if [[ ! -f "$src_agent" ]]; then + warn "Codex: missing agents/openai.yaml for '$src_name', skipped." + continue + fi + + mkdir -p "$dest/$src_name/agents" + cp "$src_skill" "$dest/$src_name/SKILL.md" + cp "$src_agent" "$dest/$src_name/agents/openai.yaml" + + (( count++ )) || true + done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0) + + ok "Codex: $count skills -> $dest" + warn "Codex: project-scoped. Run from your project root to install there." + warn "Codex: integrations/codex/AGENTS.md is informational and is not installed by default." +} + install_tool() { case "$1" in claude-code) install_claude_code ;; @@ -480,6 +527,7 @@ install_tool() { aider) install_aider ;; windsurf) install_windsurf ;; qwen) install_qwen ;; + codex) install_codex ;; esac }