# Implementation plan: OpenCode Toolkit ## Objective Create an independent, small OpenCode V2-native project using selected and reviewed ECC skills, agent prompts, and workflows. The ECC fork remains a source of reference, not a runtime dependency. The new package must be reproducible, installable in a project, testable without a model provider, and explicit about unverified behavior. ## Starting assumptions and decisions - ECC source: `https://github.com/sargatxet/ECC`, commit `ef648e01899ba3e8dc6371642deaaf64b4477775`, version 2.2.3, MIT. - Runtime baseline: OpenCode 2.0.24, `@opencode/plugin` 2.0.24, Node.js 24.21.0 in the development environment; declared minimum Node.js 20. - Scope: OpenCode V2 only for the initial release. No attempt to retain ECC's Claude Code, Codex, or other harness installers. - Distribution: one ESM package; project-local install first. Global/XDG installation and npm publication are deferred. - Provider and model selection remains user-owned. No credentials, model defaults, or paid model calls are configured by this package. - Content is selected and adapted, not copied wholesale. Preserve upstream license text and per-file provenance. ## Initial scope ### Included - Skills: `coding-standards`, `security-review`, `tdd-workflow`. - Agents: planner, code reviewer, security reviewer. - V2 plugin: `toolkit_project_status`, a read-only wrapper over OpenCode's VCS context and status APIs. - Project installer/uninstaller: copy the selected content, register the npm plugin with a JSONC-preserving edit, track file ownership with SHA-256, reject collisions and symlinks, and preserve modified files during uninstall. - Unit tests, installer integration tests, coverage threshold, provenance, operating documentation, FIXME and TODO tracking. ### Explicitly deferred - ECC's V1 hook runtime, Claude-specific session discovery, continuous-learning storage, instincts, memory vault, shell automation profiles, global installs, multiple OpenCode config-layer reconciliation, npm publication, and provider-backed E2E flows. - Duplicating native OpenCode file, shell, search, delegation, and VCS tools when a native API already satisfies the use case. ## Architecture - `src/plugin.ts`: stable V2 `Plugin.define` entry point and namespaced tool. - `src/installer/config.ts`: JSONC-safe plugin registration edits. - `src/installer/project.ts`: project-local file staging, ownership manifest, safe update, and conservative uninstall. - `src/cli.ts`: `install` and `uninstall` commands. - `content/skills/` and `content/agents/`: versioned content distributed with the package. - `test/`: Node test-runner tests for plugin API shape, config edits, install idempotency, collisions, local edits, and symlink protection. - `docs/PROVENANCE.md`: origin, commit, license, adaptations, and hashes. ## Work phases and acceptance criteria ### Phase 0 — Establish project and contract (complete) - Create the separate repository without changing the ECC fork. - Pin OpenCode SDK version 2.0.24 and establish a test/build baseline. - Record package identity as provisional and document scope. **Acceptance:** independent project builds; ECC source remains unchanged. ### Phase 1 — Select and import content (initial subset complete) - Review each workflow for Claude-only paths, unavailable scripts, models, and cross-references. - Include supporting files, adapt frontmatter to native OpenCode agent format, and record source SHA and file hashes. - Confirm IDs are unique and are installed under `toolkit-*` names. **Acceptance:** OpenCode discovers installed skills and agents; resources are present; imported files have provenance and license attribution. ### Phase 2 — Prove V2 runtime (complete) - Use `Plugin.define({ id, setup(ctx) })`, V2 transforms and documented VCS APIs. - Avoid the V1 plugin callback, V1 event names, and module-global session state. - Verify namespaced tool registration and output through contract tests. - Test loading and tool execution under an actual OpenCode 2.0.24 runtime. **Acceptance:** installed package loads and the tool runs in a real OpenCode session. Verified using a local mock OpenAI-compatible endpoint; no external provider call was made. ### Phase 3 — Implement project installer (initial behavior complete) - Preflight all content and paths; reject collisions, non-regular files, and symlinked install paths. - Refuse simultaneous direct and `.opencode/` project config files until their V2 merge behavior is handled safely. - Preserve existing JSONC and unrelated settings. - Write an ownership manifest with hashes; allow repeat installation only when previously managed files remain unchanged. - On updates, remove stale package-owned files only when their stored hash still matches; keep locally edited stale files tracked and report them. - Remove only package-owned, unmodified assets and a plugin entry the installer originally added. - Test clean install, re-run, collision, user-edited files, malformed config, and symlink cases. **Acceptance:** project install is idempotent; user files are not overwritten; uninstall preserves locally modified content. ### Phase 4 — Validate distribution artifact (complete) - Build and pack the real package. - Install its tarball into a clean project outside this repository. - Check all imports/content/license files and load the plugin with OpenCode. - Verify behavior in a project with pre-existing config and skills. **Progress:** package tarball installs outside the checkout; the CLI is idempotent and OpenCode discovers the three packaged agents. Runtime testing showed that the old npm-name entry caused a registry 404 and that the namespaced tool needed Code Mode enabled. Both were corrected and the packaged plugin and tool were verified in a local mock-provider session. The actual `0.1.0` tarball was also installed into an isolated project containing a pre-existing JSONC config, unrelated plugin, and user-owned skill. Assertions confirmed that installation preserved those resources and installed all three toolkit skills, the package entry point, and license files; a second install made no changes. After locally editing an installed toolkit skill, uninstall removed the unmodified package-owned assets and only the toolkit plugin entry, while preserving the edited skill, user config, unrelated plugin, and user-owned skill. The package was installed from the tarball with its declared dependencies, not from a checkout path or symlink. `npm run typecheck`, all 16 tests, `npm run test:coverage` (87.4% lines, 95.23% functions), and `npm pack --dry-run` also passed. The temporary fixture and assertions were under `/tmp/opencode`; provider-backed agent delegation and skill behavior remain unverified. **Acceptance:** no checkout symlink or development dependency is needed at runtime; config collisions are handled or reported before writes; the V2 plugin and its custom tool are confirmed active. ### Phase 5 — Document and release (repository pre-release published) - Document scope, installation, update/uninstall, compatibility, provenance, and known limitations. - Run deterministic checks and security review before release. - Confirm package/repository names and get explicit approval before publishing. **Progress:** README now documents installing directly from the repository's pre-release tarball, as well as updating and uninstalling. A manual pre-release review of installer paths, ownership, JSONC edits, symlinks, and failure behavior found no release blocker for trusted project-local use; filesystem and provider-backed limitations are recorded in [`SECURITY-REVIEW.md`](SECURITY-REVIEW.md). Typecheck, all 16 tests, coverage (87.4% lines), and package build passed. The `v0.1.0-rc.1` pre-release and SHA-256 sidecar are published. A clean project installed the package using the public release URL, and the downloaded tarball matched its recorded SHA-256. **Acceptance:** another user can install from documented instructions and verify the deterministic behavior without credentials. ### Phase 6 — Optional memory and learning features (memory milestone implemented) - Design persistent memory and session-learning APIs separately. - Prefer V2 public APIs over assumptions about OpenCode's storage layout. - Add opt-in, scope controls, retention behavior, and isolation tests. **Progress:** explicit memory tools now use the V2 plugin storage API. They are disabled by default, session-scoped by project/session, and support separately opted-in canonical-project scope, explicit retrieval/deletion, and configurable expiry. Deterministic tests cover scope isolation and expiry. Live profile storage persistence and user-profile isolation, along with provider-backed learning proposals, remain unverified; automatic prompt/session capture is deliberately not implemented. **Acceptance:** explicit consent and tests prove project/session/user data cannot be mixed or silently uploaded. This phase remains in progress until storage behavior is verified in OpenCode 2.0.24 and learning proposals receive a separate design and validation. ## Verification strategy ### Deterministic, no-model checks - `npm run typecheck`, `npm test`, coverage threshold, package dry-run. - Plugin API contract tests using V2 types and V2-shaped context. - Installer tests using isolated temporary projects. - Real OpenCode config parse and plugin load smoke test. - Tarball install test outside the repository. ### Provider-backed checks - Load the three workflows; delegate to planner/reviewer; invoke skills; verify model-visible permissions and agent behavior. - These tests need a configured provider and may incur cost. They require an explicit budget and must not be represented by mocks as passed. ## Risks and mitigations - **OpenCode config precedence:** direct and `.opencode/` config files have layered precedence. Test the actual 2.0.24 behavior before supporting complex multi-file layouts; fail safely rather than silently hide user plugins. - **Package dependency resolution:** tests against the source checkout can hide missing package files. Validate an installed tarball. - **Content drift:** selective copying creates manual sync work. Compare source SHAs and hashes during updates; never auto-sync all of ECC. - **Session data leaks:** do not use module-global mutable maps for session state; add isolation tests before adding tracking or memory. - **Permission weakening:** do not inherit ECC's auto-approval behavior without an explicit V2 permission design and security review. - **Uninstall partial failures:** file operations can fail mid-run; preserve the manifest and report recovery instructions. Transactional rollback remains a follow-up. ## Change management For each ECC refresh, compare the pinned upstream revision, select changes component-by-component, inspect dependencies and licensing, update hashes, and run the full deterministic and runtime checks. Maintain a compatibility matrix for OpenCode versions actually tested. Do not publish or push without explicit authorization.