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
LocationScopeShares with
.opencode/command/This repositoryAnyone who clones it
~/.config/opencode/command/You, everywhereNobody
npm pluginAny repository that installs itWhoever 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 description is 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.md for 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.

Project context and instruction files MCP servers and custom tools

Last refreshed 2026-09-18.