AgentsMD supports the OpenCode 1.18.32 CLI interface on POSIX hosts. The
adapter checks that exact version and its required flags before a model run.
Other versions need compatibility proof before this support claim expands.
Provider availability is independent of host support; select an exact
provider/model for each run. No model becomes a global default.
OpenCode composes project AGENTS.md found while walking up from its working
directory with global $XDG_CONFIG_HOME/opencode/AGENTS.md, defaulting to
~/.config/opencode/AGENTS.md; OPENCODE_CONFIG_DIR selects a custom global
directory. CLAUDE.md is a project fallback, and
~/.claude/CLAUDE.md is a global fallback when the OpenCode global file is
absent. Configured instructions add further sources. AgentsMD does not edit
that configuration. See the official instruction rules.
OpenCode loads Skills on demand from $OPENCODE_CONFIG_DIR/skills/<name>/SKILL.md,
defaulting to ~/.config/opencode/skills, and also from the shared
~/.agents/skills and ~/.claude/skills directories. Link AgentsMD Skills only
into the OpenCode directory. Codex and Grok Build scan ~/.agents/skills, and
Grok scans ~/.claude/skills, so shared links duplicate every Skill on a host
that already uses the plugin. The skills command group below creates and
removes those owned links. Verify available
names with opencode debug skill in the intended repository. See official
Skill discovery. Host-native frontmatter
differs. OpenCode ignores unrecognized fields. AgentsMD Skills are
model-invocable on every host, with approval gates inside each Skill body.
The global contract requires the full Project Direction triad before project work. OpenCode runs no Codex lifecycle hook, so the AgentsMD plugin below delivers the same loader payload in the system prompt instead. Without that plugin, a fresh session must read those files and applicable project instructions explicitly. The bounded adapter includes this obligation in its handoff prompt. It also requires current canonical instruction identity and adjacent private preferences. Use the shared setup walkthrough for initialization, discovery checks and the explicit reading fallback.
Use AGENTSMD_DIR for an extracted released artifact or stable canonical
checkout of a released tag. The source must be a regular global/AGENTS.md outside
plugin caches. Release identity is verified through the distribution workflow;
the link command verifies path ownership and bytes, not GitHub release status.
"$AGENTSMD_DIR/bin/agentsmd-opencode" install --source "$AGENTSMD_DIR/global/AGENTS.md"
"$AGENTSMD_DIR/bin/agentsmd-opencode" status --source "$AGENTSMD_DIR/global/AGENTS.md"
"$AGENTSMD_DIR/bin/agentsmd-opencode" update --source "$AGENTSMD_DIR/global/AGENTS.md"Commands emit JSON including source and target hashes when readable. Install
and update initialize adjacent private preferences only when absent. Shared
path checks reject cache-bound sources and targets. Ownership
means a symlink's absolute lexical destination exactly matches the explicitly
supplied canonical source. Status distinguishes missing, regular-file,
other-path, broken-link, divergent-link, cache-bound-link, and
owned-link. A broken link also reports whether its destination is owned. Only a healthy owned link
returns status exit code zero. A regular file containing identical bytes is
still user-owned and preserved.
Install creates a missing link or verifies an already-correct link. Update can repair a broken owned link. When an extracted release changes the source path, identify the previous canonical release explicitly:
"$AGENTSMD_DIR/bin/agentsmd-opencode" update \
--source "$AGENTSMD_DIR/global/AGENTS.md" --previous-source "$PREVIOUS_AGENTSMD_DIR/global/AGENTS.md"
"$AGENTSMD_DIR/bin/agentsmd-opencode" uninstall --source "$AGENTSMD_DIR/global/AGENTS.md"Update refuses any target that is not the exact previous owned link. Uninstall
removes only the exact supplied owned link, including a broken owned link.
There is no force replacement option in this adapter. For an authorized
migration, the common agentsmd-global-instructions install --host opencode --source "$AGENTSMD_DIR/global/AGENTS.md" --replace preserves a recoverable backup. Source files, shared Skills, opencode.json,
opencode.jsonc, preferences and credentials remain in place. Start a fresh
OpenCode session after a supported install or update.
skills install creates one owned symlink per Skill directory that holds a
SKILL.md, named after that directory, under $OPENCODE_CONFIG_DIR/skills,
otherwise $XDG_CONFIG_HOME/opencode/skills, defaulting to
~/.config/opencode/skills. The command resolves that directory exactly as the
instruction link resolves its own.
"$AGENTSMD_DIR/bin/agentsmd-opencode" skills install --source "$AGENTSMD_DIR/skills"
"$AGENTSMD_DIR/bin/agentsmd-opencode" skills update --source "$AGENTSMD_DIR/skills"
"$AGENTSMD_DIR/bin/agentsmd-opencode" skills status --source "$AGENTSMD_DIR/skills"
"$AGENTSMD_DIR/bin/agentsmd-opencode" skills uninstall --source "$AGENTSMD_DIR/skills"
opencode debug skillEach entry reports one of the instruction link's states: missing,
regular-file, other-path, broken-link, divergent-link,
cache-bound-link and owned-link. The ownership rule is the same: a symlink
whose absolute lexical destination exactly matches the supplied Skill directory.
Install creates missing links and verifies existing owned links. It never
replaces an existing entry of any kind. Each entry is decided on its own, as the
instruction link decides its single target, so a blocked entry is preserved and
reported while the remaining Skills still install, and the command exits 2.
Uninstall removes only exact owned links, including a broken owned link, and
exits 2 when any entry was not an owned link. Status exits 0 only when every
Skill is an owned link.
Update installs and verifies the current inventory first. Only after that succeeds
does it retire exact owned links whose source no longer contains SKILL.md.
A blocked replacement or empty source preserves the old links. This migrates
the former separate skills to the single Operations bundle without removing
unrelated installations. Repeat updates are safe.
Install reports the Skills present in the source directory. Status and uninstall
also report any target entry whose link destination is exactly
<source>/<name>, so an owned link survives removal of its source Skill and
uninstall still removes it. Install and update require an existing source directory.
Sources inside plugins/cache are rejected, including a single Skill directory
that resolves into a plugin cache; that entry is refused before any link is
created. A target is rejected when the Skill directory resolves under ~/.agents/skills, ~/.claude/skills,
~/.grok/skills or a plugins/cache path. Codex and Grok Build scan
~/.agents/skills, and Grok scans ~/.claude/skills, so links there would list
every Skill twice on a host that already uses the plugin. Skill links do not
expand the bounded run contract, which stays pinned to 1.18.32. Run
opencode debug skill in a fresh session in the intended repository and confirm
each AgentsMD Skill appears exactly once.
plugin install creates one owned symlink named agentsmd-project-direction.js
under $OPENCODE_CONFIG_DIR/plugins, otherwise $XDG_CONFIG_HOME/opencode/plugins,
defaulting to ~/.config/opencode/plugins. The command resolves that directory
exactly as the instruction and Skill links resolve their own. The source is the
canonical clone or released artifact root, or its
opencode/agentsmd-project-direction.js file.
"$AGENTSMD_DIR/bin/agentsmd-opencode" plugin install --source "$AGENTSMD_DIR"
"$AGENTSMD_DIR/bin/agentsmd-opencode" plugin status --source "$AGENTSMD_DIR"
"$AGENTSMD_DIR/bin/agentsmd-opencode" plugin uninstall --source "$AGENTSMD_DIR"OpenCode loads that module and the plugin appends the Project Direction block to
the model's system prompt on every request in the session's working directory.
It runs bin/project-direction hook --host opencode beside the link's canonical
target with a synthetic SessionStart input, so OpenCode receives the payload
the Codex hook emits, including the not_in_repository and uninitialized
verdicts. Any loader failure leaves the system prompt unchanged and logs one
agentsmd-project-direction: line to stderr. Start a fresh OpenCode session
after install; a running session keeps its loaded plugins.
The plugin uses experimental.chat.system.transform, which is experimental in
OpenCode 1.18.32, the version the bounded run adapter pins. The plugin
context exposes no host version, so the pin is documented, not enforced at
runtime. Treat a different OpenCode version as unproved until the seam is
rechecked.
The entry reports the Skill links' ownership states: missing, owned-link,
divergent-link, regular-file, other-path and broken-link. Install
creates a missing link and verifies an existing owned link. It never replaces an
existing entry of any kind; a foreign entry is preserved and reported, and the
command exits 2. Status exits 0 only for a healthy owned link.
Install alone validates the source. It rejects a path holding any symlinked
component and requires a regular plugin file at
<clone root>/opencode/agentsmd-project-direction.js beside a regular
<clone root>/bin/project-direction, because the plugin runs the loader of its
own clone. Status and uninstall derive ownership from the lexical link
destination only, so an owned link stays reportable and removable after the
clone was removed, emptied, altered or replaced by an alias. Uninstall removes
any owned entry and nothing else. Sources under plugins/cache, a cache-bound
target and a file under another name or outside an opencode directory are
rejected everywhere, because those checks are lexical.
The coordinator supplies the complete Issue scope, accepted decisions, exact base and dependency state, and granted authority in a prompt file. Repository root and starting HEAD must match before dispatch. The base must be an exact available commit. The output directory must not exist.
"$AGENTSMD_DIR/bin/agentsmd-opencode" run \
--cwd "$ISSUE_WORKSPACE" \
--issue https://github.com/OWNER/REPO/issues/NUMBER \
--base "$EXACT_BASE_SHA" --head "$EXACT_HEAD_SHA" \
--model "$EXACT_PROVIDER_MODEL" --permissions configured \
--prompt-file "$TASK_PROMPT" --output "$NEW_RECEIPT_DIRECTORY" --timeout 900configured preserves OpenCode's configured permissions with closed stdin.
auto adds --auto only when that tool mode has been granted; explicit OpenCode
denials remain effective. Neither mode is a sandbox or a grant of production,
credential, merge, release or installation authority. Use an exclusive task
workspace and scoped host permissions. The adapter inherits the host environment
and lets OpenCode use its existing authentication; it never reads credential
files or writes configuration. See the official CLI contract.
Each run starts a new session and writes a private directory containing raw JSON
events, stderr, extracted text and receipt.json. Raw model/tool output can
contain private task data, so review it before publishing. The receipt records
Issue, working directory, exact base and before/after HEAD, requested model and
permission mode, prompt hashes, version, timestamps, process exit status,
session IDs, result, working-tree status and evidence hashes. It does not dump
the environment. Timeout terminates the process group and records failure.
Malformed events, host errors, missing session/text evidence and nonzero exit
status cannot produce a candidate. A candidate is an unreviewed implementer
result. The coordinator verifies scope, model/session evidence, exact-SHA proof,
review and external authority independently.
python3 -m unittest tests.test_opencode -v tests isolated HOME/XDG ownership,
config and credential preservation, lifecycle transitions, Skill and plugin link
install, repeat install, preserved user entries, uninstall and rejected shared
directories, explicit CLI arguments, stale-head refusal, malformed events,
errors and timeout. It uses a
fake CLI and spends no model quota. python3 -m unittest tests.test_opencode_plugin -v
runs the plugin module under Node against a fixture repository and asserts that
the appended system entry equals the loader payload byte for byte, that an
installed link resolves the canonical loader, and that an unreachable or failing
loader leaves the system prompt unchanged. It skips when node is absent. The full repository and versionctl suites
remain the deterministic release gates.
Issue #78 separately requires one requested fresh-session fixture using the
real CLI and an authorized model. Record version, selected model, global and
project instruction composition, full Project Direction hashes, shared Skill
discovery, fixture read/write result and exact HEAD. That fixture proves only
the exercised integration. User-owned behavioral Live Verification through
ordinary work on real projects remains separately pending until user evidence
exists, as defined by root AGENTS.md.
OpenCode does not reproduce Codex app-native task coordination, memory,
connectors, computer/browser UI tools or lifecycle hooks. The plugin covers
system-prompt delivery only; it reproduces no UserPromptSubmit or subagent
refresh semantics. Host-native tools and
permissions remain OpenCode's responsibility; AgentsMD supplies the shared
operating contract and the narrow CLI handoff.