Repository navigation
Description
Summary
V2 silently drops any agent whose frontmatter color is a V1 theme color name (primary, secondary, accent, success, warning, error, info). The agent disappears from the agent registry with no warning. In a real global config this dropped 8 of 9 custom agents. V1 accepted these names, and the migration guide says V2 translates legacy agent frontmatter automatically, so this is a compatibility regression rather than an expected migration step.
Environment
- opencode version: 2.0.26
- OS: Darwin 27.0.0 (macOS, arm64)
- Terminal: ghostty (
TERM_PROGRAM=ghostty,TERM=xterm-256color,COLORTERM=truecolor) - Shell: /bin/zsh
- Install/channel: Homebrew (
opencode-v2formula, latest) - Active plugins: none
Reproduction
-
Create a global agent file
~/.config/opencode/agents/demo.mdusing a V1 theme color name:--- description: demo agent mode: subagent color: accent --- Body.
-
Reload/start OpenCode and inspect the agent registry:
opencode debug agents # or opencode api get /api/agent -
demois absent from the list. -
Change only the color to a six-digit hex:
color: "#9d7cd8"
-
demonow appears.
Expected Behavior
Per the V1→V2 migration guide, "V2 translates legacy agent frontmatter automatically", and the V1 docs list theme color names (primary, secondary, accent, success, warning, error, info) as valid color values. Existing agents using those names should keep loading (and ideally resolve to the theme's corresponding color). V2's current agent docs describe color as a six-digit hex value, so a graceful translation or at least a warning is expected.
Actual Behavior
An agent whose color is a theme color name is silently omitted from the agent registry. No warning or error is logged, and no other fields are reported. A hex color loads correctly.
The failure is also masked by the V1 permission field: an agent that has a V1 permission block still loads despite a theme-name color, apparently because it takes a legacy parse path. Its color then resolves to the fallback #aaaaaa instead of the theme color. Converting that block to the documented V2 permissions array (as the migration guide instructs) removes the legacy path, and the agent is then dropped — so applying the documented migration can break an agent that previously worked.
Concretely, with a file like:
---
description: orchestrator
mode: subagent
color: warning
permissions:
- action: subagent
resource: "*"
effect: deny
---
Body.the agent is not registered, while the same file with permission: { task: { "*": deny } } (V1) is registered.
Additional Context
- Verified repeatedly via both
opencode debug agentsandopencode api get /api/agent; results were consistent once the async reload settled. - Controlled tests:
color: accent,color: warning, andcolor: successeach dropped the agent;color: "#ff6b6b"and omittingcolorboth loaded. - This affects the preferred V2 global location
~/.config/opencode/agents/<name>.md; existing V1 setups commonly use theme color names. - Workaround: replace theme color names with a six-digit hex before migrating, or leave the agent's
permissionblock in the V1 form. - Impact: agents disappear silently, so users may believe a migrated agent is active when it is not.
Activity
opencode-agent commentedon Oct 9, 2026
Thanks for the detailed report. I reproduced this on 2.0.26, and it still happens on the latest
v2commit (eefe85d) run from source.I used a separate, empty config directory with global agents in
~/.config/opencode/agents/, then ranopencode debug agents(repeating it until the list settled):color: accent,color: warningandcolor: successeach make the agent disappear, with no warning.color: "#9d7cd8"and no color both load.color: warningwith a v2permissionsarray: the agent is dropped.color: warningwith a v1permissionblock: the agent loads, but its color becomes#aaaaaa.From reading the code, it looks like files with only v2 fields are checked against a hex-only
colorrule, and a file that fails that check is skipped without a log message. Files with v1-only fields go through the legacy translation, which accepts the color name but replaces it with#aaaaaa.The script below reproduces it. Until this is fixed, your workaround of using a six-digit hex
colorkeeps the agents loading.Reproduction script (repro.sh)
Run it:
bash repro.shabinawahasan-bot commentedon Oct 18, 2026
Confirming on the current release: this still reproduces on 2.0.32.
Real-world impact (a real global
~/.config/opencode/agents/with 58 custom agent files): 13 of 58 were silently dropped — the ones whose frontmatter had onlydescription/mode/color: <theme name>and no V1-only key. The dropped files includedorchestrator(mode: all),architect, and the developer/engineer/reviewer agents. Becauseorchestratorwas still selectable as the configureddefault_agent, it kept running with an empty system prompt (0 chars) — its ~18K prompt was silently lost, with no warning anywhere.Controlled matrix on 2.0.32
Base frontmatter
description+mode: subagent; only the last field(s) varied. Checked after a full server restart (opencode reloadimmediately after creating the files is racy — the list can read empty until the async scan settles):color: accentcolor: "#ff8800"color)color: accent+permission: {}color: accent+temperature: 0.3color: accent+top_p: 0.9color: accent+hidden: falseRefinement to the two-parse-path diagnosis
The rescue is not "any extra key" — it is specifically a V1-only field (
permission,temperature,top_p) forcing the legacy path.hiddenis accepted by both schemas, sohidden: falsedoes not rescue the file. That matches: files that don't hit the legacy path are validated against the hex-onlycolorrule and dropped without a log line.Minimal, behavior-preserving workaround
Instead of converting theme names to hex (loses the theme color) or keeping a V1
permissionblock, an empty V1 block is enough:permission: {}yields an identical effective permission ruleset to having nopermissionkey at all, so it changes no behavior while keeping the theme color name.Just adding the release confirmation, the real-world scope, and the
hiddendata point on top of the root-cause analysis above.