APM-Packages/corentic-package-manager/README.md
Tobias J. Endres ae6817d86f feat(cpm): integrate 'apm install' into the guided flow
The rendered preset only configures agents; the skills/instructions
that role allowlists reference are deployed by APM. cpm setup now
detects apm.yml dependencies and offers to run 'apm install' after
rendering (manual command printed when the CLI is missing or stdin
is not a TTY). render/check print it as an explicit next step.

Also:
- next steps now name the absolute directory to start opencode from
  (fixes presets appearing 'missing' when opencode runs in the wrong
  cwd, as hit during first real-world test)
- init no longer prints literal <package-dir> placeholders
- model list is shown once instead of repeating per class
- README: new 'Using the team' section (primitives -> reload ->
  sanity check -> work via orchestrator), activation writes to the
  global user config, troubleshooting entry for missing skills
2026-08-23 18:24:25 +02:00

10 KiB
Raw Blame History

Corentic Package Manager (CPM)

A CPM package is an agent package consisting of an APM manifest plus a team configuration (team-profile.yaml). The Corentic Package Manager translates this package into the native configuration of a target harness.

Translation targets:

Target harness Status
oh-my-opencode-slim implemented
oh-my-pi planned
Codex / Claude / Copilot vision

Deterministic the CPM does not guess. It assumes no availability and never picks models automatically.

CPM package                 User                        Runtime
apm.yml +            +   model-mapping.yaml   →   cpm render  →  .opencode/
team-profile.yaml        (model class →               oh-my-opencode-slim.json
(roles, model             concrete model ID)          (or later: native config
 classes, MCPs/skills)                                of another harness)

Prerequisites

  • Python 3.10+ with PyYAML (pip install pyyaml)
  • OpenCode with the oh-my-opencode-slim plugin installed
  • A CPM package with a team-profile.yaml

Quickstart

# 1. Create the model mapping  interactively, choosing from your opencode models
python3 cpm.py init --fill

# 2. Guided: read team profile, check/fill mapping, render, install primitives
cd <project>
python3 /path/to/cpm.py setup --package /path/to/package

# 3. Activate
cd /path/to/package     # the config lives in <package>/.opencode/
opencode
/preset acme-job-applications
# Reload OpenCode -> team is active (by design: no hot-swap)

Alternatively manually:

# 1. Create the model mapping once
mkdir -p ~/.config/cpm
cp examples/model-mapping.yaml ~/.config/cpm/model-mapping.yaml
$EDITOR ~/.config/cpm/model-mapping.yaml   # adapt to your own models

# 2. Validate (dry run)
python3 cpm.py check --package examples/package

# 3. Render + install package primitives
cd /path/to/package
python3 /path/to/cpm.py render --package .
apm install        # deploys skills/instructions from APM dependencies

The three files

File Owned by Purpose Edit manually?
team-profile.yaml Package author Roles, model classes, MCP/skill allowlists per role Yes (author)
~/.config/cpm/model-mapping.yaml User Model class → concrete model ID (+ optional variant/temperature) Yes (user)
.opencode/oh-my-opencode-slim.json generated Preset with concrete model IDs No always re-render

Plus a provenance file .opencode/oh-my-opencode-slim.cpm-provenance.json documenting which role received which model.

Command reference

python3 cpm.py init   [--mapping FILE] [--fill]          # create/fill mapping
python3 cpm.py setup  --package DIR [--mapping F] ...    # guided flow
python3 cpm.py render --package DIR [--mapping F] [--output F] [--dry-run]
python3 cpm.py check  --package DIR [--mapping F]        # dry-run validation

init create the mapping

Creates ~/.config/cpm/model-mapping.yaml (if not present). With --fill, all PLACEHOLDER classes are asked interactively: the CPM lists every model from your opencode.json(c), you pick by number or enter a model ID manually.

setup guided flow

The one-command path: shows the team profile in plain language, creates a missing mapping, interactively asks for missing model classes (same selection as init --fill), renders and then handles package primitives: if the package declares APM dependencies, setup offers to run apm install for you (or prints the manual command if the apm CLI is not installed).

render / check

Option Default Meaning
--package . CPM package directory containing team-profile.yaml
--mapping ~/.config/cpm/model-mapping.yaml Local mapping table
--output <package>/.opencode/oh-my-opencode-slim.json Target file
--team-file team-profile.yaml (alternatively team.yaml) Alternative profile filename

Merge behavior: Existing presets in the target file remain untouched; only the preset for this team ID is replaced. Multiple packages coexist in the same project. Activation is explicit via /preset <name>.

Team profile schema (corentic.team-profile/v1)

schema: corentic.team-profile/v1
id: acme.job-applications          # becomes the preset name (namespaced)
description: ...

roles:
  - id: researcher                 # domain role
    purpose: ...                   # becomes prompt/description for custom agents
    runtime_agent: librarian       # optional: harness builtin or 'custom'
                                   # (default: role id as custom agent)
    model_class: fast-research     # required, must exist in the mapping
    capabilities:
      mcps: [websearch, openviking]  # MCP allowlist ([] = none)
      skills: [job-application]      # skill allowlist ([] = none)

The runtime_agent field is deliberately harness-neutral: the adapter decides how the role is represented in the target harness. Builtins recognized by the oh-my-opencode-slim adapter: orchestrator, oracle, librarian, explorer, fixer, designer, council, observer. Everything else (or runtime_agent: custom) creates a custom agent including prompt and orchestratorPrompt derived from the purpose field.

Mapping formats

model_classes:
  fast-research: ollama/qwen3.5:9b              # simple
  high-reasoning:                               # extended
    model: ollama/qwen3.6:35b-a3b-q4_K_M
    variant: thinking
    temperature: 0.3

All extra fields are passed through 1:1 into the agent entry of the preset.

What the CPM checks

  1. Team profile present, schema known, id and roles present
  2. Every model_class has a mapping entry (otherwise error with fix hint)
  3. MCPs matched against ~/.config/opencode/opencode.json(c) (warning, not fatal)
  4. Roles without MCPs/skills -> note

Examples

Example Based on Team
examples/package/ Own job-application package (OpenViking + ShareLaTeX) acme.job-applications Researcher, Writer, Checker, Notifier
examples/microsoft-design-review/ Official microsoft/apm-sample-package acme.design-review Reviewer (Oracle), Style-Checker (Fixer), Accessibility-Auditor
examples/microsoft-issue-autopilot/ Official apm-issue-autopilot from the microsoft/apm repo acme.issue-autopilot Triager, Shepherd, PR-Writer, Reviewer (+ GitHub MCP)

The two Microsoft examples are thin CPM wrappers: their own apm.yml pulls the official package as a versioned APM dependency (microsoft/apm-sample-package#v1.0.0 or monorepo subpath microsoft/apm/packages/apm-issue-autopilot) and only adds the team recommendation.

cd corentic-package-manager/examples

# Dry run: what would be generated?
python3 ../cpm.py check --package package --mapping model-mapping.yaml
python3 ../cpm.py check --package microsoft-design-review --mapping model-mapping.yaml
python3 ../cpm.py check --package microsoft-issue-autopilot --mapping model-mapping.yaml

# Render into the example project
python3 ../cpm.py render --package package \
  --mapping model-mapping.yaml \
  --output package/.opencode/oh-my-opencode-slim.json

Expected result: preset acme-job-applications with five agents orchestrator, librarian (alias researcher), custom agent writer, oracle (alias checker), custom agent notifier. The researcher gets no LaTeX access, the writer sees no job-search tools, the notifier gets no external access at all.

Then:

cd package && opencode
/preset acme-job-applications

Using the team

Rendering + activation only configures the agents. To actually work with the team:

  1. Install primitives. If the package declares APM dependencies, run apm install in the package directory (cpm setup offers this automatically). This deploys the skills/instructions that role allowlists reference into .opencode/skills/ etc.
  2. Reload OpenCode. Agents (preset) and skills are loaded at startup.
  3. Sanity check. In OpenCode: /agents lists the team members; "ping all agents" verifies they respond.
  4. Work via the orchestrator. Just state your task in normal language e.g. "Review the components in src/ against our design standards". The orchestrator decomposes it and delegates according to the generated routing prompts: style violations → @style-checker, design judgment → @reviewer, audits → the auditor agent. It then consolidates the findings.

Two things to know:

  • The preset switch (/preset) and skill loading both require an OpenCode restart/reload by design.
  • Activating a preset writes its name to your global user config (~/.config/opencode/oh-my-opencode-slim.json), so it persists across sessions and projects until you switch again.

Troubleshooting

Problem Cause/Fix
Model class X is not mapped Add to the mapping, re-render
Warning: MCP ... not configured Set up the MCP in opencode.jsonc or remove it from the profile
/preset does not show anything new Start opencode in the directory containing .opencode/ and reload; presets do not apply mid-session
Agent references a skill that does not exist Run apm install in the package directory the preset only configures agents, primitives come from APM
Preset lost after manual editing The file is generated changes belong in the mapping or team profile
YAML errors Follow the line number in the error message

Deliberate limits

  • The CPM does not start agents and orchestrates nothing at runtime that is the job of the target harness.
  • MCP/skill allowlists are capability scoping, not a sandbox. Irreversible actions need server-side authorization + human approval.
  • Model availability is checked against opencode.json(c) names, not via API health checks.