[PR #1304] Feat: custom commands #9886

Open
opened 2026-02-16 18:14:20 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/anomalyco/opencode/pull/1304
Author: @ezynda3
Created: 7/25/2025
Status: 🔄 Open

Base: devHead: feature/custom-commands


📝 Commits (10+)

📊 Changes

15 files changed (+1056 additions, -22 deletions)

View changed files

📝 bun.lock (+15 -2)
📝 packages/opencode/package.json (+1 -0)
packages/opencode/src/command/index.ts (+37 -0)
packages/opencode/src/command/loader.ts (+138 -0)
packages/opencode/src/command/resolver.ts (+131 -0)
packages/opencode/src/command/types.ts (+36 -0)
📝 packages/opencode/src/server/server.ts (+130 -0)
packages/opencode/test/command/loader.test.ts (+231 -0)
packages/opencode/test/command/resolver.test.ts (+85 -0)
📝 packages/tui/cmd/opencode/main.go (+16 -2)
📝 packages/tui/internal/app/app.go (+3 -0)
packages/tui/internal/commands/custom.go (+99 -0)
📝 packages/tui/internal/completions/commands.go (+26 -12)
📝 packages/tui/internal/components/chat/editor.go (+105 -5)
📝 packages/tui/internal/tui/tui.go (+3 -1)

📄 Description

feat: Add custom slash commands support

Summary

• Adds support for user-defined custom slash commands stored as markdown files
• Commands support dynamic argument interpolation with validation
• Implements automatic command discovery with scope-based priority

Overview

This PR implements a custom slash commands feature that allows users to define their own commands as markdown files in .opencode/commands/ directories. Commands are treated as prompts that can include argument placeholders which are validated and interpolated before submission.

Key Features

  1. Command Discovery & Loading
    • Automatically discovers commands from:
    • Project-specific: <project>/.opencode/commands/
    • User-global: ~/.opencode/commands/
    • Supports namespaced commands via directory structure (e.g., git/commit.md/git:commit)
    • Commands are prefixed with scope (user: or project:) to prevent conflicts
    • Project commands take priority over user commands with the same name
    • Hot-reloads commands when files change

  2. Argument Handling
    • Argument placeholders: $ARGUMENTS or {{args}} in command content
    • Automatic argument count validation based on placeholder occurrences
    • Commands with placeholders are inserted into input field for user to add arguments
    • Commands without placeholders are submitted immediately
    • Clear error messages when wrong number of arguments provided

  3. Content Resolution
    • File references: @{path/to/file.ts} injects file contents (relative to command file)
    • Arguments are interpolated individually into their respective placeholders
    • File content is truncated to 1MB to prevent memory issues

  4. Integration
    • Server endpoints: /command, /command/:name, /command/resolve
    • TUI autocomplete support with descriptions and argument hints
    • Commands appear in slash command menu with proper categorization
    • Seamless execution as regular prompts to the AI

Implementation Details

Server-side (TypeScript):
packages/opencode/src/command/ - Core command module
types.ts - Type definitions and schemas
loader.ts - Command discovery and file watching
resolver.ts - Argument validation and content resolution
index.ts - Public API with App.state integration

TUI-side (Go):
internal/components/chat/editor.go - Command selection and submission logic
• Added validation to prevent submission with unresolved placeholders
• Custom commands populate input field when arguments are needed

Example Commands

Simple command without arguments:

---
description: Explain the current code
---

Please explain what this code does and how it works.

Command with arguments:

---
description: Create a function with specified parameters
argument-hint: "<name> <params> <return-type>"
---

Create a function named $ARGUMENTS that takes parameters $ARGUMENTS and returns $ARGUMENTS.
Include proper error handling and documentation.

Testing

• Unit tests for argument validation and interpolation
• Tests for command loading with scope priority
• Tests for file reference resolution
• All resolver tests passing (8/8)

Breaking Changes

None - this is a new feature that doesn't affect existing functionality.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/anomalyco/opencode/pull/1304 **Author:** [@ezynda3](https://github.com/ezynda3) **Created:** 7/25/2025 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `feature/custom-commands` --- ### 📝 Commits (10+) - [`03ec4e1`](https://github.com/anomalyco/opencode/commit/03ec4e105dde179828dcc794bf8f42cc26b7e65c) Implement custom commands - [`2da704e`](https://github.com/anomalyco/opencode/commit/2da704e4e051b4d50165f8086ebd21cbaa4fb60d) fix typecheck errors - [`d5410eb`](https://github.com/anomalyco/opencode/commit/d5410ebc58de4753b6a5d39a44fdd9fb55d54299) namespacing - [`f2eeb7f`](https://github.com/anomalyco/opencode/commit/f2eeb7f3ab1647ee2a1234da954449440d024ebc) simplify - [`949d1f9`](https://github.com/anomalyco/opencode/commit/949d1f9ce3ce5aa9760d3d209372aea1ba217e99) allow adding args - [`fecf946`](https://github.com/anomalyco/opencode/commit/fecf946f39c6360cf23199e6a8f15918e1178813) fix args parsing - [`70e8520`](https://github.com/anomalyco/opencode/commit/70e8520ecc869ae4d402196126617c17d086764c) cleanup - [`0b1e78c`](https://github.com/anomalyco/opencode/commit/0b1e78cf8a4388d0845e1e12c7823abb6cb503f0) cleanup - [`4461b44`](https://github.com/anomalyco/opencode/commit/4461b44d70e750aa090e4e73909239d0c20ff893) Remove allowed-tools feature from custom commands - [`3ab5eb6`](https://github.com/anomalyco/opencode/commit/3ab5eb6ddbacd66a2daf6f999e9c9bab84a7c115) cleanup ### 📊 Changes **15 files changed** (+1056 additions, -22 deletions) <details> <summary>View changed files</summary> 📝 `bun.lock` (+15 -2) 📝 `packages/opencode/package.json` (+1 -0) ➕ `packages/opencode/src/command/index.ts` (+37 -0) ➕ `packages/opencode/src/command/loader.ts` (+138 -0) ➕ `packages/opencode/src/command/resolver.ts` (+131 -0) ➕ `packages/opencode/src/command/types.ts` (+36 -0) 📝 `packages/opencode/src/server/server.ts` (+130 -0) ➕ `packages/opencode/test/command/loader.test.ts` (+231 -0) ➕ `packages/opencode/test/command/resolver.test.ts` (+85 -0) 📝 `packages/tui/cmd/opencode/main.go` (+16 -2) 📝 `packages/tui/internal/app/app.go` (+3 -0) ➕ `packages/tui/internal/commands/custom.go` (+99 -0) 📝 `packages/tui/internal/completions/commands.go` (+26 -12) 📝 `packages/tui/internal/components/chat/editor.go` (+105 -5) 📝 `packages/tui/internal/tui/tui.go` (+3 -1) </details> ### 📄 Description ## feat: Add custom slash commands support ### Summary • Adds support for user-defined custom slash commands stored as markdown files • Commands support dynamic argument interpolation with validation • Implements automatic command discovery with scope-based priority ### Overview This PR implements a custom slash commands feature that allows users to define their own commands as markdown files in `.opencode/commands/` directories. Commands are treated as prompts that can include argument placeholders which are validated and interpolated before submission. ### Key Features 1. **Command Discovery & Loading** • Automatically discovers commands from: • Project-specific: `<project>/.opencode/commands/` • User-global: `~/.opencode/commands/` • Supports namespaced commands via directory structure (e.g., `git/commit.md` → `/git:commit`) • Commands are prefixed with scope (`user:` or `project:`) to prevent conflicts • Project commands take priority over user commands with the same name • Hot-reloads commands when files change 2. **Argument Handling** • Argument placeholders: `$ARGUMENTS` or `{{args}}` in command content • Automatic argument count validation based on placeholder occurrences • Commands with placeholders are inserted into input field for user to add arguments • Commands without placeholders are submitted immediately • Clear error messages when wrong number of arguments provided 3. **Content Resolution** • File references: `@{path/to/file.ts}` injects file contents (relative to command file) • Arguments are interpolated individually into their respective placeholders • File content is truncated to 1MB to prevent memory issues 4. **Integration** • Server endpoints: `/command`, `/command/:name`, `/command/resolve` • TUI autocomplete support with descriptions and argument hints • Commands appear in slash command menu with proper categorization • Seamless execution as regular prompts to the AI ### Implementation Details **Server-side (TypeScript):** • `packages/opencode/src/command/` - Core command module • `types.ts` - Type definitions and schemas • `loader.ts` - Command discovery and file watching • `resolver.ts` - Argument validation and content resolution • `index.ts` - Public API with App.state integration **TUI-side (Go):** • `internal/components/chat/editor.go` - Command selection and submission logic • Added validation to prevent submission with unresolved placeholders • Custom commands populate input field when arguments are needed ### Example Commands **Simple command without arguments:** ```markdown --- description: Explain the current code --- Please explain what this code does and how it works. ``` **Command with arguments:** ```markdown --- description: Create a function with specified parameters argument-hint: "<name> <params> <return-type>" --- Create a function named $ARGUMENTS that takes parameters $ARGUMENTS and returns $ARGUMENTS. Include proper error handling and documentation. ``` ### Testing • Unit tests for argument validation and interpolation • Tests for command loading with scope priority • Tests for file reference resolution • All resolver tests passing (8/8) ### Breaking Changes None - this is a new feature that doesn't affect existing functionality. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-16 18:14:20 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#9886