-
Notifications
You must be signed in to change notification settings - Fork 67
Support Codex CLI as integration target #502
Description
Support Codex CLI as integration target
Problem Statement
APM needs to support OpenAI's Codex CLI as a first-class integration target. Codex uses a unique multi-directory configuration model unlike any existing target: skills live under .agents/skills/ (cross-tool agent skills standard), while hooks, subagent definitions, and config live under .codex/. Instructions are read from AGENTS.md at repo root. This breaks APM's current assumption that all primitives for a target deploy under a single root_dir.
Research: Codex CLI Configuration Model
Sources:
- Codex Skills
- Codex Subagents
- Codex Hooks
- Codex AGENTS.md
- Codex MCP
- Codex Plugins
- Codex Rules
- Codex Config Basics
- Codex Config Advanced
| Codex Concept | Location | Format | APM Primitive |
|---|---|---|---|
| Skills | .agents/skills/*/SKILL.md |
Markdown (agent skills standard) | skills |
| Subagents | .codex/agents/*.toml |
TOML (name, description, developer_instructions) |
agents |
| Hooks | .codex/hooks.json |
JSON (SessionStart, PreToolUse, PostToolUse, UserPromptSubmit, Stop) |
hooks |
| Instructions | AGENTS.md at repo root (walked from root to CWD) |
Markdown | instructions (compile-only) |
| Rules | .codex/rules/*.rules |
Starlark (command execution policies) | Deferred to v2 |
| MCP servers | .codex/config.toml [mcp_servers.*] |
TOML | |
| Plugins | Distribution format (skills + apps + MCP) | N/A (APM packages serve this role) | N/A |
Key insight: Codex skills use the agent skills standard -- the same SKILL.md format APM already supports. This is a direct format match.
Key Architectural Decisions
Decision 1: deploy_root on PrimitiveMapping
Problem: Current TargetProfile assumes all primitives deploy under one root_dir. Codex needs .codex/ for hooks/agents but .agents/ for skills.
Decision: Add deploy_root: Optional[str] = None to PrimitiveMapping. When set, integrators use it instead of target.root_dir. Default None preserves all existing behavior (zero regression).
Rejected alternatives:
- Option B (hardcode Codex paths in SkillIntegrator): creates precedent rot, defeats data-driven architecture
- Option C (two target entries for
.codex/and.agents/): breaks 1:1 target-to-tool model, leaks implementation details to users
Security implication: get_integration_prefixes() must also emit prefixes from deploy_root values, so .agents/ enters the allowed prefix set.
Decision 2: Extend AgentIntegrator, not new SubagentIntegrator
Problem: Codex agents are TOML files; APM agents are Markdown.
Decision: Add _write_codex_agent() transformer to AgentIntegrator, dispatched via format_id == "codex_agent". Same pattern as Cursor rules (format_id == "cursor_rules" triggers frontmatter conversion).
Rationale: The transform is ~30 lines. One call site. Creating a new integrator class would violate "abstract when 3+ call sites" guideline.
Decision 3: Instructions via compile only, not install
Problem: Codex reads ONE AGENTS.md per directory level. Individual file deployment (like Copilot's .instructions.md) is not viable.
Decision: apm compile --target codex generates AGENTS.md. No instructions primitive in the Codex target profile during install.
Note: Install-time AGENTS.md with <!-- APM:BEGIN/END --> managed sections is a strong v2 candidate but adds merge complexity that doesn't exist in any other target.
Decision 4: Detect by .codex/ only, not .agents/
Problem: .agents/ is cross-tool (agent skills standard). Its presence doesn't mean Codex is active.
Decision: detect_by_dir=True checks .codex/ only. Consistent with all other targets (.github/ -> copilot, .claude/ -> claude, etc.).
Decision 5: Defer Starlark rules to v2
Rationale: Starlark is a new format family with no existing APM primitive mapping.
Decision 6: Flat tree output, "agents" label
Problem: Codex deploys to two roots. Should output group by root?
Decision: Flat list with full paths. No grouping by root. Use "agents" label (not "subagents") -- APM is the abstraction layer, label follows the filesystem.
[+] my-package #v1.0 @b0cbd3df
|-- 2 skill(s) integrated -> .agents/skills/
|-- 1 agent(s) integrated -> .codex/agents/
|-- 1 hook(s) integrated -> .codex/hooks.json
Format transformation (MD->TOML) shown as verbose-only detail:
|-- 1 agent(s) integrated -> .codex/agents/
(md -> toml: converted for Codex CLI)
Decision 7: Hook merge with _apm_source markers
Codex hooks merge into single .codex/hooks.json, following the Claude/Cursor pattern exactly. APM entries tagged with _apm_source for safe cleanup. The hooks.json file itself is NOT tracked in deployed_files (cleaned via markers); only referenced script files are tracked.
Lockfile Management
No schema changes required
LockedDependency.deployed_files is List[str] -- flat list of relative POSIX paths with no single-root constraint. A single dependency already supports files across multiple roots (confirmed by existing tests where skills deploy to both .github/skills/ and .claude/skills/).
Codex deployed_files example
dependencies:
- repo_url: org/my-package
resolved_commit: abc123
deployed_files:
- .agents/skills/my-skill/SKILL.md
- .agents/skills/my-skill/scripts/run.sh
- .codex/agents/my-agent.toml
- .codex/hooks/my-package/validate.shNote: .codex/hooks.json is NOT listed -- it's a shared file cleaned via _apm_source markers (same as Claude's settings.json). Only script files referenced by hooks are tracked.
Path flow
Integrator returns -> Path("/project/.agents/skills/my-skill/SKILL.md")
.relative_to(root) -> PosixPath(".agents/skills/my-skill/SKILL.md")
.as_posix() -> ".agents/skills/my-skill/SKILL.md"
Stored in apm.lock.yaml -> deployed_files: [".agents/skills/my-skill/SKILL.md"]
Collision detection
managed_files set is built from ALL existing lockfile deployed_files before install starts. Passed to every integrator. The .agents/skills/ paths are included automatically -- no changes to the collision detection pipeline.
Partition for uninstall
partition_managed_files() uses O(1) (root_dir, subdir) component lookup. Codex adds new bucket keys:
agents_codex-- files under.codex/agents/skills-- files under.agents/skills/(cross-target bucket, shared with existing skill entries but routed viadeploy_root)hooks--.codex/hooks/scripts (cross-target bucket)
Codex Target Registration
"codex": TargetProfile(
name="codex",
root_dir=".codex",
primitives={
"agents": PrimitiveMapping(
"agents", ".toml", "codex_agent",
),
"skills": PrimitiveMapping(
"skills", "/SKILL.md", "skill_standard",
deploy_root=".agents", # Cross-tool dir, NOT under .codex/
),
"hooks": PrimitiveMapping(
"", "hooks.json", "codex_hooks",
),
},
auto_create=False,
detect_by_dir=True,
)Key Logging Decisions (Consistency Across Targets)
Tree output pattern (all targets follow this)
[+] package-name #v1.0 @b0cbd3df # logger.download_complete()
|-- N primitive(s) integrated -> {deploy_path} # logger.tree_item() via _log_integration
Codex adds no new output primitives. Every line maps to existing logger methods.
Label follows filesystem, not tool branding
| Target | Primitive | Deploy Path | Label |
|---|---|---|---|
| Copilot | instructions | .github/instructions/ |
instruction(s) |
| Cursor | instructions | .cursor/rules/ |
rule(s) |
| Claude | agents | .claude/agents/ |
agent(s) |
| Codex | agents | .codex/agents/ |
agent(s) (not "subagent(s)") |
| Codex | skills | .agents/skills/ |
skill(s) |
| Codex | hooks | .codex/hooks.json |
hook(s) |
Format transformation is verbose-only
Codex MD->TOML agent transform follows the Cursor precedent (Cursor silently converts .instructions.md to .mdc with frontmatter rewriting):
# Default: outcome only
logger.tree_item(f" |-- {count} agent(s) integrated -> .codex/agents/")
# Verbose: adds implementation detail
logger.verbose_detail(f" (md -> toml: converted for Codex CLI)")Hook merge diagnostics
# Default: count summary
logger.tree_item(f" |-- {count} hook(s) integrated -> .codex/hooks.json")
# Verbose: preserved user hooks
logger.verbose_detail(f" ({user_count} existing user hook(s) preserved)")
# Warning (only on collision): via DiagnosticCollector
diagnostics.warn("hook event collision in .codex/hooks.json", package=pkg_name)No direct _rich_* calls in integration code
All output goes through logger.tree_item(), logger.verbose_detail(), or diagnostics.*(). The rendering layer (console.py) owns colors and symbols.
Architecture Diagram
apm install --target codex
|
v
active_targets(project_root, "codex")
-> [TargetProfile("codex", root_dir=".codex", ...)]
|
v
_integrate_package_primitives(targets=[codex_profile], ...)
|
|-- for "agents" primitive:
| AgentIntegrator.integrate_agents_for_target(codex_profile, ...)
| -> format_id == "codex_agent" -> _write_codex_agent()
| -> .agent.md -> .codex/agents/{name}.toml
| -> deployed_files: [".codex/agents/{name}.toml"]
|
|-- for "hooks" primitive:
| HookIntegrator.integrate_hooks_for_target(codex_profile, ...)
| -> integrate_package_hooks_codex()
| -> merge into .codex/hooks.json (_apm_source markers)
| -> copy scripts to .codex/hooks/{package}/
| -> deployed_files: [".codex/hooks/{package}/script.sh"]
| -> .codex/hooks.json NOT in deployed_files (shared file)
|
|-- for "skills" primitive (separate handling):
SkillIntegrator.integrate_package_skill(targets=[codex_profile], ...)
-> deploy_root=".agents" overrides root_dir=".codex"
-> .agents/skills/{name}/SKILL.md
-> deployed_files: [".agents/skills/{name}/SKILL.md", ...]
|
v
LockFile.write() -> apm.lock.yaml
deployed_files:
- .agents/skills/{name}/SKILL.md
- .codex/agents/{name}.toml
- .codex/hooks/{package}/script.sh
Execution Waves
Dependency Graph
Wave 1 (Foundation)
1-deploy-root --------+
+---> 1-target-registration ---> 1-bucket-aliases
1-cli-choices | |
| +---> 1-security-prefixes
| |
Wave 2 (Integrators) | |
| v
2-deploy-root-int <---+ 2-agent-toml
2-skill-deploy-root <------+
2-hook-codex <--------------+
|
Wave 3 (Flows) v
3-lockfile-verify <----- 2-* (all integrators)
4-uninstall-codex <----- 1-bucket-aliases + 2-deploy-root-int
3-compile-codex <-------- 1-cli-choices
5-user-scope <----------- 1-target-registration
Wave 4 (Tests)
6-test-* <-------------- Wave 2 + Wave 3
Wave 5 (Docs + E2E)
7-docs-* <-------------- Wave 2
8-e2e-* <--------------- Wave 4
Critical Path:
1-deploy-root -> 1-target-registration -> 2-agent-toml -> 6-test-agent-toml
-> 2-skill-deploy-root -> 6-test-skill-deploy-root
-> 2-hook-codex -> 6-test-hooks-codex
-> 8-e2e-install -> 8-e2e-codex-reads
Wave 1: Foundation
All parallelizable once 1-deploy-root completes (it unblocks 1-target-registration and 1-security-prefixes). 1-cli-choices has no dependencies and can start immediately.
Gate: All Wave 1 items must complete before Wave 2 starts. 1-deploy-root and 1-target-registration are on the critical path.
-
1-deploy-root-- Adddeploy_rootto PrimitiveMapping- File:
src/apm_cli/integration/targets.py - Add
deploy_root: Optional[str] = Nonefield toPrimitiveMappingdataclass. Whendeploy_root is not None, integrators use it instead oftarget.root_dirfor path computation. DefaultNonepreserves all existing behavior (zero regression risk). - Dependencies: none
- File:
-
1-target-registration-- Register Codex in KNOWN_TARGETS- File:
src/apm_cli/integration/targets.py - Add
"codex"TargetProfiletoKNOWN_TARGETS:root_dir=".codex", primitives for agents (.toml), skills (deploy_root=".agents"), hooks (.json).auto_create=False,detect_by_dir=True. - Dependencies:
1-deploy-root
- File:
-
1-security-prefixes-- Update security validation for.agents/prefix- File:
src/apm_cli/integration/targets.py - Update
get_integration_prefixes()to also emit prefixes fromdeploy_rootvalues. Ensures.agents/is in the allowed prefix set forvalidate_deploy_path(). Do NOT add empty string""as prefix (repo-root AGENTS.md needs explicit handling if added later). - Dependencies:
1-deploy-root
- File:
-
1-cli-choices-- Add "codex" to--targetCLI option- Files:
src/apm_cli/commands/install.py,src/apm_cli/commands/compile/cli.py, pack commands - Add
"codex"to theclick.Choicelist for--targetoption across install, compile, and pack commands. - Dependencies: none
- Files:
-
1-bucket-aliases-- Add Codex bucket aliases forpartition_managed_files- File:
src/apm_cli/integration/base_integrator.py - Add bucket alias entries for Codex primitives (e.g.,
agents_codex). Ensurepartition_managed_files()handles the.agents/root for skills correctly within the O(1) component-based path routing. - Dependencies:
1-target-registration
- File:
Wave 2: Integrator Updates
All four items are parallelizable across integrators. They fan out from 1-target-registration and converge into Wave 3.
Gate: All Wave 2 items must complete before Wave 3 starts. All four items are on the critical path.
-
2-agent-toml-- Add Codex TOML transformer to AgentIntegrator- File:
src/apm_cli/integration/agent_integrator.py - Add
_write_codex_agent()method: transforms.agent.md->.toml. Parse agent frontmatter (name,description) and body (instructions). Emit TOML with required Codex fields:name,description,developer_instructions. Dispatch viaformat_id == "codex_agent"inintegrate_agents_for_target(). Usetomli_wor manual TOML serialization (check existing deps). - Dependencies:
1-target-registration
- File:
-
2-skill-deploy-root-- Teach SkillIntegrator aboutdeploy_root- File:
src/apm_cli/integration/skill_integrator.py - Currently hardcodes
target.root_dir / "skills"as deploy path. Update to usemapping.deploy_root or target.root_dirwhen computing skill deploy dir. For Codex: skills deploy to.agents/skills/instead of.codex/skills/. Also updatecopy_skill_to_target()standalone function. - Dependencies:
1-deploy-root,1-target-registration
- File:
-
2-hook-codex-- Add Codex hook merge to HookIntegrator- File:
src/apm_cli/integration/hook_integrator.py - Add
integrate_package_hooks_codex()method following Claude/Cursor merge pattern. Merge hooks into single.codex/hooks.json(additive,_apm_sourcemarkers for safe cleanup). Map APM hook events to Codex lifecycle events (SessionStart,PreToolUse,PostToolUse,UserPromptSubmit,Stop). Script path rewriting to.codex/hooks/{package_name}/. Add dispatch inintegrate_hooks_for_target()fortarget.name == "codex". - Dependencies:
1-target-registration
- File:
-
2-deploy-root-integrators-- Update path computation in all integrators- Files:
agent_integrator.py,command_integrator.py,instruction_integrator.py,install.py - Each integrator that computes
project_root / target.root_dir / mapping.subdirmust usemapping.deploy_root or target.root_dirinstead. Small change per integrator (~1 line each), but critical for correctness. Also update_log_integrationdeploy_dir computation ininstall.py. - Dependencies:
1-deploy-root
- Files:
Wave 3: Install/Uninstall Flows + Compile + Scope
All parallelizable. Validates end-to-end data flows through the lockfile and uninstall pipeline.
Gate: All Wave 3 items must complete before Wave 4 starts.
-
3-lockfile-verify-- Verify lockfile with cross-rootdeployed_files- File:
src/apm_cli/commands/install.py(verify, likely zero changes) - Confirm
.agents/skills/...and.codex/agents/...paths are both recorded in the samedeployed_fileslist viatp.relative_to(project_root).as_posix(). Confirmmanaged_filesset includes paths from both roots for collision detection. Confirm.codex/hooks.jsonis NOT tracked (only script files are). Write a focused test confirming cross-rootdeployed_filesround-trip through the lockfile. - Dependencies:
2-agent-toml,2-deploy-root-integrators,2-hook-codex,2-skill-deploy-root
- File:
-
4-uninstall-codex-- Wire Codex into uninstall sync- File:
src/apm_cli/commands/uninstall/engine.py(verify + minor updates) - Codex target is automatically handled by the data-driven sync loop. Verify
partition_bucket_key()returns correct keys for Codex primitives. Verifysync_for_target()works with thedeploy_rootoverride. Special attention to.agents/skills/cleanup (different root than.codex/). Test that removing all Codex packages leaves.codex/hooks.jsonwith only user hooks. - Dependencies:
1-bucket-aliases,2-deploy-root-integrators
- File:
-
3-compile-codex-- Add Codex target toapm compile- File:
src/apm_cli/commands/compile/cli.py - Add
"codex"to compile's--targetchoices. Codex compilation emitsAGENTS.mdat repo root (same general approach as copilot target). Codex reads AGENTS.md walking from root to CWD, layering files. May need minor format adjustments vs copilot's AGENTS.md output. - Dependencies:
1-cli-choices
- File:
-
5-user-scope-- Add Codex toUSER_SCOPE_TARGETS- File:
src/apm_cli/core/scope.py - Add Codex entry to
USER_SCOPE_TARGETSwith appropriate support level. Codex user-scope config lives at~/.codex/(hooks, agents). Codex user-scope skills live at~/.agents/skills/. Determine which primitives are supported at user scope (skills, agents likely yes; hooks maybe partial). - Dependencies:
1-target-registration
- File:
Wave 4: Unit Tests
Highly parallelizable. Each test file targets one specific integration area.
Gate: All Wave 4 tests must pass before Wave 5 starts.
-
6-test-target-profile-- Test Codex target registration- File:
tests/unit/integration/test_targets.py - Test
active_targets()with.codex/directory present (auto-detect). Test explicit--target codexresolution. Test--target allincludes Codex. Test Codex is NOT detected when only.agents/exists (no.codex/). - Dependencies:
1-target-registration
- File:
-
6-test-dispatch-- Test data-driven dispatch for Codex- File:
tests/unit/integration/test_data_driven_dispatch.py - Add Codex to
TestTargetGatingRegression(no cross-target primitive writes). Add Codex toTestExhaustivenessChecks(all primitives have handlers). Testpartition_bucket_keyfor Codex primitives. Test thatdeploy_rootflows correctly through dispatch. - Dependencies:
1-bucket-aliases,2-deploy-root-integrators
- File:
-
6-test-agent-toml-- Test MD-to-TOML agent transformation- File:
tests/unit/integration/test_agent_integrator.py - Test
_write_codex_agent()with frontmatter parsing. Test withname/descriptionin frontmatter. Test with body-only (no frontmatter) -- extract from content. Test TOML output has required Codex fields. Test filename:.agent.mdsource ->.tomltarget. - Dependencies:
2-agent-toml
- File:
-
6-test-hooks-codex-- Test Codex hook merging- File:
tests/unit/integration/test_hook_integrator.py - Test merge into new
.codex/hooks.json(no existing file). Test merge into existinghooks.json(preserves user hooks). Test_apm_sourcemarkers for cleanup. Test re-install replaces old APM hooks, keeps user hooks. Test script path rewriting to.codex/hooks/{package}/. - Dependencies:
2-hook-codex
- File:
-
6-test-skill-deploy-root-- Test skill deployment to.agents/- File:
tests/unit/integration/test_skill_integrator.py - Test that Codex skills deploy to
.agents/skills/not.codex/skills/. Test that other targets still deploy to their own{root_dir}/skills/. Test skill uninstall cleans up.agents/skills/{name}/. - Dependencies:
2-skill-deploy-root
- File:
-
6-test-uninstall-codex-- Test uninstall cleanup- File:
tests/unit/integration/test_sync_integration_url_normalization.pyor new - Test
partition_managed_fileswith Codex deployed files. Test sync removes Codex-specific files from correct locations. Test.codex/hooks.jsoncleanup removes APM entries only. - Dependencies:
4-uninstall-codex
- File:
-
6-test-lockfile-crossroot-- Test cross-rootdeployed_fileslockfile round-trip- File:
tests/unit/integration/test_deployed_files_manifest.py - Test that
deployed_fileswith paths from both.codex/and.agents/roots serialize/deserialize correctly throughapm.lock.yaml. Test collision detection works across roots. - Dependencies:
3-lockfile-verify
- File:
Wave 5: Documentation + E2E
Highly parallelizable. Documentation and E2E testing can proceed independently.
Documentation
-
7-docs-integration-- Add Codex integration guide- File:
docs/src/content/docs/integrations/ide-tool-integration.md - Add "Codex CLI Integration" section alongside Claude/Cursor/OpenCode. Document which primitives are supported (skills, agents, hooks). Document auto-detection (
.codex/directory). Document format details (TOML agents,hooks.jsonschema). Document that instructions useapm compile --target codex. - Dependencies:
2-agent-toml,2-hook-codex,2-skill-deploy-root
- File:
-
7-docs-cli-ref-- Update CLI reference- File:
docs/src/content/docs/reference/cli-commands.md - Add
codexto--targetoption values for install, compile, pack. Update examples showing--target codex. - Dependencies:
1-cli-choices
- File:
-
7-docs-compilation-- Update compilation guide- File:
docs/src/content/docs/guides/compilation.md - Add Codex to target auto-detection table. Add Codex output format (AGENTS.md). Add to tool compatibility table.
- Dependencies:
3-compile-codex
- File:
-
7-docs-manifest-- Update manifest schema reference- File:
docs/src/content/docs/reference/manifest-schema.md - Add
codexto allowedtargetvalues. Document effect oftarget: codex. - Dependencies: none
- File:
-
7-docs-skills-- Update skills guide- File:
docs/src/content/docs/guides/skills.md - Add
.agents/skills/as Codex deploy path. Note that Codex uses the agent skills standard natively. - Dependencies: none
- File:
-
7-changelog-- Update CHANGELOG.md- File:
CHANGELOG.md - Add entries under
[Unreleased]>Addedfor Codex CLI target support. - Dependencies:
1-target-registration
- File:
E2E Testing with Real Codex CLI
-
8-e2e-install-- E2E: Install packages with--target codex- Create a test APM package containing skills, agents, and hooks. Run
apm install --target codexin a fresh project. Verify:.agents/skills/{name}/SKILL.mdexists and is valid. Verify:.codex/agents/{name}.tomlexists with correct TOML schema. Verify:.codex/hooks.jsonexists with merged hooks and_apm_sourcemarkers. Verify:apm.lockcontains correctdeployed_filespaths from both.codex/and.agents/roots. - Dependencies:
6-test-target-profile,6-test-agent-toml,6-test-hooks-codex,6-test-skill-deploy-root
- Create a test APM package containing skills, agents, and hooks. Run
-
8-e2e-codex-reads-- E2E: Codex CLI discovers APM-deployed primitives- Install Codex CLI (
npm install -g @openai/codexor usenpx). Deploy a test skill via APM to.agents/skills/. Runcodexand verify it discovers the skill (use/skillsTUI command). Deploy a test agent to.codex/agents/. Verify Codex lists the custom agent. Deploy hooks to.codex/hooks.jsonwithcodex_hooks = truein config. Verify hooks are loaded (check codex logs). - Dependencies:
8-e2e-install
- Install Codex CLI (
-
8-e2e-autodetect-- E2E: Auto-detection with.codex/directory- Create
.codex/config.toml(minimal valid config) in test project. Runapm install(no--targetflag). Verify Codex is auto-detected in the targets list. Verify primitives deploy to correct Codex locations. - Dependencies:
8-e2e-install
- Create
-
8-e2e-uninstall-- E2E: Uninstall cleans up Codex files- Install a package with
--target codex. Runapm uninstall {package}. Verify:.agents/skills/{name}/is removed. Verify:.codex/agents/{name}.tomlis removed. Verify:.codex/hooks.jsonretains user hooks, removes APM entries. Verify:apm.lockno longer references the removed files. - Dependencies:
8-e2e-install
- Install a package with
-
8-e2e-compile-- E2E: Compile generates AGENTS.md for Codex- Create an
apm.ymlwith instructions-bearing packages. Runapm compile --target codex. VerifyAGENTS.mdis generated at repo root. Verify content is valid Codex instruction format. Run Codex CLI and verify it reads the generatedAGENTS.md. - Dependencies:
3-compile-codex
- Create an
-
8-e2e-multi-target-- E2E: Multi-target install (copilot + codex)- Create project with both
.github/and.codex/dirs. Runapm install(auto-detect both). Verify skills deploy to BOTH.github/skills/AND.agents/skills/. Verify agents deploy to both.github/agents/*.agent.mdAND.codex/agents/*.toml. - Dependencies:
8-e2e-install
- Create project with both
Files Changed Summary
| File | Change Type | Wave |
|---|---|---|
src/apm_cli/integration/targets.py |
Modify: deploy_root field + codex target + prefixes |
W1 |
src/apm_cli/integration/base_integrator.py |
Modify: bucket aliases, partition update | W1 |
src/apm_cli/commands/install.py |
Modify: CLI choices + deploy_dir computation | W1+W2 |
src/apm_cli/integration/agent_integrator.py |
Modify: TOML transformer (~40 lines) | W2 |
src/apm_cli/integration/hook_integrator.py |
Modify: Codex hook merge (~60 lines) | W2 |
src/apm_cli/integration/skill_integrator.py |
Modify: deploy_root path (~5 lines) |
W2 |
src/apm_cli/integration/instruction_integrator.py |
Modify: deploy_root path (~2 lines) |
W2 |
src/apm_cli/integration/command_integrator.py |
Modify: deploy_root path (~2 lines) |
W2 |
src/apm_cli/commands/compile/cli.py |
Modify: CLI choices for codex | W3 |
src/apm_cli/commands/uninstall/engine.py |
Verify: data-driven, likely zero changes | W3 |
src/apm_cli/core/scope.py |
Modify: USER_SCOPE_TARGETS codex entry |
W3 |
| 7 test files | Modify: ~400 lines tests | W4 |
| 6 documentation files | Modify: Codex integration docs | W5 |
CHANGELOG.md |
Modify: release notes | W5 |
Estimated: ~200 lines production, ~400 lines tests, 0 new classes, ~20 files.
Deferred to v2
| Feature | Reason |
|---|---|
Starlark rules (.codex/rules/) |
New format family, no APM primitive maps to execution policies |
MCP server config (.codex/config.toml) |
Complex TOML section management |
| Install-time AGENTS.md with managed sections | Strong UX case, but adds unprecedented merge complexity |
| Codex plugins | APM packages already serve the distribution role |
Risk Assessment
| Risk | Level | Mitigation |
|---|---|---|
deploy_root regression on existing targets |
Low | Default None = no behavior change; full unit suite validates |
| TOML agent transform correctness | Low | ~30 lines, isolated behind format_id check, thorough tests |
| SkillIntegrator path change | Medium | Currently hardcoded; need to verify all 6 call sites use new path |
| Hook merge event mapping | Medium | Codex events differ from Claude/Cursor; need careful mapping |
| Codex CLI evolving rapidly | Low | Data-driven architecture absorbs changes via KNOWN_TARGETS only |
| Lockfile cross-root paths | Low | Already supported; confirmed by existing multi-root tests |