CPM is an international project; only the blogpost stays German. Translated: cpm.py docstring/messages/help texts, README.md, cpm-setup skill, all team-profile.yaml files (incl. runtime_agent comments), example apm.yml wrappers and the model-mapping template. Also fixes DEFAULT_MAPPING_PATH pointing to ~/.config/apm-team instead of ~/.config/cpm. |
||
|---|---|---|
| .. | ||
| examples | ||
| skills/cpm-setup | ||
| .gitignore | ||
| cpm.py | ||
| README.md | ||
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
cd <project>
python3 /path/to/cpm.py setup --package /path/to/package
# 3. Activate
opencode # project config gets loaded
/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
cd <project>
python3 /path/to/cpm.py render --package /path/to/package
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 prints the activation steps.
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
- Team profile present, schema known,
idandrolespresent - Every
model_classhas a mapping entry (otherwise error with fix hint) - MCPs matched against
~/.config/opencode/opencode.json(c)(warning, not fatal) - 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
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 |
Reload OpenCode after rendering; presets do not apply mid-session |
| 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.