Original explainer
OpenCode custom commands: a reusable review prompt with positional arguments
Turn a repeated prompt into a Markdown file under .opencode/commands, pass values with $1 and $2, and check argument count and injected content before running.
Retyping the same prompt makes its wording drift. This guide builds a /review-file command that takes a file path and a focus area, so the review prompt keeps one structure. You need to be able to create a .opencode/commands directory in a project. The file is written from the official commands page, and frontmatter, placeholders and the JSON equivalent were checked offline. OpenCode was not installed or run, and no model was called.
Action and acceptance sequence
Place the command
Use .opencode/commands per project or ~/.config/opencode/commands globally; the file name is the command name.[1]
Write template and arguments
Put description in frontmatter; the body is the template, and $1 and $2 read arguments.[1]
Check before running
Check argument count, quoting and injected content, then call it from the TUI.[1]
Write down the inputs and outputs first
Original exercise: the command is review-file and takes two values, a file path and a focus area, such as docs/setup.md and accuracy. The output is at most 5 review findings, each quoting the original text and saying how to verify it. List the two inputs in a table before writing the file. The official page places project commands in .opencode/commands/ and global ones in ~/.config/opencode/commands/; the Markdown file name becomes the command name, so review-file.md maps to /review-file.[1]
Frontmatter and template
Wrap frontmatter in --- at the top and set only description, which the TUI shows when you type /. The body is the template sent to the model: Review the file $1 with a focus on $2, then ask for at most 5 findings, a quote for each, and no proposed edits to other files. agent, model and subtask are optional: without agent the current agent is used, and subtask is for keeping a separate context. The page does not say whether a do-not-edit sentence limits tool permissions, so treat it as a request, not a permission boundary.[1]
Arguments, quoting and missing values
$1 and $2 read values by position; $ARGUMENTS is the whole argument string, suited to one free-text sentence, while two independent fields fit positional arguments better. The official example wraps its third argument in double quotes and $3 receives the whole quoted content, so values containing spaces need double quotes. The page does not say what $2 becomes when an argument is missing, or whether an @ file reference can follow $1. Treat both as unverified: count the arguments yourself and do not send the command when one is missing.[1]
Checks and stop conditions
Three things were checked offline: the frontmatter parses as YAML and has a description; a local splitter reproduced the official $1/$2/$3 example (it was compared with that one example only) and then filled docs/setup.md and accuracy; and in the equivalent opencode config, command.review-file.template matches the Markdown body exactly. On the first TUI call, confirm the prompt contains no leftover $1 or $2 and returns at most 5 findings. If a template injects shell output using an exclamation mark and backticks, the page says that output becomes part of the prompt, so do not use it with commands that print secrets. OpenCode was not started, and nothing here shows review quality.[1]
Article sources
Original editorial content; official descriptions and checking suggestions are distinguished.