Overview
Custom commands are predefined prompts stored as.md files that can be executed from OpenCode’s command palette (Ctrl+K). They support:
- Named arguments with clear, semantic variable names
- Multiple argument types per command
- Organized hierarchies using subdirectories
- Two scopes: user-level and project-level commands
Command locations
OpenCode loads custom commands from three locations:XDG Config Home
$XDG_CONFIG_HOME/opencode/commands/Typically: ~/.config/opencode/commands/User commands available across all projectsHome Directory
$HOME/.opencode/commands/Alternative user commands locationUseful when XDG config not setProject Directory
<PROJECT_DIR>/.opencode/commands/Project-specific commandsSharable via version controlOpenCode creates these directories automatically if they don’t exist.
Creating basic commands
The simplest form is a Markdown file containing the prompt text:Named arguments
Named arguments make commands dynamic and reusable. They follow the pattern$NAME where NAME consists of uppercase letters, numbers, and underscores, and must start with a letter.
Argument syntax
Named argument in format
$NAMERules:- Must start with
$followed by a capital letter - Can contain uppercase letters, numbers, and underscores
- Examples:
$ISSUE_NUMBER,$FILE_PATH,$AUTHOR_NAME
Single argument example
Create~/.config/opencode/commands/explain-file.md:
user:explain-file, OpenCode prompts:
Multiple arguments example
Create~/.config/opencode/commands/fetch-issue.md:
ISSUE_NUMBERAUTHOR_NAME
Argument reuse
Arguments can be used multiple times throughout the command:$PATTERN and $DIRECTORY each appear twice, but only prompts for them once.
Organizing commands
Use subdirectories to organize related commands:git/commit.md→user:git:commitdocker/build.md→user:docker:buildtesting/unit.md→user:testing:unit
User vs project commands
- User Commands
- Project Commands
Prefix:
user:Locations:$XDG_CONFIG_HOME/opencode/commands/$HOME/.opencode/commands/
- Personal workflows
- General-purpose commands
- Commands used across multiple projects
- Development environment setup
- Code review templates
- Personal productivity commands
- Common debugging workflows
Real-world examples
GitHub issue workflow
~/.config/opencode/commands/github/issue-context.md:
Code review preparation
~/.config/opencode/commands/git/review-prep.md:
API endpoint documentation
.opencode/commands/api/document-endpoint.md:
Database migration
.opencode/commands/db/create-migration.md:
Test generation
~/.config/opencode/commands/testing/generate-tests.md:
Advanced patterns
Conditional logic in commands
While commands don’t have built-in conditionals, you can structure prompts to guide the AI:Multi-step workflows
Environment-aware commands
Command palette integration
Accessing custom commands:Browse commands
- User commands have
user:prefix - Project commands have
project:prefix - Navigate with arrow keys or
j/k
Argument input dialog
When a command with named arguments is executed:- Multi-argument dialog appears
- Arguments shown in order of first appearance
- Each argument has its own input field
- Use
Tabto move between fields - Press
Enterto submit all values - Press
Escapeto cancel
Best practices
Use descriptive names
Name arguments clearly:
$ISSUE_NUMBERnot$NUM$FILE_PATHnot$PATH$AUTHOR_NAMEnot$AUTHOR
Provide context
Include helpful comments:
Validate inputs
Structure prompts to handle invalid inputs:
Keep commands focused
One command = one task
- Break complex workflows into multiple commands
- Chain commands together when needed
Use hierarchical organization
Group related commands:
git/for git operationsdocker/for container taskstesting/for test commands
Document edge cases
Anticipate issues:
Sharing commands
Sharing with your team
Project commands in.opencode/commands/ can be version controlled:
Sharing user commands
Create a dotfiles repository:Publishing command collections
Create a dedicated repository:Troubleshooting
Command not appearing in palette
Command not appearing in palette
Check:
- File has
.mdextension - File is in correct directory
- Restart OpenCode to reload commands
- Check file permissions (should be readable)
Arguments not being prompted
Arguments not being prompted
Verify:
- Arguments use format
$NAME(capital letters) - Argument name starts with a letter
- No spaces in argument name
- Pattern:
$[A-Z][A-Z0-9_]*
Command executes but arguments blank
Command executes but arguments blank
Check:
- Argument names are unique
- Typing input correctly in dialog
- Not canceling dialog accidentally
Wrong command scope (user vs project)
Wrong command scope (user vs project)
Remember:
- Commands in
~/.config/opencode/commands/areuser:scoped - Commands in
.opencode/commands/areproject:scoped - Prefix determines scope, not location
Migration from simple commands
Upgrading existing simple commands to use named arguments: Before:- More flexible
- Reusable across different issues
- Self-documenting
- Team-friendly
Next steps
Built-in commands
Explore built-in commands like Initialize Project and Compact Session
AI tools
Learn about tools available for use in commands
Configuration
Configure command directories and behavior
Examples
Browse community command collections