feat(hooks): add rules-injector hook for .cursor/rules and .claude/rules support

Implements adaptive rule injection similar to Claude Code's rule system:
- Searches .cursor/rules and .claude/rules directories recursively
- Supports YAML frontmatter with globs, paths, alwaysApply, description
- Adaptive project root detection (finds markers even outside ctx.directory)
- Symlink duplicate detection via realpath comparison
- Content hash deduplication (SHA-256) to avoid re-injecting same rules
- picomatch-based glob pattern matching for file-specific rules

🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2025-12-11 11:07:31 +09:00
parent c12f73f774
commit fcdfcd3186
12 changed files with 803 additions and 2 deletions

View File

@@ -12,6 +12,7 @@ import {
createThinkModeHook,
createClaudeCodeHooksHook,
createAnthropicAutoCompactHook,
createRulesInjectorHook,
} from "./hooks";
import {
loadUserCommands,
@@ -157,6 +158,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
disabledHooks: (pluginConfig.claude_code?.hooks ?? true) ? undefined : true,
});
const anthropicAutoCompact = createAnthropicAutoCompactHook(ctx);
const rulesInjector = createRulesInjectorHook(ctx);
updateTerminalTitle({ sessionId: "main" });
@@ -220,6 +222,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
await contextWindowMonitor.event(input);
await directoryAgentsInjector.event(input);
await directoryReadmeInjector.event(input);
await rulesInjector.event(input);
await thinkMode.event(input);
await anthropicAutoCompact.event(input);
@@ -339,6 +342,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
await commentChecker["tool.execute.after"](input, output);
await directoryAgentsInjector["tool.execute.after"](input, output);
await directoryReadmeInjector["tool.execute.after"](input, output);
await rulesInjector["tool.execute.after"](input, output);
await emptyTaskResponseDetector["tool.execute.after"](input, output);
if (input.sessionID === getMainSessionID()) {