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 |
||
|---|---|---|
| .. | ||
| 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, 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
- 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
Using the team
Rendering + activation only configures the agents. To actually work with the team:
- Install primitives. If the package declares APM dependencies, run
apm installin the package directory (cpm setupoffers this automatically). This deploys the skills/instructions that role allowlists reference into.opencode/skills/etc. - Reload OpenCode. Agents (preset) and skills are loaded at startup.
- Sanity check. In OpenCode:
/agentslists the team members; "ping all agents" verifies they respond. - 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.