Skip to main content
Custom commands allow you to create reusable, parameterized prompts stored as Markdown files. They support named arguments for dynamic content, making them perfect for workflow automation and repetitive tasks.

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 projects

Home Directory

$HOME/.opencode/commands/Alternative user commands locationUseful when XDG config not set

Project Directory

<PROJECT_DIR>/.opencode/commands/Project-specific commandsSharable via version control
OpenCode creates these directories automatically if they don’t exist.

Creating basic commands

The simplest form is a Markdown file containing the prompt text:
1

Create the commands directory

2

Create a command file

Create ~/.config/opencode/commands/prime-context.md:
3

Use the command

  1. Press Ctrl+K to open command palette
  2. Select user:prime-context
  3. The command content is sent to the AI

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

string
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:
When you run user:explain-file, OpenCode prompts:

Multiple arguments example

Create ~/.config/opencode/commands/fetch-issue.md:
When executed, OpenCode prompts for each unique argument:
  1. ISSUE_NUMBER
  2. AUTHOR_NAME

Argument reuse

Arguments can be used multiple times throughout the command:
OpenCode recognizes that $PATTERN and $DIRECTORY each appear twice, but only prompts for them once.

Organizing commands

Use subdirectories to organize related commands:
Subdirectories become part of the command ID:
  • git/commit.mduser:git:commit
  • docker/build.mduser:docker:build
  • testing/unit.mduser:testing:unit

User vs project commands

Prefix: user:Locations:
  • $XDG_CONFIG_HOME/opencode/commands/
  • $HOME/.opencode/commands/
Best for:
  • Personal workflows
  • General-purpose commands
  • Commands used across multiple projects
  • Development environment setup
Examples:
  • 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:
1

Open command palette

Press Ctrl+K anywhere in OpenCode
2

Browse commands

  • User commands have user: prefix
  • Project commands have project: prefix
  • Navigate with arrow keys or j/k
3

Execute command

  • Press Enter to select
  • If command has arguments, input dialog appears
  • Enter values for each named argument
  • Press Enter to submit

Argument input dialog

When a command with named arguments is executed:
  1. Multi-argument dialog appears
  2. Arguments shown in order of first appearance
  3. Each argument has its own input field
  4. Use Tab to move between fields
  5. Press Enter to submit all values
  6. Press Escape to cancel
Dialog example:

Best practices

Use descriptive names

Name arguments clearly:
  • $ISSUE_NUMBER not $NUM
  • $FILE_PATH not $PATH
  • $AUTHOR_NAME not $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 operations
  • docker/ for container tasks
  • testing/ 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:
Users can clone and symlink:

Troubleshooting

Check:
  • File has .md extension
  • File is in correct directory
  • Restart OpenCode to reload commands
  • Check file permissions (should be readable)
Verify:
  • Arguments use format $NAME (capital letters)
  • Argument name starts with a letter
  • No spaces in argument name
  • Pattern: $[A-Z][A-Z0-9_]*
Check:
  • Argument names are unique
  • Typing input correctly in dialog
  • Not canceling dialog accidentally
Remember:
  • Commands in ~/.config/opencode/commands/ are user: scoped
  • Commands in .opencode/commands/ are project: scoped
  • Prefix determines scope, not location

Migration from simple commands

Upgrading existing simple commands to use named arguments: Before:
After:
Benefits:
  • 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