Date: 2026-07-19
Status: Build the final product — no phased MVP rollout; ship the complete OCP stack
Repo: oakimov/opencode-plugin-compat
Docs location: docs/plans/ (canonical OCP contract: docs/ocp/0.1.md)
Related plans:
phase0-hooks-parity.md— Research evidence: Hooks / path / plugin inventory../ocp/0.1.md— OCP 0.1 product specificationphase0-adr-universal-compat.md— Product ADR + deliverableszcode-asset-migrator-plan.md— Companion migrator (not OCP ABI)
Goal: Ship a complete universal compatibility bridge so published OpenCode plugins (import "@opencode-ai/plugin" / v2/promise) run unchanged on cooperating OpenCode forks (MiMo Code, Kilo Code), with ZCode honestly at T0. Do not create host-specific forks of consumer plugins (no cursor-mimocode-provider / Kilo / ZCode variants).
| Item | Value |
|---|---|
| Org / repo | anomalyco/opencode |
| Plugin SDK | @opencode-ai/plugin — ., ./tool, ./tui, ./v2/promise, ./v2/effect |
| SDK | @opencode-ai/sdk (+ /v2) |
| Project dirs | .opencode/ |
| XDG | ~/.config/opencode, ~/.local/share/opencode, ~/.cache/opencode |
| Config | opencode.json / opencode.jsonc |
| Env prefix | OPENCODE_* |
| v2 host | Effect-first in packages/core/src/plugin/*; Promise via fromPromise |
Plugins assume this ABI + host wiring.
| Item | Value |
|---|---|
| Repo | XiaomiMiMo/MiMo-Code |
| Relationship | Declared OpenCode fork; long-horizon harness additions |
| Plugin SDK | @mimo-ai/plugin — only ., ./tool, ./tui (no v2 exports); classic Hooks ≈ OpenCode but +actor/session, -dispose/small_model (see phase0-hooks-parity.md) |
| SDK | @mimo-ai/sdk |
| Project dirs | .mimocode/ (.opencode/ not scanned — docs bug #1151) |
| XDG | mimocode / MIMOCODE_HOME |
| Config | mimocode.json(c) |
| Env | MIMOCODE_* |
| Openness | MIT + use restrictions; source available |
Breakage for OpenCode plugins: package rename, paths, missing v2 host/exports, env/XDG.
1.3 Kilo Code / Kilo CLI — verified 2026-07-19 (source: Kilo-Org/kilocode tip, pin .opencode-version = v1.17.4)
| Item | Value |
|---|---|
| Repo | Kilo-Org/kilocode |
| Relationship | Declared OpenCode fork; pin file .opencode-version = v1.17.4 |
| CLI npm | @kilocode/cli / bins kilo, kilocode (7.4.11 on npm at check time) |
| Plugin SDK | @kilocode/plugin 7.4.11 — exports only ., ./tool, ./tui (no ./v2/*) |
| SDK | @kilocode/sdk |
| Residual OpenCode deps | Internal packages still import @opencode-ai/core/* in places; external auth plugins cast from @opencode-ai/plugin types → @kilocode/plugin |
| XDG app name | kilo (packages/core/src/global.ts) → ~/.config/kilo, ~/.local/share/kilo, ~/.cache/kilo, ~/.local/state/kilo, tmp …/kilo |
| Config override | KILO_CONFIG_DIR replaces global config dir; also KILO_CONFIG, KILO_CONFIG_CONTENT |
| Env prefix | KILO_* (confirmed: KILO_CONFIG, KILO_CONFIG_DIR, KILO_DISABLE_PROJECT_CONFIG, KILO_DISABLE_DEFAULT_PLUGINS, KILO_PLUGIN_META_FILE, …) — not OPENCODE_* |
| Project dirs | .kilo (current) + .kilocode (legacy). .opencode project dirs are NOT loaded (CHANGELOG #11638 / #12034; system prompt: “Do not use .kilocode/ or .opencode/”) |
| Global config basenames (precedence / merge) | ~/.config/kilo/config.json, kilo.json(c), and still merges leftover opencode.json(c) in the global kilo config dir |
| Project config | kilo.json / kilo.jsonc under .kilo / .kilocode; schema https://app.kilo.ai/config.json |
| Plugin install cache | npm packages land under ~/.cache/kilo/packages/<sanitized-pkg> (Npm.add → Global.cache/packages) |
| Local plugin install root | writable .kilo (or legacy .kilocode / KILO_CONFIG_DIR); installer also ensures @kilocode/plugin in that tree |
| Platform extras | VS Code extension, JetBrains, gateway, memory, telemetry — larger than CLI-only |
| Openness | MIT; source available |
Breakage for OpenCode plugins:
- Package rename
@opencode-ai/*→@kilocode/* - No plugin v2 exports / host
- Project path rename; does not scan
.opencode(harder than MiMo’s docs bug — Kilo deliberately stopped fallback) - Env/XDG
OPENCODE_*/opencode→KILO_*/kilo - Plugins that hardcode OpenCode config/model paths misbehave (community: oh-my-openagent)
Nuance vs MiMo: Kilo’s tree is closer to modern OpenCode (core/llm/plugin loader with server()/tui() + classic hooks). Still classic-only on the published @kilocode/plugin surface. engines.opencode remains the plugin engine key in compatibility checks.
1.4 ZCode (Z.AI / Zhipu) — verified 2026-07-19 from ZCode-3.3.6-mac-arm64.dmg
| Item | Value |
|---|---|
| Artifact | ZCode.app 3.3.6 arm64; bundle id dev.zcode.app; product @zcode/desktop; homepage https://zcode.z.ai |
| Relationship | Closed Electron desktop built from OpenCode-architecture lineage (@zcode/{desktop,client,server,services,shared,ui,rpc}, electron-vite, Effect/Hono markers historically) |
| Frontend | Custom React 19 desktop UI (not OpenCode TUI) |
| OpenCode npm plugin ABI | Absent. No @opencode-ai/* packages, no OPENCODE_* env, no v2/promise / v2/effect strings in main/host bundles |
| “OpenCode” in product | External agent CLI provider only — enum alongside claude / gemini / codex / glm. Native config map points OpenCode at ~/.config/opencode + opencode.json for importing that CLI’s settings, not for loading @opencode-ai/plugin |
| ZCode’s own plugins | First-party marketplace plugin system (RPC: plugins/install, plugins/uninstall, plugins/marketplace/*, plugins/restoreBuiltin, …). Manifests: .zcode-plugin/plugin.json, also recognizes .claude-plugin/plugin.json / .codex-plugin/.... Components resemble Claude-style roots (skills, commands, hooks, agents, templates). Official bundled plugins e.g. document-skills-plugin, skill-creator-plugin, zcode-guide-plugin, … |
| Home / data | ZCODE_HOME default $HOME/.zcode; settings under ~/.zcode/v2/setting.json; CLI config ~/.zcode/cli/config.json; desktop userData via ZCODE_DESKTOP_* / appData/ZCode |
| Env prefix | ZCODE_* (large surface: ZCODE_HOME, ZCODE_DATA_BASE_DIR, agent spawn envs, CUA helper, telemetry, …) |
| Telemetry | Still always-on class (ARMS + product telemetry paths; see oa-tools/zcode-review; 3.3.6 still has telemetry-state under .zcode/v2) |
| Openness | Closed binary — no published OpenCode-plugin install hook to patch from outside |
Telemetry endpoints (3.3.6 out/main, verified 2026-07-19):
- ARMS RUM (hardcoded hostname URL):
https://proj-xtrace-7e235817c9b9381c22d8b743908d469f-cn-beijing.cn-beijing.log.aliyuncs.com/rum/web/v2?...viaRF.init({enable:!0, endpoint:…}) - Product events (default):
https://zcode.z.ai/api/v1/event/report— may rewrite onto a custom ZCode endpoint origin whenZCODE_BASE_URL/ endpoint override is set - No reverse-DNS / PTR / IP-literal telemetry fallback in main bundles or
@arms/rum-electron(searcheddns.reverse,in-addr.arpa,lookupService, hardcoded public telemetry IPs). Only unrelated literal found:http://192.168.6.166:8080(ZAPI catalog stub). Hostname DNS sinkhole / host firewall is therefore an effective mitigation class — not an OCP plugin feature.
Implication (final): ZCode is not an OpenCode-plugin host. It is:
- A desktop agent orchestrator that can spawn OpenCode (and others) as subprocess agents, and
- A separate plugin marketplace (Claude-/Codex-adjacent layout +
.zcode-plugin), not OCP.
Public ecosystem confirmation (2026-07-19): real third-party plugins/marketplaces exist (tmdgusya/glm-hammer, jhlee0409/zcode-glm-fleet, …). They implement .zcode-plugin/plugin.json + Claude-style hook events — zero @opencode-ai/plugin. Full ABI notes in oa-tools/zcode-review/ZCODE_RESEARCH.md §7.
Universal OCP cannot target ZCode without Z.AI adding an explicit OpenCode-plugin loader (unlikely while Agent-mode marketplace is the product path). Keep ZCode at T0 with an honest adapter stub / docs only. Companion privacy guidance (firewall/DNS) is out-of-band from the bridge runtime — see §7.1.
| Dimension | OpenCode | MiMo | Kilo | ZCode 3.3.6 |
|---|---|---|---|---|
| npm / plugin scope | @opencode-ai/plugin |
@mimo-ai/plugin |
@kilocode/plugin |
N/A (marketplace .zcode-plugin, not npm OC ABI) |
| v2 exports + host | yes | no | no | no (not present) |
| Project plugin dir | .opencode |
.mimocode |
.kilo (+ legacy .kilocode); no .opencode scan |
workspace .zcode / marketplace installs |
| Config basename | opencode.json(c) |
mimocode.json(c) |
kilo.json(c) + global config.json (+ leftover global opencode.json(c)) |
~/.zcode/v2/setting.json |
| XDG / home profile | opencode |
mimocode |
kilo |
ZCODE_HOME → ~/.zcode (not XDG app name) |
| Env prefix | OPENCODE_ |
MIMOCODE_ |
KILO_ |
ZCODE_ |
| Upstream pin | tip | older OpenCode-shaped | v1.17.4 pin file | opaque closed bundle 3.3.6 |
| Distribution | open CLI | open CLI | open CLI + IDEs | closed Electron |
| Role of “OpenCode” | self | renamed fork | renamed fork | external CLI agent only |
Pattern: open CLI forks repeatedly apply the same rename playbook (scope, paths, config, env) and lag/drop plugin v2. Closed ZCode diverged into a different plugin product plus multi-agent spawning.
Building MiMo-only + Kilo-only + ZCode-only shims:
- Multiplies maintenance by fork count.
- Each fork re-implements alias + path scan + partial v2.
- Plugins still break when the next fork appears.
- No shared compatibility contract or test matrix.
A universal approach needs a shared ABI + host profile, with thin fork adapters.
Define an explicit, versioned OpenCode Plugin Host Profile:
- Stable plugin author ABI — what plugins import (
@opencode-ai/pluginclassic +v2/promise). - Host capability interface — what a runtime must implement to claim “OpenCode-plugin compatible.”
- Fork adapter pack — maps profile → MiMo / Kilo / OpenCode / (future) native packages & paths.
- Install-time resolution — ensure
@opencode-ai/*imports resolve to the profile facade, which delegates to the fork’s native SDK.
┌──────────────────────────┐
│ Unchanged OpenCode plugin│
│ @opencode-ai/plugin(+v2) │
└────────────┬─────────────┘
│ resolve (alias / facade package)
┌────────────▼─────────────┐
│ opencode-plugin-compat │ ← universal facade (this project)
│ (implements OCP) │
│ detect host → adapter │
└────────────┬─────────────┘
┌───────┼────────┬────────────┐
▼ ▼ ▼ ▼
OpenCode MiMo Kilo (ZCode adapter stub)
native native native if/when loader exists
| Model | How it ships | Pros | Cons |
|---|---|---|---|
| External OCP layer (chosen) | Install-tree overrides / sidecar / doctor + host-kit helpers from this repo | Owned here; hosts stay read-only | Incomplete host seams stay honest (capabilities.*: false) |
| Embed OCP inside host install/loader | Each host vendors/calls OCP in install/loader | Reliable host hooks | Requires modifying host source — out of scope |
| Manual cache overrides only | Manual cache overrides | Simple Layer A | Fragile for full T3 unless OCP can reach provider-resolve |
Recommendation: Design the library + profile for an external attach. Path gaps → docs/doctor/operator copy-symlink. Wire host-promise-v2 from the OCP layer where seams allow. Hosts remain read-only references.
ZCode stays T0 (marketplace ABI ≠ OpenCode plugin ABI).
| Package | Purpose |
|---|---|
@opencode-compat/profile |
Types: HostProfile, capability flags, path/env schema, OCP semver, detect() |
@opencode-compat/facade-plugin |
Published as drop-in stand-in used via install overrides named @opencode-ai/plugin in plugin install trees / operator overrides (or re-exports) |
@opencode-compat/facade-sdk |
Same for @opencode-ai/sdk |
@opencode-compat/adapter |
One universal host adapter — autodetects host, dispatches via HostProfile to native @opencode-ai/* / @mimo-ai/* / @kilocode/*; zcode → T0 doctor |
@opencode-compat/host-promise-v2 |
Shared Promise v2 host kit (aisdk required) wired from OCP layer |
@opencode-compat/cli |
Dev tool: compat doctor, matrix runner, generate install overrides |
Rejected: separate @opencode-compat/adapter-{opencode,mimo,kilo,zcode} packages. Host variance is profile data + internal dispatch in the single adapter.
Important npm constraint: You cannot publish the real @opencode-ai/* scope without anomalyco. Universal layer uses:
- Install overrides:
"@opencode-ai/plugin": "npm:@opencode-compat/facade-plugin@…"inside plugin install trees / operator tooling, or - Import maps / aliases at runtime from the OCP layer (without modifying host upstream source).
type HostId = "opencode" | "mimo" | "kilo" | "zcode" | "unknown"
type HostProfile = {
id: HostId
/** Semver of OCP implemented by this adapter */
ocpVersion: string
/** Fork’s native plugin package name to peer on */
nativePlugin: string // @opencode-ai/plugin | @mimo-ai/plugin | @kilocode/plugin
nativeSdk: string
upstreamPin?: string // e.g. kilo ".opencode-version" = v1.17.4
paths: {
configDir: string // ~/.config/{opencode|mimocode|kilo}
dataDir: string
cacheDir: string // kilo npm plugins: ~/.cache/kilo/packages/*
projectDirs: string[] // kilo: [".kilo", ".kilocode"] — do NOT assume ".opencode" is scanned
/** Compat suggestion for matrix/doctor — close via bridge/docs/operator */
compatProjectDirs?: string[] // e.g. [".opencode"] for kilo/mimo
}
configFiles: string[] // basenames, precedence order
envPrefix: string // OPENCODE | MIMOCODE | KILO | ZCODE (zcode = non-OCP)
capabilities: {
classicHooks: boolean
promiseV2: boolean // exports + host
effectV2: boolean
aisdkProviderHooks: boolean
localPluginScan: boolean
scansDotOpencode: boolean // kilo today: false
}
agents?: { builtins: string[]; aliases?: Record<string, string> }
}
/** Concrete verified drafts (research — not shipped code) */
const OPENCODE_PROFILE_DRAFT = {
id: "opencode",
ocpVersion: "0.1.0",
nativePlugin: "@opencode-ai/plugin",
nativeSdk: "@opencode-ai/sdk",
pluginVersionObserved: "1.18.3",
paths: {
configDir: "~/.config/opencode",
dataDir: "~/.local/share/opencode",
cacheDir: "~/.cache/opencode",
projectDirs: [".opencode"],
},
configFiles: ["opencode.json", "opencode.jsonc"],
envPrefix: "OPENCODE",
capabilities: {
classicHooks: true,
promiseV2: true,
effectV2: true,
aisdkProviderHooks: true,
localPluginScan: true,
scansDotOpencode: true,
},
hooks: {
core: "/* 21 keys — see phase0-hooks-parity.md */",
missing: [],
extensions: [],
},
} as const
const MIMO_PROFILE_DRAFT = {
id: "mimo",
ocpVersion: "0.1.0", // target — not claiming host embeds OCP
nativePlugin: "@mimo-ai/plugin",
nativeSdk: "@mimo-ai/sdk",
pluginVersionObserved: "0.1.6",
paths: {
configDir: "~/.config/mimocode", // or $MIMOCODE_HOME/config
dataDir: "~/.local/share/mimocode",
cacheDir: "~/.cache/mimocode",
projectDirs: [".mimocode"],
compatProjectDirs: [".opencode"], // matrix/doctor expectation — close via bridge/docs/operator
},
configFiles: ["mimocode.json", "mimocode.jsonc"],
envPrefix: "MIMOCODE",
capabilities: {
classicHooks: true,
promiseV2: false, // no published exports; host kit required for T3
effectV2: false,
aisdkProviderHooks: false,
localPluginScan: true,
scansDotOpencode: false,
},
hooks: {
missing: ["dispose", "experimental.provider.small_model"],
extensions: [
"actor.preStop",
"actor.postStop",
"session.pre",
"session.post",
"session.userQuery.pre",
"session.userQuery.post",
],
},
note: "PluginInput still types createOpencodeClient from @mimo-ai/sdk (residual name)",
} as const
const KILO_PROFILE_DRAFT = {
id: "kilo",
ocpVersion: "0.1.0", // target — not claiming host embeds OCP
nativePlugin: "@kilocode/plugin",
nativeSdk: "@kilocode/sdk",
pluginVersionObserved: "7.4.11",
upstreamPin: "v1.17.4",
paths: {
configDir: "~/.config/kilo",
dataDir: "~/.local/share/kilo",
cacheDir: "~/.cache/kilo",
pluginInstallDir: "~/.cache/kilo/packages",
projectDirs: [".kilo", ".kilocode"],
compatProjectDirs: [".opencode"], // matrix/doctor expectation — close via bridge/docs/operator
},
configFiles: ["config.json", "kilo.json", "kilo.jsonc", "opencode.json", "opencode.jsonc"],
envPrefix: "KILO",
capabilities: {
classicHooks: true, // Hooks keys identical to OpenCode 1.18.3
promiseV2: false,
effectV2: false,
aisdkProviderHooks: false,
localPluginScan: true,
scansDotOpencode: false,
},
hooks: { missing: [], extensions: [] },
} as const
const ZCODE_PROFILE_DRAFT = {
id: "zcode",
nativePlugin: "(marketplace .zcode-plugin — not @opencode-ai/plugin)",
ocpVersion: "none",
paths: {
home: "${ZCODE_HOME:-$HOME/.zcode}",
settings: "~/.zcode/v2/setting.json",
cliConfig: "~/.zcode/cli/config.json",
},
envPrefix: "ZCODE",
capabilities: {
classicHooks: false,
promiseV2: false,
effectV2: false,
aisdkProviderHooks: false,
localPluginScan: false, // OpenCode ABI
marketplacePlugins: true, // different ABI
externalOpencodeAgent: true,
},
} as constDetection order (runtime):
- Explicit
OPENCODE_COMPAT_HOST=mimo|kilo|opencode - Presence of native packages / binary names (
mimo,kilo,opencode) - Config dir heuristics (
~/.config/kilovsmimocodevsopencode) zcode→ refuse OCP with doctor message (marketplace ≠ OpenCode plugins)unknown→ fail with doctor message
Same stack as MiMo plan, generalized:
Install-time overrides so plugin code importing @opencode-ai/plugin / sdk / v2/* resolves to facade → adapter → native.
Each adapter declares projectDirs + configFiles. Hosts should scan OpenCode dirs as fallback plus native dirs (documented precedence: native wins).
Suggested default scan for maximum plugin reuse (hosts do not scan .opencode today — close via bridge docs/doctor/operator copy-symlink):
- Native project dir (
.mimocode/.kilo/ …) .opencode(compat expectation for matrix/doctor; optional operator copy/symlink into native dirs)
OPENCODE_COMPAT_PATH_BRIDGE=1: map missing OPENCODE_* to host prefix; do not dual-write secrets by default.
Facade re-exports classic Hooks types and runtime registration by delegating to native plugin SDK. Maintain a Hooks parity table across OpenCode tip × MiMo × Kilo pin.
This is the hard universal piece.
Forks currently lack v2 exports (MiMo, Kilo). Options:
| Approach | Description |
|---|---|
| E-univ | Ship @opencode-compat/host-promise-v2 implementing define + PluginContext + aisdk hook bus; OCP layer / reachable host seams call into it at provider-resolve time |
| E-port | Each fork cherry-picks OpenCode core Effect host (Kilo closer; MiMo harder) |
| E-stub | Export v2 that throws “host incomplete” |
Product = E-univ with aisdk required, wired from the OCP layer where provider-resolve can be reached without modifying host source. Catalog/agent/… domains ship as part of the same host kit with loud stubs until a domain is fully wired (no “ship T1 now, T4 later” product split — one release trains the full surface; incomplete domains fail loud).
Effect v2 (./v2/effect): ship export + clear unsupported error unless a host already has Effect host parity; do not gate the product on Effect completeness.
@opencode-compat/cli runs fixtures against each adapter:
- Classic auth/config/tool hooks
- Promise v2 aisdk injection
- Local
.opencode/pluginsscan - Negative: unsupported domain errors
Publish public compat matrix: Plugin × Host × OCP tier × last pass.
| Tier | Meaning | Hosts in scope |
|---|---|---|
| T0 | Broken / unsupported | ZCode today; unknown forks |
| T1 | Classic npm plugins via alias | OpenCode, MiMo, Kilo (via external OCP layer) |
| T2 | Local .opencode plugins |
Same |
| T3 | Promise v2 + aisdk |
Forks that embed host kit |
| T4 | Promise v2 domains (catalog/agent/…) | Progressive |
| T5 | Effect v2 | Opt-in / upstream-aligned forks |
| TX | Host-aware plugins (hardcoded XDG) | Close in bridge / document residual limits — not per-host plugin forks |
- Product stance: ZCode remains T0 / out of scope for drop-in
@opencode-ai/pluginpackages. Confirmed in 3.3.6 and by public plugins: marketplace ABI is.zcode-plugin/plugin.json(+ Claude/Codex manifests), subprocess hooks (SessionStart…Stop), skills/commands/MCP — not npm classic/v2. Evidence: oa-tools/zcode-review/ZCODE_RESEARCH.md §7; samplestmdgusya/glm-hammer,jhlee0409/zcode-glm-fleet. - Do not confuse ZCode’s “OpenCode” agent tile / MCP-import-from-
opencode.jsonwith plugin compat. - Partner path (only if Z.AI wants it): Electron loader for npm OpenCode plugins — product-political, not a sidecar we can force.
- Possible narrow bridge (optional, not OCP): package markdown skills/commands as
.zcode-plugin(ecosystem already does this). Hooks do not map cleanly to@opencode-ai/pluginHooks. - Adapter stub = types + doctor message only; never claim T1+. Doctor text may cite marketplace ABI + example repos above.
- Telemetry kill via OCP/marketplace plugin: not deliverable. No in-app opt-out; Electron hooks cannot disable ARMS/
event/report; ASAR patch/resign rejected as product path.
| Host | In-app opt-out? | Deliverable |
|---|---|---|
| Kilo | Yes — PostHog via config / env | docs/guides/kilocode-telemetry-disable.md |
| MiMo | Yes — Xiaomi metrics via env | docs/guides/mimocode-telemetry-disable.md |
| ZCode | No — docs-only firewall/DNS | docs/guides/zcode-telemetry-block.md |
Evidence: @kilocode/kilo-telemetry → https://us.i.posthog.com; CLI bootstrap Telemetry.init({ enabled: cfg.experimental?.openTelemetry !== false }); if KILO_TELEMETRY_LEVEL is set, only all enables. VS Code respects vscode.env.isTelemetryEnabled and POST /telemetry/setEnabled.
Must cover (done in guide): config experimental.openTelemetry: false; env KILO_TELEMETRY_LEVEL=off; VS Code consent path; optional us.i.posthog.com sinkhole; naming caveat (key name says OpenTelemetry but gates PostHog); not an OCP plugin feature.
Evidence: MiMo packages/opencode/src/metrics → https://tracking.miui.com/track/v4/o; analytics on by default; documented env opt-out MIMOCODE_ENABLE_ANALYSIS=false. See oa-tools/mimo-review/MIMO_RESEARCH.md §6–§7.
Must cover (done in guide):
- Primary disable —
export MIMOCODE_ENABLE_ANALYSIS=false(shell / IDE / spawn env) - Default-on honesty — unset ⇒ analytics enabled
- Endpoint —
tracking.miui.com(+ optional DNS/firewall sinkhole for defense in depth) - Scope caveat — flag gates usage analysis, not Xiaomi-hosted inference / OAuth / install CDN; MiMo Auto can still send code to Xiaomi models
- Verification — no POSTs to
tracking.miui.comafter restart - Honesty — MiMo host feature, not an OCP plugin kill; re-check after upgrades
- Cross-links — Kilo guide; ZCode firewall/DNS guide (ZCode has no equivalent env opt-out)
Doctor/CLI: optional one-liner pointer from mimo doctor text to the guide — no automated env mutation from OCP.
Why: 3.3.6 has no reverse-DNS / IP-literal bypass for telemetry hostnames, so host-level DNS/firewall blocks work. Users who want product-event suppression also need guidance that includes zcode.z.ai — with explicit control-plane / Coding Plan breakage.
Must cover:
- Targets
- ARMS:
proj-xtrace-…cn-beijing.log.aliyuncs.comand broader*.log.aliyuncs.com/*.rum.aliyuncs.comas needed - Product analytics:
zcode.z.aipath/api/v1/event/report(and whole-host block when path filtering unavailable)
- ARMS:
- Evidence — hostname-only endpoints; no PTR/IP fallback;
192.168.6.166is not telemetry - Tiered recipes
- Tier A (ARMS-only): DNS sinkhole / Little Snitch /
pf/ Pi-hole for Alibaba ARMS hosts — keepszcode.z.aicontrol plane - Tier B (ARMS + product events, keep BYO LLM): also block
zcode.z.ai(or HTTPS MITM/path proxy only for/api/v1/event/reportif available) - Tier C (maximum isolation): block
zcode.z.ai+ ARMS; use API-key BYO againstapi.z.ai/open.bigmodel.cn/ catalog hosts — document what breaks
- Tier A (ARMS-only): DNS sinkhole / Little Snitch /
- Breakage matrix when blocking
zcode.z.ai- Breaks: OAuth/token, client configs, updates, WebSocket remote (
wss://zcode.z.ai/ws), Coding Plan / Start Plan LLM proxy (/api/v1/zcode-plan*) - Keeps (typical): local UI; API-key BYO inference to non-
zcode.z.aicatalog hosts
- Breaks: OAuth/token, client configs, updates, WebSocket remote (
- Verification — Console.app /
lsof -i/ packet filter logs; confirm ARMS +event/reportfail while optional BYO chat still works - Honesty — not an OCP feature; not a marketplace plugin; do not claim silent perfect privacy if CDN/IP ranges change; re-check after ZCode upgrades
- Cross-links — Kilo + MiMo in-app opt-out guides (ZCode has no equivalent env/config kill)
Doctor/CLI: optional one-liner pointers from host doctor text — no automated firewall mutation from OCP; no ZCode in-process kill.
Rule: We are not shipping “Phase 1 then Phase 2.” Research is done. Build and ship the complete product below as one coherent deliverable (workstreams may run in parallel; none are deferred “later phases”).
Completed 2026-07-19; see phase0-hooks-parity.md, ../ocp/0.1.md, phase0-adr-universal-compat.md:
- Kilo env/XDG/plugin cache; no project
.opencodescan - ZCode 3.3.6 = T0 (marketplace ≠ OCP)
- Classic Hooks: OC ↔ Kilo identical; MiMo +extensions / −dispose / −small_model
- Sample plugin inventory (classic vs classic+v2)
- ADR: external OCP layer, facade overrides, OCP 0.1, new repo
opencode-plugin-compat
| Workstream | Deliverable |
|---|---|
| Repo | Create opencode-plugin-compat; move/copy OCP docs into docs/ |
| Profile | @opencode-compat/profile — HostProfile types + opencode/mimo/kilo/zcode drafts |
| Facades | @opencode-compat/facade-plugin + facade-sdk (classic + v2/promise exports; effect throws unless capable) |
| Adapter | @opencode-compat/adapter — one universal autodetection runtime (opencode / mimo / kilo dispatch; zcode → T0 doctor) |
| Host kit | @opencode-compat/host-promise-v2 — aisdk language/sdk end-to-end; other domains loud-stub |
| CLI | @opencode-compat/cli — compat doctor + matrix runner |
| Fixtures | Full conformance set from OCP §10 (T0–T3 + unsupported-domain) |
| Host enablement notes | docs/hosts/mimo.md + docs/hosts/kilo.md — operator overrides / path workarounds / host-kit wiring from OCP |
| Docs | Per-host enablement, public Plugin×Host×Tier matrix, ZCode T0 honesty |
| Companion (non-runtime) | Kilo + MiMo telemetry disable guides + ZCode telemetry block guide — §7.1 / docs/guides/kilocode-telemetry-disable.md + docs/guides/mimocode-telemetry-disable.md + docs/guides/zcode-telemetry-block.md (ZCode = firewall/DNS docs only; not an OCP plugin kill) |
| Out of scope | Host-specific consumer plugin forks (cursor-mimocode-provider, etc.) — close TX/path gaps in the bridge instead |
opencode-plugin-compat/
packages/
profile/ # HostProfile + detect() + drafts
facade-plugin/
facade-sdk/
adapter/ # ONE universal autodetection adapter
host-promise-v2/
cli/ # doctor + matrix
fixtures/ # conformance
docs/ocp/0.1.md
docs/hosts/ # host enablement notes (operator attach)
- Scaffold monorepo + profile + facade classic exports.
- Universal
@opencode-compat/adapter(autodetect + mimo/kilo/opencode dispatch) + alias resolve fixtures (T1). - Host kit aisdk + facade
v2/promise+ provider-resolve wiring from OCP layer (T3). - Path/env bridge docs + doctor honesty for
.opencodegaps (T2 via operator copy-symlink). - Doctor CLI + public matrix + ZCode T0 doctor path.
- Re-eval any remaining TX plugins against the T3+path bridge; do not ship host-specific consumer plugin forks.
Order is for dependency convenience only — the release bar is the full product (§13), not a mid-stack MVP cut.
- ZCode marketplace↔OCP translation / vendor Electron loader (blocked on Z.AI)
- In-process ZCode telemetry kill (plugin/ASAR/
NODE_OPTIONS) — host firewall/DNS docs only (§7.1); Kilo/MiMo use in-app opt-out guides instead - Full Effect v2 host parity on every fork (export + loud fail is enough)
- Owning
@opencode-ainpm org - Host-specific dual packages (
cursor-mimocode-provider, etc.) as an escape hatch — close gaps in the bridge instead - Guaranteeing every deeply host-aware (TX) plugin without further bridge work
| Scope | Estimate | Feasibility |
|---|---|---|
| Full library + profile + facades + one universal adapter + CLI + fixtures | ~3–6 weeks eng | High — we control it |
| External attach on MiMo + Kilo (overrides / sidecar / docs) | Owned in this repo | High — incomplete seams stay honest |
| T3 aisdk green on both open forks | Included in product bar once seams found | Medium — needs reachable provider seams via OCP |
| “All plugins on all forks unchanged” | Not realistic | Low |
| ZCode drop-in | Blocked without Z.AI | Low until partner |
Honest ceiling: Universal layer makes open CLI forks converge on OCP. Deeply host-aware (TX) plugins may still need bridge gaps closed (paths, agents, env). It does not unlock closed ZCode without vendor work. Dual-package consumer forks are out of scope.
| Strategy | Long-term maintenance |
|---|---|
| Per-plugin dual/triple packages | Easy per product; scales poorly across many plugins |
| Per-fork compat (MiMo-only × N) | Medium-hard; duplicated |
| Universal OCP + one autodetection adapter (this product) | Harder upfront; best asymptote if ≥2 forks cooperate |
| Wait for OpenCode “official fork ABI” | Ideal but uncertain |
Cursor provider: ship unchanged via OCP (cursor-opencode-provider); close path/TX gaps in the bridge. Do not create cursor-mimocode-provider / Kilo / ZCode variants.
Ecosystem goal: OCP + one universal adapter is the primary product. Every cooperating host is an equal HostProfile target of that adapter — no host is a privileged "proof" and none gets its own adapter package or code path. The MiMo plan is host-integration detail only (external layer).
| Plan | Role |
|---|---|
phase0-adr-universal-compat.md |
Product ADR |
phase0-hooks-parity.md |
Research evidence |
../ocp/0.1.md |
Protocol contract |
zcode-asset-migrator-plan.md |
Companion migrator (not OCP ABI) |
| This plan | Shared profile, facades, host kit, multi-fork matrix, ZCode policy |
Build sequencing (dependency only):
- OCP packages + classic facade + one universal adapter (
mimoprofile first). - Add
kilo/opencode/zcodeHostProfiledata in the same adapter (no new packages) once MiMo proves overrides. - Host kit wiring from the OCP layer for T3 (operator overrides / sidecar).
- TX/path smoke for unchanged plugins (incl.
cursor-opencode-provider); no host-specific consumer forks.
| Risk | Mitigation |
|---|---|
| Host seams incomplete / unreachable | Keep capabilities.* honest; ship docs/doctor/operator workarounds; matrix shows residual TX limits |
| API skew between Kilo 1.17.4 pin and OpenCode tip | Profile upstreamPin; test against pin + tip; facade version gates |
Facade mistaken for official @opencode-ai |
Clear naming, docs, no trademark abuse; overrides only in plugin install trees / operator tooling |
| Security / supply chain | Pin facade versions; checksums; no auto-exec of unreviewed plugins beyond host policy |
| Over-claiming ZCode support | Explicit T0 until loader exists |
| Scope creep disguised as “phases later” | No deferred phases — incomplete domains = loud stub in the same product, not a future phase gate |
- Published OCP 0.1 with capability flags +
@opencode-compat/*packages. - Universal
@opencode-compat/adapterwithmimo+kiloprofiles passes classic conformance suite (T1). - Documented path story for T2 (docs/doctor/operator copy-symlink; matrix
--compat-scan). - Promise v2 aisdk fixture green where host kit is embedded (T3); unsupported domains fail loud.
- At least one unchanged community classic plugin runs on MiMo and Kilo.
- Public matrix lists OpenCode / MiMo / Kilo / ZCode with honest tiers.
- ZCode documented as unsupported (T0 doctor).
- Unchanged
cursor-opencode-provider(and similar) passes T3+path smoke on cooperating hosts; dual-package forks remain out of scope. - Doctor CLI + governance (semver, CI matrix against pinned forks, security note).
- Phased MVP / “Phase N later” delivery.
- Owning
@opencode-ainpm scope. - Guaranteeing closed-source forks (ZCode loader).
- Building host-specific dual packages (
cursor-mimocode-provider, etc.) as a TX escape hatch. - Building IDE-specific Kilo VS Code/JetBrains extension bridges (CLI/OpenCode-ABI first).
- Full Effect v2 host port on every fork.
Create repoDone.opencode-plugin-compat; copy OCP docs; scaffold packages (§8.3).Implement profile + facade + one universal adapter + host kit + CLI + fixtures as one product.Done (matrix green; T3 needs host embed).- Prove external attach on MiMo/Kilo from
docs/hosts/: install overrides → facade + path/docs workarounds + host-kit wiring from the OCP layer. - Prove unchanged plugins (incl.
cursor-opencode-provider) via the bridge — no host-specific consumer forks. - ZCode remains T0 stub/doctor only.
Write §7.1 companion guidesDone:docs/guides/kilocode-telemetry-disable.md+docs/guides/mimocode-telemetry-disable.md(in-app opt-out) +docs/guides/zcode-telemetry-block.md(ARMS + optionalzcode.z.aiblock tiers; docs only). Linked fromdocs/README.md, cross-guides,docs/hosts/mimo.md/docs/hosts/kilo.md, and doctor one-liners.
packages/core/src/global.ts—app = "kilo"; XDG join;KILO_TEST_HOME;Flag.KILO_CONFIG_DIRpackages/core/src/flag/flag.ts—KILO_CONFIG,KILO_CONFIG_DIR,KILO_CONFIG_CONTENT, …packages/core/src/npm.ts— install dirglobal.cache/packages/<pkg>packages/opencode/src/config/paths.ts— project targets[.kilocode, .kilo]onlypackages/opencode/src/config/config.ts— global merge ofconfig.json/kilo.json(c)/opencode.json(c)packages/plugin/package.json— exports././tool/./tuionly.opencode-version—v1.17.4- CHANGELOG — stop loading
.opencode(#11638); leftover.opencodenotice (#12034)
ZCode 3.3.6 (ZCode-3.3.6-mac-arm64.dmg → extracted app.asar)
package.json—@zcode/desktop3.3.6, homepagehttps://zcode.z.aiout/host+out/main— RPCplugins/*; manifests.zcode-plugin/.claude-plugin/.codex-plugin- Public plugin ABI follow-up — oa-tools/zcode-review/ZCODE_RESEARCH.md §7 (
tmdgusya/glm-hammer,jhlee0409/zcode-glm-fleet) - External agent enum includes
opencodewithnativeConfigDir: ".config/opencode" - No
@opencode-ai/plugin/v2/promise/OPENCODE_*in main/host bundles