opencode-config-authoring
Skill0 starsChanged 41 days agoMITView on GitHub
Author and repair opencode's own configuration — opencode.json/opencode.jsonc, agents, commands, skills, plugins, MCP servers, permissions, references. Use when creating or editing anything under .opencode/ or ~/.config/opencode/, when opencode fails to start with ConfigInvalidError, when wiring a skill/agent/command/plugin, or when validating config shapes against the published JSON Schema before writing.
- Reads credentials
In this repository19 other files it gives its agents.
- api-doc-recallSkill
- assistant-runtime-architectureSkill
- code-disciplineSkill
- english-requestSkill
- github-repo-opsSkill
- git-safetySkill
- long-task-continuitySkill
- opencode-tool-outputSkill
- powershell-windowsSkill
- provider-reconnectSkill
- reference-booksSkill
- release-checklistSkill
- research-synthesisSkill
- self-improvementSkill
- skill-authoringSkill
- subagent-delegationSkill
- task-closureSkill
- test-first-fixSkill
- troubleshooting-treeSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 3 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 87
Write the description in third person ("Use when..."), lead with concrete trigger words, and add "Use ONLY when..." when the skill must …
- Very specific: line 179
Prefer new files in the correct location over inlining definitions into opencode.json.
- Distinctive: line 181
Do not reformat unrelated parts of a user's config.
- Distinctive: line 182
After every change: tell the user to quit and restart opencode.
- Distinctive: line 184
If their config is currently broken and opencode will not start, use the escape hatches below so they can repair it from inside a working …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Authoring opencode configuration
opencode loads config once at startup and hard-fails on an invalid shape. It is not hot-reloaded. So the cost of a wrong field is a broken CLI that you then have to fix from outside the running session. Validate first.
1. Where files live
| Scope | Path |
| Project config | ./opencode.json, ./opencode.jsonc, .opencode/opencode.json |
| Global config | ~/.config/opencode/opencode.json(c) — not ~/.opencode/ |
| Project agents | .opencode/agent/<name>.md or .opencode/agents/<name>.md |
| Global agents | ~/.config/opencode/agent(s)/<name>.md |
| Project commands | .opencode/command(s)/<name>.md |
| Global commands | ~/.config/opencode/command(s)/<name>.md |
| Project skills | .opencode/skill(s)/<name>/SKILL.md |
| Global skills | ~/.config/opencode/skill(s)/<name>/SKILL.md |
| External skills (auto) | ~/.claude/skills/<name>/SKILL.md, ~/.agents/skills/<name>/SKILL.md |
| Plugins (auto) | any *.ts/*.js in .opencode/plugin/ or .opencode/plugins/ |
Scopes are deep-merged; project overrides global. Both skill/ and skills/
work — pick skills/ and stay consistent within a tree.
2. Non-negotiable frontmatter rules
Agents (.opencode/agent/foo.md):
---
description: Reviews PRs for style violations.
mode: subagent
model: anthropic/claude-sonnet-4-6
permission:
edit: deny
bash: ask
---
You are a strict PR reviewer. Focus on ...- The body is the prompt. Never add a
prompt:key to frontmatter. - Allowed frontmatter keys only:
name, model, variant, description, mode, hidden, color, steps, options, permission, disable, temperature, top_p. Unknown keys are silently routed intooptions— a typo becomes dead config. mode:primary|subagent|all.default_agentmust point to a non-hiddenprimaryagent.
Commands (.opencode/command/deploy.md):
---
description: One sentence on what it does.
agent: build
model: anthropic/claude-sonnet-4-6
---
Deploy $1 to $2. Body is the prompt; `$ARGUMENTS` is everything after the
command name.- Body is the template. No
template:key in frontmatter. $ARGUMENTS= full argument string,$1/$2= positional.- Optional frontmatter:
description, agent, model, variant, subtask.
Skills (.opencode/skills/foo/SKILL.md): filename is exactly SKILL.md,
inside a folder named after the skill.
---
name: foo
description: What it does AND when to trigger it. Front-load literal
keywords/filenames the user would say.
---
Body in markdown.namerequired, lowercase-hyphenated, ≤64 chars, matches folder name.- A skill without a
descriptionis filtered out and never surfaces to the model. This is the single most common skill bug. - Write the description in third person ("Use when..."), lead with concrete
trigger words, and add "Use ONLY when..." when the skill must stay quiet on
adjacent topics. Optional extra frontmatter:
license,compatibility,metadata(string→string map).
3. Shape traps in opencode.json
These fields are the ones people get wrong because the natural shape is wrong:
{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-6",
"skills": { "paths": [".opencode/skills"], "urls": ["https://x/.well-known/skills/"] },
"references": { "docs": { "path": "../docs", "description": "why" } },
"agent": { "my-agent": { "mode": "subagent" } },
"command": { "deploy": { "template": "..." } },
"plugin": ["opencode-foo", "opencode-bar@1.2.3", "./local.ts", ["baz", { "k": "v" }]],
"mcp": {
"local-one": { "type": "local", "command": ["npx", "-y", "pkg"], "enabled": true, "environment": {} },
"remote-one": { "type": "remote", "url": "https://...", "headers": { "Authorization": "Bearer {env:TOKEN}" } }
},
"permission": { "edit": "deny", "bash": { "git *": "allow", "*": "ask" } }
}modelalways carries a provider prefix.skillsis an object withpaths/urls— not an array.agent,command,mcp,referencesare objects keyed by name.pluginis an array of strings or[name, options]tuples.mcp[name].commandis an array of strings, never a bare string.typeis required. Disable an inherited server with{"enabled": false}.permissioninside an object is a last-match-wins list: put broad rules first, narrow last.{"git *": "allow", "*": "ask"}allows git, asks for everything else.todowrite,question,webfetch,websearch,doom_loopaccept only a flat action — not a{pattern: action}object.{env:VAR}and{file:path}are the interpolation forms.${VAR}is not substituted.- Top-level
"permission": "allow"allows everything; almost never wanted.
4. Plugin module shape
The export is a function returning a hooks object, not an object literal.
import type { Plugin } from "@opencode-ai/plugin"
export default (async ({ client, project, directory, $ }) => {
return {
config: (cfg) => { /* mutate merged config in place */ },
"tool.execute.before": async (input, output) => { /* mutate output.args */ },
event: async (input) => {},
}
}) satisfies PluginHook surface: event, config, chat.message, chat.params, chat.headers,
tool.execute.before, tool.execute.after, tool.definition,
command.execute.before, shell.env, permission.ask, and the
experimental.* family (chat.messages.transform, chat.system.transform,
session.compacting, compaction.autocontinue, text.complete).
Non-callback, object-shaped entries: tool: { my_tool: {...} }, auth: {...},
provider: {...}.
5. Validation workflow — do this before writing
node scripts/validate-config.mjs <path-to-opencode.jsonc>The bundled script (scripts/validate-config.mjs, run with node, no deps) is
the entry point; the rules live in scripts/lib/ split by concern — jsonc
(text transform), schema (network), scan (filesystem), checks (rules),
report (findings). It:
- strips JSONC comments and trailing commas,
- parses JSON,
- fetches
https://opencode.ai/config.json, - checks every present key against the schema's allowed properties,
- enforces the traps from section 3 (skills object, array
mcp.command, provider prefix onmodel, flat-only permission keys), - flags references to skills/agents/commands whose files do not exist.
Exit code is nonzero on any violation. Read https://opencode.ai/config.json directly when the script cannot tell you a field's exact shape — it is the source of truth, not this skill.
6. Editing discipline
- Preserve
$schemaand every field the user did not ask you to touch. - Prefer new files in the correct location over inlining definitions into
opencode.json. - Do not reformat unrelated parts of a user's config; minimal diffs.
- After every change: tell the user to quit and restart opencode. The running session keeps the already-loaded config.
- If their config is currently broken and opencode will not start, use the escape hatches below so they can repair it from inside a working session.
7. Escape hatches
| Env var | Effect |
OPENCODE_DISABLE_PROJECT_CONFIG=1 | ignore the project config, start from globals only |
OPENCODE_CONFIG=/path/file.json | load an extra explicit config |
OPENCODE_CONFIG_CONTENT='{"..."}' | inject inline JSON as the final local-scope merge |
OPENCODE_DISABLE_DEFAULT_PLUGINS=1 | skip bundled default plugins |
OPENCODE_PURE=1 | skip all external plugins |
OPENCODE_DISABLE_EXTERNAL_SKILLS=1 | skip ~/.claude + ~/.agents skill scans |
OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 | skip only the ~/.claude scan |
Typical repair: launch with
OPENCODE_DISABLE_PROJECT_CONFIG=1 opencode, edit the file, restart without
the flag.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

