Native APM Support for Jackin Agent Roles
Status: Open — design proposal
Summary
Section titled “Summary”Add convention-based support for Microsoft APM, the Agent Package Manager, in Jackin role repositories, and make it the long-term replacement for Jackin-owned agent-context packaging. If a role repository contains apm.yml next to jackin.role.toml, Jackin should run APM inside the isolated role environment before launching the selected agent. Jackin should not generate, translate, or mutate apm.yml; APM remains the package manager and role authors manage their own APM manifest. Jackin only orchestrates installation, target override, lockfile enforcement, isolation, logging, errors, and caching.
APM is close to Jackin’s role-dependency problem space: the APM project describes itself as a dependency manager for AI agent configuration, with one apm.yml declaring skills, prompts, instructions, plugins, and MCP servers across targets such as Claude Code, Codex, OpenCode, Cursor, GitHub Copilot, Gemini, Windsurf, and others. Its docs also describe lockfiles, target selection, policy and audit concepts, marketplaces, and install-time handling for agent context packages.
Strategic Direction
Section titled “Strategic Direction”APM should become Jackin’s dependency and agent-context packaging layer. Jackin should keep the parts APM does not try to own: sandbox lifecycle, role repository resolution, Docker image construction, per-workspace and per-role auth forwarding, host-mutation guardrails, mount isolation, runtime launch, TUI/CLI orchestration, and per-instance state recovery. Jackin should stop growing its own plugin, marketplace, skill, MCP dependency, or package ecosystem unless APM cannot cover a concrete requirement after a focused upstream evaluation.
The current Jackin implementation already overlaps with APM in several places:
jackin.role.tomlhas[claude] plugins = [...]and[[claude.marketplaces]], which Jackin converts intoclaude plugin marketplace addandclaude plugin installDockerfile layers.- The derived image snapshots
/home/agent/.claude,/home/agent/.codex,/home/agent/.local/share/amp,/home/agent/.kimi, and/home/agent/.local/share/opencodeinto/jackin/default-homeso image-baked runtime context survives first launch. - Runtime startup seeds those defaults into durable per-instance homes, then overlays auth handoff files.
- Separate roadmap work such as workspace skill mounts and Jackin-managed skill bundles duplicates parts of APM’s skills/package/distribution model.
That overlap should be intentionally reduced. APM should own role-declared agent context packages. Jackin should own where and when those packages are installed, and should guarantee the install happens inside the container boundary.
Design Stance
Section titled “Design Stance”jackin.role.toml stays Jackin’s role contract. It owns Jackin-specific metadata and launch semantics, such as the role name, supported Jackin agent runtimes, default agent, environment prompts, hooks, and Jackin-specific role behavior.
apm.yml stays APM’s dependency contract. It owns APM-native dependencies, MCP server declarations, plugin marketplaces, APM targets for standalone use, and any APM-native settings.
The first version should not add an [apm] section to jackin.role.toml. Native support should be purely convention-based at the root of each standalone role repository. For example, the chainargos/backend-engineer role maps to a separate chainargos/jackin-backend-engineer repository with this root layout:
jackin-backend-engineer/ jackin.role.toml apm.yml apm.lock.yaml Dockerfile scripts/If apm.yml exists next to jackin.role.toml, Jackin installs it. If it does not exist, Jackin does nothing APM-related.
Replacement Plan for Existing Jackin Features
Section titled “Replacement Plan for Existing Jackin Features”Jackin’s Claude plugin manifest fields should be removed after APM support lands:
- Remove
[claude].plugins. - Remove
[[claude.marketplaces]]. - Remove the derived-Dockerfile
claude plugin marketplace add/claude plugin installgeneration. - Stop scaffolding
plugins = []in new role repositories. - Move role-author documentation for Claude plugins, marketplaces, skills, prompts, agents, and MCP servers to
apm.ymlexamples.
This is a role-manifest schema change, so it requires a CURRENT_MANIFEST_VERSION bump, a manifest migration registry step, migration fixtures, and a schema-version timeline entry. Normal Jackin launch should not generate apm.yml, but jackin role migrate is the explicit role-author migration tool and should be allowed to create or update apm.yml when converting legacy Jackin-owned plugin fields. Recommended migration behavior: remove empty legacy defaults such as plugins = []; when non-empty [claude].plugins or [[claude.marketplaces]] are present, automatically create or update apm.yml, move those dependencies into the APM manifest, preserve the role’s Jackin metadata in jackin.role.toml, and remove the legacy fields from the migrated manifest.
After the migration lands, the runtime should not carry compatibility code for the old fields. A role manifest stamped with an older version should fail at startup with a clear message that the manifest schema is unsupported until the role author runs jackin role migrate <role-repo-path> or the standalone jackin-role migrate <role-repo-path> binary in CI. That migration command should be the only compatibility bridge; once it has rewritten the role, the new schema is the only shape Jackin understands.
Role resolution must preserve Jackin’s version-gated decode invariant. The resolver must read the manifest as a raw TOML document, check the version field, and only deserialize into the current RoleManifest struct after the file is known to be current or after an available migration has been applied. This matters because the current struct will no longer contain removed fields such as [claude].plugins and [[claude.marketplaces]]; trying to deserialize first would turn a migratable old manifest into an unrecoverable unknown-field parse error. The load path should therefore do the same kind of pre-deserialize migration gate that config and workspace files already use: older-but-supported role manifests are migrated before decode, newer/unknown manifests fail with “upgrade Jackin” or “no migration path” guidance, and only current manifests are decoded.
Roadmap items that propose Jackin-owned skill/package distribution should be revisited after this lands. The likely outcome is:
- The workspace skill mount item becomes either unnecessary or narrower: local/team skills should be represented as APM local-path dependencies where possible.
- Jackin-managed skill bundles, such as future tag-protocol skills, should be published as APM packages instead of as a custom Jackin marketplace.
- Runtime-specific MCP setup should prefer APM MCP declarations; Jackin should only keep hardwired runtime setup for security tools or orchestration features that are genuinely part of the sandbox contract.
Non-goals
Section titled “Non-goals”- Do not replace Jackin role TOML with APM YAML.
- Do not generate
apm.ymlfromjackin.role.tomlduring normal launch. - Do not translate
jackin.role.tomlfields into APM dependencies at runtime. - Do not keep runtime compatibility shims for legacy Jackin-owned plugin fields after the schema migration lands.
- Do not mutate a role author’s
apm.yml. - Do not rely on APM auto-detection inside the container.
- Do not run APM against the operator’s host configuration.
- Do not invent a Jackin-specific package manager while APM remains a viable upstream dependency manager for agent context.
Proposed Behavior
Section titled “Proposed Behavior”When Jackin resolves a role repository, it checks for apm.yml next to jackin.role.toml. If the file is present, Jackin runs APM from inside the role container or role build environment, never directly on the host.
The role-level install is different from APM’s default project-level install. Jackin roles are meant to provide agent context across whatever workspace the operator mounts, not mutate the operator’s project repository. The implementation should prefer APM’s user-scope install shape inside the container (--global) or an equivalent staging-home approach so deployed primitives land under container-local runtime config paths such as /home/agent/.claude, /home/agent/.codex, and /home/agent/.config/opencode, then flow through Jackin’s existing /jackin/default-home snapshot and durable-home seeding model. If APM cannot consume a role-repo apm.yml directly in --global mode, Jackin should stage the role’s apm.yml and apm.lock.yaml into a temporary container-local HOME/.apm/ area and run APM there without writing the role repo or host project tree.
Jackin should always pass an explicit --target value. APM target precedence is --target CLI flag, then apm.yml targets:, then auto-detection, and Jackin knows which runtime or runtimes the current session selected. Relying on auto-detection would let marker directories such as .claude/, .codex/, .cursor/, or other runtime config paths influence behavior accidentally.
Examples:
apm install --global --target claudeapm install --global --target codexapm install --global --target claude,codexRole authors may still include targets: in apm.yml so the same manifest works when run directly with APM outside Jackin. Jackin’s launch path should override those targets without editing the file.
Lockfile and Reproducibility
Section titled “Lockfile and Reproducibility”If apm.lock.yaml exists next to apm.yml, Jackin should run:
apm install --global --target <targets> --frozenIf apm.lock.yaml is missing, Jackin may run:
apm install --global --target <targets>The missing-lockfile path must warn that the role is not fully pinned or reproducible. If APM generates a lockfile during install, Jackin should either place the generated lockfile in the role build/cache area or surface it as an artifact the role author should commit to the role repository. The design pass should choose one behavior and document it before implementation.
Successful installs should be cacheable when apm.yml, apm.lock.yaml, the APM version, and selected targets are unchanged.
Isolation and Host-side Effects
Section titled “Isolation and Host-side Effects”APM must run inside the Jackin role container or role build environment. It must not write to the operator’s host HOME, host agent config directories, host MCP config, host APM cache/config paths, host Git config, or any other host-side state.
The implementation should force container-local paths for:
HOME- Claude config directories
- Codex config directories
- MCP config files
- APM cache/config paths, if APM exposes configurable locations
- Any runtime-specific directories for targets Jackin supports
This requirement is part of Jackin’s host-mutation hard rule: all smoothing needed to make a role work belongs inside the container or role build environment. The only acceptable host-side writes are explicit, opt-in, surfaced operator actions, and APM integration should not need any.
Install Timing to Decide
Section titled “Install Timing to Decide”The design pass should decide where APM installation belongs in the lifecycle:
- During role image build
- During first role startup
- During every role startup with a cache and frozen lockfile
- Manually through a command such as
jackin role prepareor a narrower APM-specific role command
Likely desired behavior:
- Reproducible roles run APM during role preparation/build and cache the result.
- Development roles can opt into startup-time install while iterating on
apm.yml. apm.lock.yamlis the determinant for frozen, deterministic installs.- Repeated installs are avoided when the role’s APM inputs and selected targets have not changed.
Acceptance Criteria
Section titled “Acceptance Criteria”- Jackin detects
apm.ymlnext tojackin.role.toml. - Jackin runs APM inside the role container/environment, not on the host.
- Jackin installs role-declared APM dependencies into container-local role/runtime state, not into the operator’s mounted project repository.
- Jackin passes explicit
--targetbased on the selected agent or selected agents. - Jackin respects
apm.lock.yaml. - Jackin uses
--frozenwhen the lockfile exists. - Jackin warns when the lockfile is missing.
- Normal Jackin launch does not generate
apm.yml. jackin role migrateautomatically converts legacy[claude].pluginsand[[claude.marketplaces]]intoapm.ymland removes those fields fromjackin.role.toml.- Startup rejects older role-manifest versions that still use the removed Jackin-owned plugin fields and points to the migration command.
- Jackin does not require an
[apm]section injackin.role.toml. - Jackin does not mutate the role’s APM manifest.
- Jackin no longer has its own Claude plugin marketplace installer after the replacement phase lands.
- Role resolution checks the manifest version before deserializing into
RoleManifest. - Older-but-supported role manifests are migrated before current-schema decode; newer or unsupported versions fail with a clear error.
- Jackin captures APM install logs clearly.
- Jackin fails with a useful error if APM install fails.
- Jackin caches successful APM installs when
apm.ymlandapm.lock.yamlare unchanged. - Tests cover roles with and without
apm.yml. - Tests cover target override behavior.
- Tests prove APM writes into the container/role environment, not the host.
Implementation Phases
Section titled “Implementation Phases”Phase 1: Detection and execution
Section titled “Phase 1: Detection and execution”Detect apm.yml next to jackin.role.toml, run APM inside the role container or role build environment with an explicit target, capture logs, and fail clearly on errors. Prefer a container-local user-scope/staging-home install so role dependencies become image/default-home context rather than project-repo mutations.
Phase 1b: Schema migration and removal
Section titled “Phase 1b: Schema migration and removal”Bump the role manifest schema, remove [claude].plugins and [[claude.marketplaces]] from the current serde shape, and add a migration that automatically converts existing role manifests to the APM shape. The migration should create or update apm.yml, add equivalent APM dependencies and marketplace references where APM supports them, remove the legacy fields from jackin.role.toml, and leave startup with no legacy plugin installer path. Role resolution must run the raw-document version/migration gate before RoleManifest deserialization so migrated old manifests never hit deny_unknown_fields on removed fields. Newer manifests and old manifests with no registry path should fail with migration/upgrade instructions rather than being tolerated by runtime fallback code.
Phase 2: Lockfile and reproducibility
Section titled “Phase 2: Lockfile and reproducibility”Detect apm.lock.yaml, pass --frozen when it exists, warn when it is missing, and add a cache key based on apm.yml, apm.lock.yaml, APM version, selected targets, and the chosen APM install scope.
Phase 3: Target mapping
Section titled “Phase 3: Target mapping”Map Jackin agent runtime names to APM target names, starting with claude and codex, then extending to other runtimes Jackin supports. Always pass explicit --target and test that Jackin never relies on APM auto-detection.
Phase 4: Isolation hardening
Section titled “Phase 4: Isolation hardening”Ensure HOME, agent config paths, MCP config paths, and APM cache/config paths are container-local. Add tests that host .claude, .codex, MCP config, and other relevant host paths are not modified.
Phase 5: Compatibility testing
Section titled “Phase 5: Compatibility testing”Test representative APM inputs: mattpocock/skills, mattpocock/skills/skills/engineering/tdd, frontend-design@claude-plugins-official, direct MCP declarations such as io.github.github/github-mcp-server, and JuliusBrussee/caveman. Document known limitations instead of assuming every Claude plugin behavior is preserved just because APM can resolve it.
Phase 6: Documentation
Section titled “Phase 6: Documentation”Document how role authors add apm.yml, provide Claude/Codex/multi-agent examples, explain lockfile recommendations, explain target override behavior, and state clearly that normal Jackin launch does not own or generate APM manifests. Replace the existing Jackin-owned Claude plugin and marketplace examples with APM examples, and document that jackin role migrate performs the one-time conversion for legacy role manifests.
Research Notes
Section titled “Research Notes”APM appears to be the closest existing tool for this problem. It supports agent skills, prompts, instructions, agents, Claude plugin collections, MCP server declarations, multiple target runtimes, lockfiles, marketplaces, and policy/audit concepts.
APM package layouts include .apm/ package directories, root SKILL.md skill bundles, nested skills/<name>/SKILL.md skill collections, and Claude plugin collections via plugin.json or .claude-plugin/.
APM can install from GitHub repositories, virtual subdirectories, local paths, and marketplaces. The APM docs describe installing packages by repository, adding MCP servers directly, using explicit targets, and using lockfiles for reproducible setup.
Researched examples:
mattpocock/skillsinstalled as a skill collection in testing, including individual skills through virtual subdirectories such asmattpocock/skills/skills/engineering/tdd.JuliusBrussee/cavemanwas recognized as a Claude plugin/marketplace-shaped package and installed skills and agents for Claude/Codex, but plugin hook behavior appeared only partially preserved in testing. Jackin should not assume every complex Claude plugin is fully supported through APM without compatibility notes or post-install support.claude.com/pluginsis a catalog, not the install source. The APM-consumable source is the official Anthropic plugin marketplace repository,anthropics/claude-plugins-official;apm marketplace add anthropics/claude-plugins-officiallisted 203 plugins during testing, andfrontend-design@claude-plugins-officialinstalled cleanly as a skill. Some MCP-heavy plugins may still need direct MCP declaration inapm.ymlinstead of relying on plugin metadata.
Open Questions
Section titled “Open Questions”- Should APM be preinstalled in Jackin base role images, or installed on demand?
- Should Jackin support a global setting to disable APM installs?
- Should Jackin support offline or frozen-only mode?
- Where should APM caches live inside a role container?
- Should APM install happen during image build, role preparation, or session startup?
- How should Jackin expose APM install failures in the UI/TUI?
- Should Jackin allow multiple targets for one role session, or only the selected active agent?
- How should Jackin handle roles where
apm.ymltargets:conflicts withjackin.role.tomlsupported agents? - Should Jackin validate that requested APM targets are supported by the role before running install?
- Should Jackin provide a command like
jackin role apm install, or keep the integration entirely automatic? - Should Jackin add special compatibility handling for packages known to be partially supported by APM, such as complex Claude plugins with hooks?