Skills, plugins and custom commands
Package repeatable procedures as commands, knowledge as skills, and behaviour changes as plugins, then share the whole setup across repositories.
Custom commands
---
description: Add a database migration with a matching down migration
agent: build
---
Create a migration for: $ARGUMENTS
Requirements:
- Generate it with the project's migration tool, never by hand.
- The down migration must be exact, not a no-op.
- Update the schema snapshot afterwards.
- Run the migration test suite and show the output..opencode/command/migrate.md -> /migrate add a unique index on users.email
~/.config/opencode/command/ -> available in every project
# the body supports the same injections as the prompt
$ARGUMENTS # everything typed after the command
!git diff # output of a shell command, inlined
@src/db.ts # contents of a file, inlined| Location | Scope | Shares with |
|---|---|---|
.opencode/command/ | This repository | Anyone who clones it |
~/.config/opencode/command/ | You, everywhere | Nobody |
| npm plugin | Any repository that installs it | Whoever installs the plugin |
Skills for knowledge, commands for actions
A command tells the agent to do something now. A skill describes how to do something, and is loaded when the task matches its description. That difference is what keeps a large body of procedure out of the always-on prompt.
---
name: incident-postmortem
description: Write a postmortem from an incident timeline. Use when asked for a postmortem, an incident report, or a root cause write-up.
---
Structure every postmortem as:
1. Impact - who was affected, for how long, in user-visible terms.
2. Timeline - timestamps, detection, actions, resolution.
3. Root cause - the mechanism, not the person.
4. Contributing factors - including the missing alert or test.
5. Action items - each with an owner and a due date.
Rules: no blame, no vague verbs, quantify the impact where possible.
See references/template.md for the house format.- The frontmatter
descriptionis the trigger - include the words someone would actually use. - Supporting files next to the skill are read only when the skill runs, which is what makes a large library affordable.
- Skills live in
.opencode/skills/<name>/SKILL.mdfor a project, or in the global config directory for you.
💡
Keep standing rules in AGENTS.md, actions in commands and procedures in skills. Once a single file holds all three, every session pays for all of it and the agent cannot tell which instruction applies to the task in front of it.
Plugins and sharing a setup
// .opencode/plugin/audit-edits.js
export const AuditEdits = async ({ project, client, $, directory }) => ({
"tool.execute.after": async (input, output) => {
if (input.tool !== "edit" && input.tool !== "write") return;
await client.app.log({
body: { service: "audit", level: "info", message: "edited " + input.args.filePath },
});
},
});{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "./.opencode/plugin/audit-edits.js"]
}- Plugins are JavaScript modules that can hook tool execution and session events, so they are the extension point for behaviour you need to be deterministic.
- They can be listed as npm package names or as relative paths, and both can be shared across repositories.
- A plugin runs with the same access as the agent process - installing one is trusting executable code, so read it first.
- The practical way to onboard a team: a plugin plus project commands plus AGENTS.md, installed from one repository.
Version the whole setup in a shared repository with the plugin and commands, and reference it from each project's configuration. A team whose agents share commands, rules and hooks produces diffs that review consistently.
FAQ
When should something be a plugin rather than a command?
If the requirement must hold no matter what the model decides - logging, a policy check, a deterministic transformation - it belongs in a plugin or a hook. If it is a procedure you invoke deliberately, a command is simpler and easier to read.
How do I share my setup with a teammate?
Commit
.opencode/command, .opencode/skills and any project plugins into the repository, keep only personal preferences in the global config, and never commit credentials. Everything else travels with a clone.Related
Project context and instruction files MCP servers and custom tools
Last refreshed 2026-09-18.