Repository navigation
OpenCode V2: install skips an existing opencode.json, so no agents and no skills path are ever wired #3559
Description
Summary
On a machine that already has ~/.config/opencode/opencode.json, an OpenCode install copies the whole catalog but never writes ECC's config, so the pieces that depend on config are silently missing. Two separate consequences:
-
No agents are installed. The opencode target declares its 26 subagents inside
.opencode/opencode.jsonunder theagentmap (each withprompt: "{file:prompts/agents/<name>.txt}"). It does not shipagents/*.mdfiles. Because that config file is skipped,~/.config/opencode/ends up with noplanner,tdd-guide,code-reviewer,security-reviewer, ... — whilecommands/*.mdreference exactly those agents in frontmatter (commands/plan.md→agent: planner,commands/tdd.md→agent: tdd-guide). 14 of the installed commands delegate to an agent that does not exist. -
skills.pathsis never applied. The template sets"skills": { "paths": ["../skills"] }, which is CWD-relative. It resolves against the user's project directory (e.g.D:/School/skills), not the installed config root. (Same finding as the note in PR fix: port OpenCode plugin from v1 to v2 plugin API #3536; reported here because it is a consequence of the skip for existing-config users.)
Separately: on OpenCode V2 the top-level instructions field is accepted but its entries are not loaded (V2 docs: "OpenCode accepts this field but does not load its entries; use AGENTS.md for instructions"). ECC relies on instructions for its curated instruction set, so none of it takes effect on V2 regardless of whether the config file is written.
Why the config is never written
scripts/lib/install/ownership-guard.js:77-89: a copy-file operation is skipped with a warning when the destination already exists and is not recorded as ECC-managed in the previous install-state — correct behavior for user-owned files, but it also means the ECC config template is never applied to anyone who already has an opencode.json:
Skipped user-owned file ~/.config/opencode/opencode.json: the existing file is not recorded in ECC install-state.
So the install reports success, writes ~1100 files, and leaves the active config completely unwired.
Repro
Windows 11, native. OpenCode v2.0.26. ECC 2.2.3.
git clone https://github.com/affaan-m/ECC
cd ECC
npm install
npm run build:opencode
node scripts/install-apply.js --target opencode --profile full --no-hooks(with an existing ~/.config/opencode/opencode.json present)
Observed
- Install completes:
Operations: 835planned,Skipped operations: 3(package.json,package-lock.json,opencode.json). ~/.config/opencode/agents/contains no ECC agents.commands/plan.mdfrontmatter:agent: planner— that agent does not exist.~/.config/opencode/opencode.jsonhas no ECC keys (noplugin/plugins, noagent/agents, noskills, nocommand/commands).~/.config/opencode/instructions/INSTRUCTIONS.mdis written to disk but nothing loads it on V2.
Impact
Users with an existing OpenCode config get a partial install that looks complete: commands appear (they are discovered from the commands/ directory) but every command that delegates to an ECC agent cannot resolve it, and the curated instructions never load. This is close to "installed but does nothing useful", which is likely a strong uninstall trigger.
Suggested fixes
- Do not skip the config outright. Merge only ECC-owned keys into an existing
opencode.json(preserving user keys) and record them as managed, so repair/uninstall can reverse them.deepMergeJsonalready exists inscripts/lib/install/json-ops.js. - Ship the 26 opencode agents as file-based definitions (
agents/<name>.mdwithdescription+mode: subagent) instead ofagententries in config. Then agents do not depend on the config file at all, and they are discovered by directory. - Replace the
instructionsarray with anAGENTS.mdfor V2 (global~/.config/opencode/AGENTS.md), since V2 does not loadinstructions. - Make
skills.pathsabsolute to the installed config root, or drop it and rely on V2's automatic discovery of the config directory'sskills/.
Relations
- OpenCode V2 fails to load ECC plugin (V1 format: needs id + setup) #3537 / PR fix: port OpenCode plugin from v1 to v2 plugin API #3536 cover the V2 plugin API break. This issue is independent: it affects the already-ported plugin too, and persists after the plugin loads.
- [Problem] Opencode there is simple step by step guide? V2 seems currently its for V1 #3229 asks for a V2 guide; this is the concrete install-level gap behind that request.
Environment
- ECC 2.2.3
- OpenCode v2.0.26
- Windows 11, native (no WSL)
Activity
Ducquangbill commentedon Oct 13, 2026
Additional finding: uninstall writes a Claude-harness state store on an OpenCode-only machine
Related residue from the same target, found while verifying the uninstall path.
On a machine that has never used Claude Code (no
~/.claudeat all), running the OpenCode uninstall creates one:Result:
~/.claudedid not exist before the command, and its only content afterwards wasecc/state.db.Cause:
scripts/lib/state-store/index.js:22hardcodes the default store location:resolveStateStorePath()(index.js:203) joins it ontohomeDir, with no target awareness.scripts/uninstall.js:183-191callsreconcileCanonicalInstallStates()for every target, which opens the store and creates the file.So the derived projection is pinned to the Claude harness directory regardless of
--target.Two consequences:
~/.claudetree created by ECC.ecc-install-state.json, souninstalldoes not remove it, anddoctor --target opencodestill reportsStatus: OK. The residue survives a full uninstall and is only found by scanning the filesystem.Suggested fix: resolve the projection path from the target's own config root (the opencode target already has
scripts/lib/opencode-paths.js:resolveOpencodeConfigRoot), or keep the store under the install root / a target-scoped directory, and have uninstall remove it.Verification context
Windows 11 native, OpenCode v2.0.26, ECC 2.2.3. After removing
~/.claudemanually and re-scanning the whole home directory for name and content matches (ecc-install-state.json,.pi/,ecc-universal,affaan-m/ECC), the only remaining traces were unrelated shell history lines.pradeep14012004 commentedon Oct 14, 2026
Hi there! I'd love to help out with this one! The installation logic does seem worthy of looking into, particularly the effect on people who are already using OpenCode. Do you think you could allow an external PR for this issue? I would love to help make a focused fix as per your repository's contribution guidelines.
Thanks
akushonkamen commentedon Oct 15, 2026
Confirmed the root cause by reading the code at HEAD:
scripts/lib/install/ownership-guard.js:77-89skips anycopy-filewhose destination already exists and isn't recorded in the previous install-state — which also hits ECC's ownopencode.jsontemplate planned as a managed operation byscripts/lib/install-targets/opencode-home.js:106-112. So existing-config users never get theagentmap,skills.paths, or plugin wiring.deepMergeJson(scripts/lib/install/json-ops.js:85) is already available for the fix.I'm working on a focused fix: merge only ECC-owned keys into an existing
opencode.json(preserving user keys), record the merged keys in install-state so repair/uninstall stays reversible. Filed on behalf of an AI-assisted workflow (Claude by Anthropic); I'll author and review the changes. Will follow up with a PR shortly.akushonkamen commentedon Oct 15, 2026
Opened the fix as #3599: the managed config template now merges into an existing
opencode.jsoninstead of being skipped (user keys preserved; pre-merge content snapshotted in install-state so uninstall restores exact bytes; unrecorded hook-consent still refuses the install; repair merges the same way). Red/green reproduction, focused suites and the fullnode tests/run-all.jsrun (7800 passed / 0 failed, 423 files) are documented in the PR body. Root-cause analysis and AI disclosure are in my claim comment above.fix(opencode): merge config into an existing opencode.json instead of…