agentsclimarketplace

Opencode commands

Skill Timmy6942025/opencode-builder-skill/skills/opencode-commands

Kilo/agent skill for building OpenCode extensions, plugins, and integrations

Install
npx -y skills add Timmy6942025/opencode-builder-skill --skill opencode-commands

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

36.1 KB, as published. Nobody here has run it

OpenCode Custom Commands

πŸ“š Official Docs: For the latest information, always refer to the official documentation: https://opencode.ai/docs/commands/

Expert skill for building, configuring, and troubleshooting OpenCode's custom command system. Covers markdown command files, JSON configuration, prompt placeholders, command options, built-in commands, keybinds, and overriding built-ins.

Overview

OpenCode's custom command system lets you define reusable prompts that execute via slash commands in the TUI (e.g., /test, /review, /deploy). Commands are triggered by typing / followed by the command name in the prompt input.

Custom commands are in addition to the built-in commands like /init, /undo, /redo, /share, /help. Custom commands can also override built-in command names β€” if you define a custom command with the same name as a built-in, the custom version takes precedence.

Commands support prompt placeholders ($ARGUMENTS, $1, $2, !command``, @filename) for dynamic prompt construction, and options for agent routing, model override, and subagent invocation.


Create via Markdown

The primary way to create custom commands is by placing markdown files in the commands/ directory.

Location

ScopePath
Project.opencode/commands/
Global~/.config/opencode/commands/

The file name (minus .md extension) becomes the command name:

File NameCommand
test.md/test
review.md/review
deploy-staging.md/deploy-staging
create-component.md/create-component

Structure

A markdown command file has two parts:

  1. Frontmatter (YAML between --- delimiters) β€” defines command properties
  2. Content (everything after the closing ---) β€” becomes the prompt template sent to the LLM

Frontmatter Fields

FieldRequiredDescription
descriptionNoShort description shown in the TUI command list when typing /
agentNoWhich agent executes this command. If the agent is a subagent, triggers subagent invocation by default
modelNoOverride the default model for this command

Complete Example

Create .opencode/commands/test.md:

---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---

Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.

Usage in TUI:

/test

Multi-line Prompts

The content after the frontmatter is the prompt template. You can use multiple paragraphs, code blocks, and any markdown formatting β€” everything is sent as-is to the LLM:

---
description: Refactor module with best practices
---

You are a senior software engineer. Analyze the following module and refactor it according to these principles:

1. Single Responsibility Principle
2. DRY (Don't Repeat Yourself)
3. Clear naming conventions
4. Proper error handling

Ensure all existing tests still pass after refactoring.

Nested Directories

Commands can be organized in subdirectories. The directory structure maps to a namespace:

.opencode/commands/
β”œβ”€β”€ test.md              β†’ /test
β”œβ”€β”€ review.md            β†’ /review
└── db/
    β”œβ”€β”€ migrate.md       β†’ /db/migrate
    └── seed.md          β†’ /db/seed

Note: The exact namespace separator behavior depends on your OpenCode version. Verify with !ls .opencode/commands/ if unsure.


Create via JSON

You can also define commands in opencode.json (or opencode.jsonc) using the command field.

JSON Configuration

{
  "$schema": "https://opencode.ai/config.json",
  "command": {
    // This key becomes the command name
    "test": {
      // Required: the prompt sent to the LLM
      "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
      // Shown in TUI command list
      "description": "Run tests with coverage",
      // Which agent executes (optional)
      "agent": "build",
      // Override model (optional)
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }
  }
}

Usage:

/test

JSON vs Markdown

AspectJSON (opencode.json)Markdown (.opencode/commands/)
LocationProject root config fileDedicated directory
Template fieldtemplate (string, \n for newlines)Content after frontmatter (natural newlines)
Multi-commandAll in one fileOne file per command
Version controlChanges mixed with other configIsolated per command file
DiscoverabilityRequires reading configBrowsable via file tree

Recommendation: Use markdown files for most custom commands. Use JSON for quick one-off commands or when you prefer centralized configuration.


Prompt Placeholders

Prompt placeholders allow dynamic content injection into your command templates. They are evaluated at runtime when the command is executed.

$ARGUMENTS β€” All Arguments as Single String

The $ARGUMENTS placeholder is replaced with all arguments passed to the command as a single concatenated string.

Markdown example:

---
description: Create a new component
---

Create a new React component named $ARGUMENTS with TypeScript support.
Include proper typing and basic structure.

JSON example:

{
  "command": {
    "component": {
      "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.",
      "description": "Create a new component"
    }
  }
}

Usage:

/component Button

Resulting prompt:

Create a new component named Button with TypeScript support.
Include proper typing and basic structure.

Usage with multiple words:

/component UserAvatar with image loading

Resulting prompt:

Create a new component named UserAvatar with image loading with TypeScript support.
Include proper typing and basic structure.

Note: $ARGUMENTS captures everything after the command name as one string, including spaces. It does not split on spaces.


$1, $2, $3 β€” Positional Arguments

Individual arguments are accessed via positional parameters. Arguments are split by whitespace.

Markdown example:

---
description: Create a new file with content
---

Create a file named $1 in the directory $2
with the following content: $3

JSON example:

{
  "command": {
    "create-file": {
      "template": "Create a file named $1 in the directory $2\nwith the following content: $3",
      "description": "Create a new file with content"
    }
  }
}

Usage:

/create-file config.json src "{ \"key\": \"value\" }"

Resulting prompt:

Create a file named config.json in the directory src
with the following content: { "key": "value" }

Positional argument mapping:

PlaceholderValue
$1config.json
$2src
$3{ "key": "value" }

Additional positional arguments:

  • $4, $5, $6, ... β€” Access arguments by position (up to the number of arguments provided)
  • Unreferenced positional parameters are simply ignored in the prompt

Multi-word arguments: Positional parameters split on whitespace. To pass a multi-word value as a single positional argument, quote it:

/create-file README.md . "Hello World"

This maps:

  • $1 β†’ README.md
  • $2 β†’ .
  • $3 β†’ Hello World

!command`` β€” Inject Bash Command Output

Use backtick syntax with ! prefix to run a bash command and inject its output directly into the prompt. The command runs in your project's root directory.

Syntax: !command``

Markdown example β€” Analyze test coverage:

---
description: Analyze test coverage
---

Here are the current test results:
!`npm test`

Based on these results, suggest improvements to increase coverage.

Markdown example β€” Review recent changes:

---
description: Review recent changes
---

Recent git commits:
!`git log --oneline -10`

Review these changes and suggest any improvements.

Markdown example β€” Check project structure:

---
description: Analyze project structure
---

Project file tree:
!`find . -type f -name "*.ts" | head -30`

Analyze the module organization and suggest improvements.

JSON example:

{
  "command": {
    "review-changes": {
      "template": "Recent git commits:\n!`git log --oneline -10`\n\nReview these changes and suggest any improvements.",
      "description": "Review recent changes"
    }
  }
}

Behavior:

  • The bash command executes in the project's root directory
  • stdout is captured and inserted into the prompt at the placeholder position
  • stderr is typically not included (or handled silently)
  • If the command fails, the output may be empty or contain an error message
  • The command runs synchronously β€” the prompt is not sent until the command completes
  • Multiple !command`` placeholders can be used in a single prompt

Advanced examples:

---
description: Check dependency versions
---

Current dependencies:
!`cat package.json | jq '.dependencies'`

Check for outdated or vulnerable packages.
---
description: Lint and format check
---

Lint output:
!`npm run lint 2>&1`

Format check:
!`npx prettier --check . 2>&1`

Fix any issues found.

@filename β€” Include File Content

Use @ followed by a filename to include the file's content in the prompt. The file path is relative to the project root.

Syntax: @filename or @path/to/file

Markdown example β€” Review a component:

---
description: Review component
---

Review the component in @src/components/Button.tsx.
Check for performance issues and suggest improvements.

Markdown example β€” Compare files:

---
description: Compare implementations
---

Compare these two implementations:
@src/utils/old-helper.ts
@src/utils/new-helper.ts

Identify the differences and explain which approach is better.

JSON example:

{
  "command": {
    "review-component": {
      "template": "Review the component in @src/components/Button.tsx.\nCheck for performance issues and suggest improvements.",
      "description": "Review component"
    }
  }
}

Behavior:

  • The file content is resolved relative to the project root directory
  • The file's content is included verbatim in the prompt
  • The LLM receives the file content as context
  • If the file does not exist, the placeholder may be included as-is or produce an error depending on the OpenCode version
  • Multiple @ references can be used in a single prompt

Fuzzy file search: In the TUI prompt input (outside of commands), typing @ triggers a fuzzy file search. Inside command templates, @ references are resolved literally by path.


Command Options

Each custom command supports the following configuration options. These can be set in JSON (opencode.json) or via frontmatter in markdown files.

template (Required for JSON; implicit in Markdown)

The prompt that will be sent to the LLM when the command is executed.

In JSON: The template field is required. Use \n for newlines within the string.

{
  "command": {
    "test": {
      "template": "Run the full test suite with coverage report.\nFocus on failures and suggest fixes."
    }
  }
}

In Markdown: The template is the content after the frontmatter. No separate field needed β€” everything below the closing --- becomes the template.

---
description: Run tests
---

Run the full test suite with coverage report.
Focus on failures and suggest fixes.

description

A brief description of what the command does. This is displayed in the TUI command list when you type / and is purely informational.

In JSON:

{
  "command": {
    "test": {
      "template": "...",
      "description": "Run tests with coverage"
    }
  }
}

In Markdown frontmatter:

---
description: Run tests with coverage
---

In TUI: When you type /, the command list shows each command's description next to its name:

/test      Run tests with coverage
/review    Review code changes
/deploy    Deploy to staging

agent

Optionally specify which agent should execute this command. If the specified agent is a subagent, the command will trigger a subagent invocation by default (see subtask below).

In JSON:

{
  "command": {
    "review": {
      "template": "Review the recent code changes for quality and correctness.",
      "agent": "plan"
    }
  }
}

In Markdown frontmatter:

---
description: Review code
agent: plan
---

Review the recent code changes for quality and correctness.

Behavior:

  • If agent is not specified, the command uses the current agent (the one active in the session)
  • If agent specifies a subagent, the command automatically invokes it as a subagent (unless subtask: false is set)
  • If agent specifies the primary agent, the command runs in the primary context (unless subtask: true is set)

subtask

A boolean that forces the command to trigger a subagent invocation. This is useful when you want the command to run in an isolated context without polluting your primary conversation.

In JSON:

{
  "command": {
    "analyze": {
      "template": "Analyze the codebase for security vulnerabilities.",
      "subtask": true
    }
  }
}

In Markdown frontmatter:

---
description: Security analysis
subtask: true
---

Analyze the codebase for security vulnerabilities.

Behavior:

  • When subtask: true, the agent acts as a subagent regardless of its mode setting in agent configuration
  • When subtask: false, the agent runs in its default mode even if it's a subagent
  • If not specified, defaults to false unless the agent is a subagent (in which case it defaults to true)

Use cases for subtask: true:

  • Long-running analysis that shouldn't block the main conversation
  • Tasks where you want results returned without full conversation context
  • Parallel execution of independent tasks
  • Keeping the primary context clean for focused work

model

Override the default model for this command. Useful when a specific task benefits from a different model (e.g., a reasoning-heavy task using a more capable model, or a simple task using a faster/cheaper model).

In JSON:

{
  "command": {
    "analyze": {
      "template": "Analyze this codebase for architectural issues.",
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }
  }
}

In Markdown frontmatter:

---
description: Architectural analysis
model: anthropic/claude-3-5-sonnet-20241022
---

Analyze this codebase for architectural issues.

Common model override patterns:

Use CaseModel Strategy
Quick formatting/lintingFast, cheaper model (e.g., openai/gpt-4o-mini)
Deep code reviewMost capable model available
Simple file generationMid-tier model
Complex multi-step reasoningTop-tier reasoning model

Built-in Commands

OpenCode ships with the following built-in commands. These are always available in the TUI. Custom commands can override any of these by using the same name.

/connect

Add a provider to OpenCode. Allows you to select from available providers and add their API keys.

/connect

/compact

Compact the current session. This summarizes the conversation to reduce token usage while preserving key context. Useful for long sessions approaching context limits.

Alias: /summarize

/compact

Keybind: ctrl+x c


/details

Toggle the display of tool execution details. When enabled, you can see detailed information about how tools are executed (file reads, bash commands, etc.).

/details

/editor

Open an external editor for composing messages. Uses the editor set in your EDITOR environment variable. This is useful for writing long or complex prompts that benefit from proper text editing.

/editor

Keybind: ctrl+x e

Editor setup: Set the EDITOR environment variable:

# Nano
export EDITOR=nano

# Vim
export EDITOR=vim

# VS Code (with --wait for blocking mode)
export EDITOR="code --wait"

# Cursor
export EDITOR="cursor --wait"

For GUI editors, the --wait flag is required so the process blocks until the editor is closed.


/exit

Exit OpenCode.

Aliases: /quit, /q

/exit

Keybind: ctrl+x q


/export

Export the current conversation to Markdown and open it in your default editor. Uses the EDITOR environment variable. The exported markdown includes all messages, tool results, and file changes.

/export

Keybind: ctrl+x x


/help

Show the help dialog with available commands and keybinds.

/help

/init

Guided setup for creating or updating AGENTS.md. This walks you through configuring project-specific rules, conventions, and instructions for the AI agent.

/init

/models

List available models. Shows all models configured across your providers and allows you to switch the active model.

/models

Keybind: ctrl+x m


/new

Start a new session. Clears the current conversation and begins fresh.

Alias: /clear

/new

Keybind: ctrl+x n


/redo

Redo a previously undone message. Only available after using /undo. Restores the most recently undone user message, all subsequent responses, and any file changes.

Important: Your project must be a Git repository for file changes to be restored. Internally, OpenCode uses Git to manage file change reversions.

/redo

Keybind: ctrl+x r


/sessions

List and switch between sessions. Shows all saved sessions with timestamps and allows you to resume a previous conversation.

Aliases: /resume, /continue

/sessions

Keybind: ctrl+x l


/share

Share the current session. Generates a shareable link to the conversation. Learn more.

/share

/themes

List available themes. Allows you to switch the TUI color scheme.

/themes

Keybind: ctrl+x t


/thinking

Toggle the visibility of thinking/reasoning blocks in the conversation. When enabled, you can see the model's internal reasoning process for models that support extended thinking.

Note: This command controls display only β€” it does not enable or disable the model's actual reasoning capabilities. To toggle reasoning capabilities, use ctrl+t to cycle through model variants.

/thinking

/undo

Undo the last message in the conversation. Removes the most recent user message, all subsequent responses, and any file changes made by those responses.

Important: Your project must be a Git repository for file changes to be reverted. Internally, OpenCode uses Git to manage file change reversions.

/undo

Keybind: ctrl+x u


/unshare

Unshare the current session. Revokes the shareable link previously generated with /share. Learn more.

/unshare

Keybinds

OpenCode uses a leader key pattern for command shortcuts. The default leader key is ctrl+x. To execute a command via keybind, press the leader key followed by the shortcut key.

Leader key: ctrl+x (configurable in tui.json via keybinds.leader)

Leader timeout: 2000ms (configurable via leader_timeout in tui.json)

Complete Keybind Reference

CommandKeybindDescription
/compactctrl+x cCompact/summarize the current session
/editorctrl+x eOpen external editor for message input
/exitctrl+x qExit OpenCode
/exportctrl+x xExport conversation to Markdown
/modelsctrl+x mList available models
/newctrl+x nStart a new session
/redoctrl+x rRedo last undone message
/sessionsctrl+x lList/switch between sessions
/themesctrl+x tList available themes
/undoctrl+x uUndo last message

Other Notable Keybinds (Non-command)

KeybindAction
ctrl+x bToggle sidebar
ctrl+x sStatus view
ctrl+x aAgent list
ctrl+x gSession timeline
ctrl+x hToggle tips / conceals
ctrl+x yCopy message
ctrl+pCommand palette
ctrl+tCycle model variants
tab / shift+tabCycle agents
escapeInterrupt session
ctrl+cClear input
ctrl+zSuspend terminal (Unix only)

Customizing Keybinds

Keybinds are configured in tui.json (separate from opencode.json):

{
  "$schema": "https://opencode.ai/tui.json",
  "leader_timeout": 2000,
  "keybinds": {
    "leader": "ctrl+x",
    "session_compact": "<leader>c",
    "session_new": "<leader>n",
    "session_list": "<leader>l"
  }
}

To disable a keybind, set it to "none":

{
  "keybinds": {
    "session_compact": "none"
  }
}

Multiple keybinds for the same action can be specified as an array:

{
  "keybinds": {
    "messages_copy": ["<leader>y", "ctrl+shift+c"]
  }
}

Override Built-ins

Custom commands can override built-in commands by using the same command name. If you define a custom command named help, /help will execute your custom version instead of the built-in help dialog.

Example: Custom /help

---
description: Show project-specific help
---

## Project Commands

- `/test` β€” Run test suite
- `/lint` β€” Run linter
- `/deploy` β€” Deploy to staging

## Project Conventions

- Use TypeScript strict mode
- Follow ESLint airbnb config
- Write tests for all new features

Now /help shows your custom help content instead of the default OpenCode help.

Example: Custom /init

---
description: Initialize project for AI coding
---

## Setting Up AGENTS.md

Run the following steps to initialize this project:

1. Read the README.md for project overview
2. Examine package.json for dependencies and scripts
3. Check tsconfig.json for TypeScript configuration
4. Create AGENTS.md with project-specific rules

Important Considerations

  • Override scope: Overrides apply project-wide. If you override /undo, you lose access to the built-in undo unless you explicitly implement reversal logic.
  • Naming conflicts: If a custom command and a built-in share the same name, the custom command always wins. There is no fallback mechanism.
  • Documentation: When overriding built-ins, document the override clearly so team members understand the behavior change.
  • Global vs project: Global commands (in ~/.config/opencode/commands/) can also override built-ins, affecting all projects. Use global overrides cautiously.

Complete Examples

Example 1: Test Runner with Coverage

.opencode/commands/test.md:

---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---

Run the full test suite with coverage report:

1. Run `!`npm test -- --coverage``
2. Analyze the coverage output
3. Identify any files below 80% coverage
4. For files below threshold, suggest specific test cases to add
5. Check for any flaky or skipped tests

Output a summary:
- Total coverage percentage
- Files below threshold (list each)
- Skipped/flaky tests
- Recommended next steps

JSON equivalent:

{
  "command": {
    "test": {
      "template": "Run the full test suite with coverage report:\n\n1. Run `!`npm test -- --coverage``\n2. Analyze the coverage output\n3. Identify any files below 80% coverage\n4. For files below threshold, suggest specific test cases to add\n5. Check for any flaky or skipped tests\n\nOutput a summary:\n- Total coverage percentage\n- Files below threshold (list each)\n- Skipped/flaky tests\n- Recommended next steps",
      "description": "Run tests with coverage",
      "agent": "build",
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }
  }
}

Example 2: Component Creator with $ARGUMENTS

.opencode/commands/component.md:

---
description: Create a new React component
---

Create a new React component named $ARGUMENTS following these conventions:

## File Structure
Create these files:
- `src/components/$ARGUMENTS/index.tsx` β€” Main component
- `src/components/$ARGUMENTS/$ARGUMENTS.test.tsx` β€” Unit tests
- `src/components/$ARGUMENTS/$ARGUMENTS.stories.tsx` β€” Storybook stories
- `src/components/$ARGUMENTS/styles.module.css` β€” CSS module styles

## Requirements
- TypeScript with strict typing
- Functional component with hooks
- Props interface exported as `$ARGUMENTSProps`
- Default export of the component
- CSS modules for styling (import as `styles`)
- Basic unit test with React Testing Library
- Storybook story with default and loading variants

## Example Props Interface
```typescript
export interface $ARGUMENTSProps {
  className?: string;
  children?: React.ReactNode;
}

Generate all files with complete, production-ready code.


**Usage:**

/component Button /component UserAvatar /component Modal


**Resulting prompt (for `/component Button`):**

Create a new React component named Button following these conventions:

File Structure

Create these files:

  • src/components/Button/index.tsx β€” Main component
  • src/components/Button/Button.test.tsx β€” Unit tests
  • src/components/Button/Button.stories.tsx β€” Storybook stories
  • src/components/Button/styles.module.css β€” CSS module styles ...

---

### Example 3: Git Changelog with !`git log`

**`.opencode/commands/changelog.md`:**

```markdown
---
description: Generate changelog from git history
---

Generate a changelog from recent git history.

## Recent commits:
!`git log --oneline --since="2 weeks ago" --no-merges`

## Full diff summary:
!`git diff --stat HEAD~10..HEAD`

Based on these changes, generate a structured changelog with:

### Categories
- **Features** β€” New functionality
- **Bug Fixes** β€” Issue resolutions
- **Refactors** β€” Code improvements without behavior changes
- **Documentation** β€” Doc updates
- **Chores** β€” Maintenance tasks

### Format
Use [Keep a Changelog](https://keepachangelog.com/) format with version header.
Date range: last 2 weeks.
Group related commits together.
Write user-facing descriptions (not developer implementation details).

Output the changelog in markdown format.

JSON equivalent:

{
  "command": {
    "changelog": {
      "template": "Generate a changelog from recent git history.\n\n## Recent commits:\n!`git log --oneline --since=\"2 weeks ago\" --no-merges`\n\n## Full diff summary:\n!`git diff --stat HEAD~10..HEAD`\n\nBased on these changes, generate a structured changelog with:\n\n### Categories\n- **Features** β€” New functionality\n- **Bug Fixes** β€” Issue resolutions\n- **Refactors** β€” Code improvements without behavior changes\n- **Documentation** β€” Doc updates\n- **Chores** β€” Maintenance tasks\n\n### Format\nUse [Keep a Changelog](https://keepachangelog.com/) format with version header.\nDate range: last 2 weeks.\nGroup related commits together.\nWrite user-facing descriptions (not developer implementation details).\n\nOutput the changelog in markdown format.",
      "description": "Generate changelog from git history"
    }
  }
}

Example 4: Code Review with @file Reference

.opencode/commands/review.md:

---
description: Review a specific file for issues
agent: plan
---

Perform a thorough code review of @src/api/handlers.ts.

## Review Criteria

### Correctness
- Logic errors and edge cases
- Null/undefined handling
- Race conditions and async issues
- Off-by-one errors

### Security
- Input validation and sanitization
- SQL injection / XSS vulnerabilities
- Authentication/authorization checks
- Secrets or credentials in code

### Performance
- Unnecessary re-renders or computations
- Memory leaks
- N+1 query patterns
- Inefficient algorithms

### Code Quality
- Naming conventions and clarity
- Function length and complexity
- DRY violations
- Error handling completeness

### Testing
- Test coverage gaps
- Missing edge case tests
- Mock quality

## Output Format
For each issue found:
1. **Line number** and code snippet
2. **Severity** (Critical / Warning / Suggestion)
3. **Category** (from above)
4. **Description** of the issue
5. **Recommended fix** with code example

End with an overall assessment and priority-ordered action items.

JSON equivalent:

{
  "command": {
    "review": {
      "template": "Perform a thorough code review of @src/api/handlers.ts.\n\n## Review Criteria\n\n### Correctness\n- Logic errors and edge cases\n- Null/undefined handling\n- Race conditions and async issues\n- Off-by-one errors\n\n### Security\n- Input validation and sanitization\n- SQL injection / XSS vulnerabilities\n- Authentication/authorization checks\n- Secrets or credentials in code\n\n### Performance\n- Unnecessary re-renders or computations\n- Memory leaks\n- N+1 query patterns\n- Inefficient algorithms\n\n### Code Quality\n- Naming conventions and clarity\n- Function length and complexity\n- DRY violations\n- Error handling completeness\n\n### Testing\n- Test coverage gaps\n- Missing edge case tests\n- Mock quality\n\n## Output Format\nFor each issue found:\n1. **Line number** and code snippet\n2. **Severity** (Critical / Warning / Suggestion)\n3. **Category** (from above)\n4. **Description** of the issue\n5. **Recommended fix** with code example\n\nEnd with an overall assessment and priority-ordered action items.",
      "description": "Review a specific file for issues",
      "agent": "plan"
    }
  }
}

Example 5: Subagent Task with Model Override

.opencode/commands/deep-analysis.md:

---
description: Deep codebase analysis via subagent
agent: plan
subtask: true
model: anthropic/claude-3-5-sonnet-20241022
---

Perform a comprehensive analysis of the authentication module:

1. Read all files in @src/auth/
2. Map the authentication flow end-to-end
3. Identify security vulnerabilities
4. Check for compliance with OWASP Top 10
5. Review token handling and session management
6. Assess password hashing implementation
7. Verify CSRF protection

!`find src/auth -type f -name "*.ts" | sort`

Output:
- Architecture diagram (text-based)
- Security audit report
- List of vulnerabilities ranked by severity
- Recommended fixes for each vulnerability

JSON equivalent:

{
  "command": {
    "deep-analysis": {
      "template": "Perform a comprehensive analysis of the authentication module:\n\n1. Read all files in @src/auth/\n2. Map the authentication flow end-to-end\n3. Identify security vulnerabilities\n4. Check for compliance with OWASP Top 10\n5. Review token handling and session management\n6. Assess password hashing implementation\n7. Verify CSRF protection\n\n!`find src/auth -type f -name \"*.ts\" | sort`\n\nOutput:\n- Architecture diagram (text-based)\n- Security audit report\n- List of vulnerabilities ranked by severity\n- Recommended fixes for each vulnerability",
      "description": "Deep codebase analysis via subagent",
      "agent": "plan",
      "subtask": true,
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }
  }
}

Example 6: Combined Placeholders

.opencode/commands/scaffold.md:

---
description: Scaffold a new API endpoint
---

Scaffold a new API endpoint: $1

## Method and Path
- Method: $2
- Path: $3

## Requirements
1. Create route handler in @src/api/routes/
2. Add input validation schema
3. Create service layer function
4. Add unit tests
5. Update API documentation

## Conventions
- Use Zod for request validation
- Return consistent error format: `{ error: string, code: number }`
- Log all errors with structured logging
- All handlers must be async with proper error boundaries

Generate all necessary files.

Usage:

/scaffold users POST /api/v1/users

Resulting prompt:

Scaffold a new API endpoint: users

## Method and Path
- Method: POST
- Path: /api/v1/users

## Requirements
1. Create route handler in @src/api/routes/
2. Add input validation schema
3. Create service layer function
4. Add unit tests
5. Update API documentation
...

File Structure Reference

.opencode/
β”œβ”€β”€ commands/
β”‚   β”œβ”€β”€ test.md              β†’ /test
β”‚   β”œβ”€β”€ review.md            β†’ /review
β”‚   β”œβ”€β”€ changelog.md         β†’ /changelog
β”‚   β”œβ”€β”€ component.md         β†’ /component
β”‚   β”œβ”€β”€ scaffold.md          β†’ /scaffold
β”‚   └── db/
β”‚       β”œβ”€β”€ migrate.md       β†’ /db/migrate
β”‚       └── seed.md          β†’ /db/seed
└── ...

~/.config/opencode/
└── commands/
    β”œβ”€β”€ global-review.md     β†’ /global-review (available in all projects)
    └── global-template.md   β†’ /global-template

Best Practices

  1. Use descriptive filenames β€” The filename becomes the command name. run-tests.md is clearer than rt.md.

  2. Write clear descriptions β€” The description field helps users discover commands in the TUI. Be specific about what the command does.

  3. Leverage placeholders wisely β€” Use $ARGUMENTS for simple single-value inputs. Use $1, $2 for structured multi-argument commands.

  4. Use !command`` for dynamic context β€” Injecting shell output (git logs, test results, file listings) makes commands much more powerful.

  5. Use @file for focused reviews β€” Reference specific files to give the LLM precise context without polluting the prompt with unnecessary content.

  6. Set subtask: true for heavy analysis β€” Long-running tasks should use subagent invocation to avoid blocking the main conversation.

  7. Override built-ins intentionally β€” Only override built-in commands when you have a clear reason and have documented the change for your team.

  8. Use global commands sparingly β€” Global commands in ~/.config/opencode/commands/ affect all projects. Prefer project-level commands for project-specific workflows.

  9. Test your commands β€” Run each command after creation to verify placeholders resolve correctly and the prompt produces the expected output.

  10. Version control your commands β€” Commit .opencode/commands/ to your repository so team members can use the same custom commands.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.