Skip to content

Support Codex CLI as integration target #502

@danielmeppiel

Description

@danielmeppiel

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 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.sh

Note: .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 via deploy_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 -- Add deploy_root to PrimitiveMapping

    • File: src/apm_cli/integration/targets.py
    • Add deploy_root: Optional[str] = None field to PrimitiveMapping dataclass. When deploy_root is not None, integrators use it instead of target.root_dir for path computation. Default None preserves all existing behavior (zero regression risk).
    • Dependencies: none
  • 1-target-registration -- Register Codex in KNOWN_TARGETS

    • File: src/apm_cli/integration/targets.py
    • Add "codex" TargetProfile to KNOWN_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
  • 1-security-prefixes -- Update security validation for .agents/ prefix

    • File: src/apm_cli/integration/targets.py
    • Update get_integration_prefixes() to also emit prefixes from deploy_root values. Ensures .agents/ is in the allowed prefix set for validate_deploy_path(). Do NOT add empty string "" as prefix (repo-root AGENTS.md needs explicit handling if added later).
    • Dependencies: 1-deploy-root
  • 1-cli-choices -- Add "codex" to --target CLI option

    • Files: src/apm_cli/commands/install.py, src/apm_cli/commands/compile/cli.py, pack commands
    • Add "codex" to the click.Choice list for --target option across install, compile, and pack commands.
    • Dependencies: none
  • 1-bucket-aliases -- Add Codex bucket aliases for partition_managed_files

    • File: src/apm_cli/integration/base_integrator.py
    • Add bucket alias entries for Codex primitives (e.g., agents_codex). Ensure partition_managed_files() handles the .agents/ root for skills correctly within the O(1) component-based path routing.
    • Dependencies: 1-target-registration

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 via format_id == "codex_agent" in integrate_agents_for_target(). Use tomli_w or manual TOML serialization (check existing deps).
    • Dependencies: 1-target-registration
  • 2-skill-deploy-root -- Teach SkillIntegrator about deploy_root

    • File: src/apm_cli/integration/skill_integrator.py
    • Currently hardcodes target.root_dir / "skills" as deploy path. Update to use mapping.deploy_root or target.root_dir when computing skill deploy dir. For Codex: skills deploy to .agents/skills/ instead of .codex/skills/. Also update copy_skill_to_target() standalone function.
    • Dependencies: 1-deploy-root, 1-target-registration
  • 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_source markers 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 in integrate_hooks_for_target() for target.name == "codex".
    • Dependencies: 1-target-registration
  • 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.subdir must use mapping.deploy_root or target.root_dir instead. Small change per integrator (~1 line each), but critical for correctness. Also update _log_integration deploy_dir computation in install.py.
    • Dependencies: 1-deploy-root

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-root deployed_files

    • File: src/apm_cli/commands/install.py (verify, likely zero changes)
    • Confirm .agents/skills/... and .codex/agents/... paths are both recorded in the same deployed_files list via tp.relative_to(project_root).as_posix(). Confirm managed_files set includes paths from both roots for collision detection. Confirm .codex/hooks.json is NOT tracked (only script files are). Write a focused test confirming cross-root deployed_files round-trip through the lockfile.
    • Dependencies: 2-agent-toml, 2-deploy-root-integrators, 2-hook-codex, 2-skill-deploy-root
  • 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. Verify sync_for_target() works with the deploy_root override. Special attention to .agents/skills/ cleanup (different root than .codex/). Test that removing all Codex packages leaves .codex/hooks.json with only user hooks.
    • Dependencies: 1-bucket-aliases, 2-deploy-root-integrators
  • 3-compile-codex -- Add Codex target to apm compile

    • File: src/apm_cli/commands/compile/cli.py
    • Add "codex" to compile's --target choices. Codex compilation emits AGENTS.md at 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
  • 5-user-scope -- Add Codex to USER_SCOPE_TARGETS

    • File: src/apm_cli/core/scope.py
    • Add Codex entry to USER_SCOPE_TARGETS with 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

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 codex resolution. Test --target all includes Codex. Test Codex is NOT detected when only .agents/ exists (no .codex/).
    • Dependencies: 1-target-registration
  • 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 to TestExhaustivenessChecks (all primitives have handlers). Test partition_bucket_key for Codex primitives. Test that deploy_root flows correctly through dispatch.
    • Dependencies: 1-bucket-aliases, 2-deploy-root-integrators
  • 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 with name/description in frontmatter. Test with body-only (no frontmatter) -- extract from content. Test TOML output has required Codex fields. Test filename: .agent.md source -> .toml target.
    • Dependencies: 2-agent-toml
  • 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 existing hooks.json (preserves user hooks). Test _apm_source markers for cleanup. Test re-install replaces old APM hooks, keeps user hooks. Test script path rewriting to .codex/hooks/{package}/.
    • Dependencies: 2-hook-codex
  • 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
  • 6-test-uninstall-codex -- Test uninstall cleanup

    • File: tests/unit/integration/test_sync_integration_url_normalization.py or new
    • Test partition_managed_files with Codex deployed files. Test sync removes Codex-specific files from correct locations. Test .codex/hooks.json cleanup removes APM entries only.
    • Dependencies: 4-uninstall-codex
  • 6-test-lockfile-crossroot -- Test cross-root deployed_files lockfile round-trip

    • File: tests/unit/integration/test_deployed_files_manifest.py
    • Test that deployed_files with paths from both .codex/ and .agents/ roots serialize/deserialize correctly through apm.lock.yaml. Test collision detection works across roots.
    • Dependencies: 3-lockfile-verify

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.json schema). Document that instructions use apm compile --target codex.
    • Dependencies: 2-agent-toml, 2-hook-codex, 2-skill-deploy-root
  • 7-docs-cli-ref -- Update CLI reference

    • File: docs/src/content/docs/reference/cli-commands.md
    • Add codex to --target option values for install, compile, pack. Update examples showing --target codex.
    • Dependencies: 1-cli-choices
  • 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
  • 7-docs-manifest -- Update manifest schema reference

    • File: docs/src/content/docs/reference/manifest-schema.md
    • Add codex to allowed target values. Document effect of target: codex.
    • Dependencies: none
  • 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
  • 7-changelog -- Update CHANGELOG.md

    • File: CHANGELOG.md
    • Add entries under [Unreleased] > Added for Codex CLI target support.
    • Dependencies: 1-target-registration

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 codex in a fresh project. Verify: .agents/skills/{name}/SKILL.md exists and is valid. Verify: .codex/agents/{name}.toml exists with correct TOML schema. Verify: .codex/hooks.json exists with merged hooks and _apm_source markers. Verify: apm.lock contains correct deployed_files paths from both .codex/ and .agents/ roots.
    • Dependencies: 6-test-target-profile, 6-test-agent-toml, 6-test-hooks-codex, 6-test-skill-deploy-root
  • 8-e2e-codex-reads -- E2E: Codex CLI discovers APM-deployed primitives

    • Install Codex CLI (npm install -g @openai/codex or use npx). Deploy a test skill via APM to .agents/skills/. Run codex and verify it discovers the skill (use /skills TUI command). Deploy a test agent to .codex/agents/. Verify Codex lists the custom agent. Deploy hooks to .codex/hooks.json with codex_hooks = true in config. Verify hooks are loaded (check codex logs).
    • Dependencies: 8-e2e-install
  • 8-e2e-autodetect -- E2E: Auto-detection with .codex/ directory

    • Create .codex/config.toml (minimal valid config) in test project. Run apm install (no --target flag). Verify Codex is auto-detected in the targets list. Verify primitives deploy to correct Codex locations.
    • Dependencies: 8-e2e-install
  • 8-e2e-uninstall -- E2E: Uninstall cleans up Codex files

    • Install a package with --target codex. Run apm uninstall {package}. Verify: .agents/skills/{name}/ is removed. Verify: .codex/agents/{name}.toml is removed. Verify: .codex/hooks.json retains user hooks, removes APM entries. Verify: apm.lock no longer references the removed files.
    • Dependencies: 8-e2e-install
  • 8-e2e-compile -- E2E: Compile generates AGENTS.md for Codex

    • Create an apm.yml with instructions-bearing packages. Run apm compile --target codex. Verify AGENTS.md is generated at repo root. Verify content is valid Codex instruction format. Run Codex CLI and verify it reads the generated AGENTS.md.
    • Dependencies: 3-compile-codex
  • 8-e2e-multi-target -- E2E: Multi-target install (copilot + codex)

    • Create project with both .github/ and .codex/ dirs. Run apm install (auto-detect both). Verify skills deploy to BOTH .github/skills/ AND .agents/skills/. Verify agents deploy to both .github/agents/*.agent.md AND .codex/agents/*.toml.
    • Dependencies: 8-e2e-install

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

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions