The opencode runtime is one of the framework's harness distributions, for the
open-source opencode harness (opencode.ai). One deterministic core, many
harnesses: the engine, state machine, audit log, graph, swarm referee, and
learnings gate are byte-identical across every distribution — only the shell
differs. The source/development tree is generated into ignored local
dist/opencode/ from core/ + harness/opencode/ by
bun scripts/package.ts opencode; never hand-edit it.
Harness-specific onboarding lives in .aidlc/onboarding.md, loaded by the
instructions list in opencode.json. The root AGENTS.md block is
harness-neutral and shared with other installed harnesses whose engine
directories differ; opencode and Copilot cannot share one .aidlc/ install.
opencode auto-imports every *.ts under .opencode/tools/ and
.opencode/tool/ as custom tool definitions, and importing a CLI-style engine
script (top-level dispatch, process.exit) crashes the session
(live-reproduced on opencode 1.17.18). So this distribution splits:
.aidlc/— the AIDLC engine tree (tools, hooks, skills, agents, knowledge, scopes, sensors, aidlc-common). opencode never scans it; the shippedopencode.jsonregistersskills.paths: [".aidlc/skills"]so the orchestrator skill and every generated runner are discovered there..opencode/— only natively-consumed surfaces: the 14 persona subagents (agents/*.md,mode: subagent), the/aidlccommand (command/aidlc.md), and the hook-adapter plugin (plugin/aidlc-opencode-adapter.ts, auto-discovered by opencode). The command prints the installed skill into itself each time it is typed (aidlc engine skill-text --harness-dir .aidlc), so the agent gets the skill whole: opencode cuts a skill loaded through its own skill tool at 50 KiB and saves the rest under its data folder, outside the project.
- opencode ≥ 1.17 — the plugin hook surface this install relies on
(
tool.execute.before,tool.execute.after,chat.message,session.idle,experimental.session.compacting,shell.env) and project-local skill/agent discovery. Check withopencode --version. - bun only when generating or running the source/development
dist/projection. Native installs and versioned release runtimes dispatch through the installedaidlcexecutable. - A model provider — the shipped project
opencode.jsonand agent definitions pin no model. Your global opencode config supplies the provider and session model; balanced reviewers retain only their medium reasoning variant.
tmp="$(mktemp -d)"
curl -fsSL \
https://github.com/awslabs/aidlc-workflows/releases/latest/download/install.sh \
-o "$tmp/install.sh"
sh "$tmp/install.sh"
rm -rf "$tmp"
cd your-project
aidlc config
aidlc doctor
opencodeThe installer verifies the release metadata, executable, and all-harness runtime archive against the published SHA-256 checksums. The installed runtime does not require Bun, Node.js, or Git. Harness selection happens in aidlc config.
On Windows, download install.ps1 and run
& $installer. See Windows installation
for account scope, automatic User PATH registration, and -NoModifyPath.
For an air-gapped package, use
install.sh --from <release-directory> --offline on Unix or
& $installer -From <release-directory> -Offline on Windows.
aidlc config projects .aidlc/, .opencode/, the workspace shell,
AGENTS.md, the managed .gitignore block, and AI-DLC's entries in
opencode.json. Those entries discover the skill and method files, let
AI-DLC's own direct aidlc engine * commands run without a prompt, and ask
once before rm -r... and git push; every other shell command follows your
own opencode settings. A project that already has an opencode.json keeps
its model, provider, instructions, permission rules, and comments: AI-DLC
adds only its own entries, and its two asks go first in your bash map so
your own rules after them decide. In your global opencode config, write a
shell rule as a map ("bash": {"*": "ask"}): opencode replaces a global
short form "bash": "ask" with any project map, this file included. A
global "git *": "allow" still meets AI-DLC's git push ask once; "Allow
always" ends it. aidlc config and aidlc doctor say so in one line when
they find the short form in your global config. Start opencode in the project and
run /aidlc --doctor, then /aidlc followed by what you want to build.
Download and extract a specific release's aidlc-copy-runtime-X.Y.Z.tar.gz as described in
Install and Lifecycle: Copy Channel,
then set RUNTIME_ROOT to the extracted runtime/ directory.
-
Copy the distribution into your project:
cp -r "$RUNTIME_ROOT/opencode/.aidlc/" your-project/.aidlc/ cp -r "$RUNTIME_ROOT/opencode/.opencode/" your-project/.opencode/ cp -r "$RUNTIME_ROOT/opencode/aidlc/" your-project/aidlc/ # the workspace shell — a sibling of .aidlc/, not inside it
The copy runtime has no
opencode.json, so copying never replaces yours. Step 2 adds AI-DLC's three load-bearing parts to it, or writes the file when there is none:skills.paths(skill discovery from.aidlc/skills),instructions(both native onboarding at.aidlc/onboarding.mdand the method globaidlc/active-memory/**/*.md, the engine's git-ignored copy of the active space's method that/aidlc space <name>rewrites), and permission rules for AIDLC bash entrypoints plus edits under.aidlc/tools/and.aidlc/hooks/. If you keep anopencode.jsoncinstead, step 2 adds those parts to it, comments kept, and creates noopencode.jsonbeside it. The adapter enforces the permission boundary: the target must be an entrypoint embedded from the packaged tree, invoked as one direct command with no chaining, redirection, expansion, or command substitution. Engine-code edits prompt for approval. -
Run the copy's own setup once, from the project:
bun .aidlc/tools/aidlc.ts config --from "$RUNTIME_ROOT" --harness opencodeIt adds AI-DLC's lines to your
AGENTS.mdand.gitignore, after everything already there, and AI-DLC's entries to youropencode.json(or creates them), before your first workflow (per-clone audit shards are committed deliberately; cursors and machine-local runtime stay ignored). -
Start opencode in the project and run
/aidlc --doctor, then/aidlcfollowed by what you want to build.
Because opencode has no channel for the session-start hook's injected context,
the /aidlc skill performs one read-only status probe on a bare invocation. An
existing workflow carries on where it stopped, as with /aidlc --resume (ask
to redo, jump to a stage, or start fresh to do something else);
/aidlc --resume skips the probe and continues directly.
The versioned runtime uses the native aidlc command. Framework developers who
need the Bun-shaped projection can clone the repository, run
bun install --frozen-lockfile and bun scripts/package.ts, then use the
ignored local dist/opencode/ output.
aidlc update updates the machine runtime without rewriting projects.
aidlc doctor reports a project stamp that differs from the selected engine.
Between workflows, preview and apply a refresh:
aidlc config --dry-run
aidlc configConfig preserves managed root blocks and user-owned files, and reports local
framework edits as conflicts. In opencode.json, a refresh updates only the
entries AI-DLC wrote that nobody changed; your own entries, and any AI-DLC
entry you edited, stay as they are.
A refresh while a workflow is open is done, like a settings change (config models, flags, providers), and says your open work carries on.
Upgrade and rollback remain safe during a workflow because they do not touch
the project.
- Questions render as numbered prose options (no structured-question
widget); the questions FILE with
[Answer]:tags remains the source of truth. - Hooks ride the adapter plugin. opencode has no hooks.json/settings hook
registry;
.opencode/plugin/aidlc-opencode-adapter.tsmaps opencode's plugin hook moments onto the core hook bodies in.aidlc/hooks/(run as bun subprocesses): reviewer read-scope and the AIDLC bash boundary before tool execution; audit + sensors on write/edit/apply_patch; rebuild-stage-graph on bash, which also shows an engine error's exact message as a TUI toast; statusline sync on todowrite; subagent logging on task; presence minting on each human turn; state validation before compaction. - Forwarding-loop enforcement is advisory. The Stop seam is the
session.idleevent — reactive, not blocking. When the core stop hook answersblock, the plugin re-engages the loop by injecting a nudge prompt (marked with a sentinel so it never mints human presence). The nudge is a synthetic part: the agent reads it, and your chat does not show it. When you stop a turn with Esc, or reject a command the agent asked to run, no nudge follows until you write again. A chatting or pausing human is released by the hook's interactive cap. /aidlcshows what you typed. opencode would show the command's whole template as your message; the plugin keeps the template for the agent and shows your/aidlc ...line instead.- Personas are native subagents (
mode: subagent); the conductor adopts them inline for most stages and delegates via thetasktool for the two subagent stages (2.1 reverse-engineering, 3.5 code-generation). Their native permission map deniestask, so delegated agents cannot delegate again. Plugin composition emits the same.opencode/agents/twin for plugin personas. - Space switches preserve JSONC.
/aidlc space <name>updates the method glob in eitheropencode.jsonoropencode.jsoncwithout stripping comments or trailing commas, and keeps explicit persona memory paths aligned. - Construction swarm runs as task-tool fan-out only (
AIDLC_USE_SWARM=1is a loud no-op — no Workflow tool exists). - No session-end moment —
SESSION_ENDEDaudit events are not emitted. Pre-compaction validation DOES fire (experimental.session.compacting). - No statusline / welcome message — use
/aidlc --statusand the progress lines at gates. - MCP servers: none ship; configure your own under
mcp:inopencode.jsonif needed.
aidlc doctor # native install
bun .aidlc/tools/aidlc-utility.ts doctor # source/development copy
opencode run --command aidlc -- "--status" # /aidlc --status through the harnessThe doctor's opencode-specific checks: the adapter plugin present at
.opencode/plugin/, a project-root opencode.json or opencode.jsonc
present, and .opencode/command/aidlc.md present.