Add auto-slash-command hook for intercepting and replacing slash commands

This hook intercepts user messages starting with '/' and REPLACES them with the actual command template output instead of injecting instructions. The implementation includes:

- Slash command detection (detector.ts) - identifies messages starting with '/'
- Command discovery and execution (executor.ts) - loads templates from ~/.claude/commands/ or similar
- Hook integration (index.ts) - registers with chat.message event to replace output.parts
- Comprehensive test coverage - 37 tests covering detection, replacement, error handling, and command exclusions
- Configuration support in HookNameSchema

Key features:
- Supports excluded commands to skip processing
- Loads command templates from user's command directory
- Replaces user input before reaching the LLM
- Tests all edge cases including missing files, malformed templates, and special commands

🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2026-01-01 20:59:36 +09:00
parent b30c17ac77
commit 490c0b626f
10 changed files with 953 additions and 0 deletions

View File

@@ -25,6 +25,7 @@ import {
createEmptyMessageSanitizerHook,
createThinkingBlockValidatorHook,
createRalphLoopHook,
createAutoSlashCommandHook,
} from "./hooks";
import { createGoogleAntigravityAuthPlugin } from "./auth/antigravity";
import {
@@ -259,6 +260,10 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
? createRalphLoopHook(ctx, { config: pluginConfig.ralph_loop })
: null;
const autoSlashCommand = isHookEnabled("auto-slash-command")
? createAutoSlashCommandHook()
: null;
const backgroundManager = new BackgroundManager(ctx);
const todoContinuationEnforcer = isHookEnabled("todo-continuation-enforcer")
@@ -310,6 +315,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
"chat.message": async (input, output) => {
await claudeCodeHooks["chat.message"]?.(input, output);
await keywordDetector?.["chat.message"]?.(input, output);
await autoSlashCommand?.["chat.message"]?.(input, output);
if (ralphLoop) {
const parts = (output as { parts?: Array<{ type: string; text?: string }> }).parts;