docs(agents): regenerate all AGENTS.md files with comprehensive codebase analysis

- Regenerated root AGENTS.md with overview, structure, and complexity hotspots
- Regenerated all 7 subdirectory AGENTS.md files: hooks, tools, features, agents, cli, auth, shared
- Used 11 background explore agents for comprehensive feature and architecture analysis
- All files within size limits (root: 112 lines, subdirs: 57-68 lines)
- Includes where-to-look guide, conventions, anti-patterns, and agent model information

🤖 Generated with assistance of oh-my-opencode
This commit is contained in:
YeonGyu-Kim
2026-01-02 10:42:38 +09:00
parent bebe6607d4
commit a1fe0f8517
8 changed files with 283 additions and 569 deletions

View File

@@ -2,19 +2,20 @@
## OVERVIEW
AI agent definitions for multi-model orchestration. 7 specialized agents: Sisyphus (orchestrator), oracle (strategy), librarian (research), explore (grep), frontend-ui-ux-engineer, document-writer, multimodal-looker.
7 AI agents for multi-model orchestration. Sisyphus orchestrates, specialists handle domains.
## STRUCTURE
```
agents/
├── sisyphus.ts # Primary orchestrator (Claude Opus 4.5)
├── oracle.ts # Strategic advisor (GPT-5.2)
├── librarian.ts # Multi-repo research (Claude Sonnet 4.5)
├── explore.ts # Fast codebase grep (Grok Code)
├── frontend-ui-ux-engineer.ts # UI generation (Gemini 3 Pro)
├── document-writer.ts # Technical docs (Gemini 3 Flash)
├── multimodal-looker.ts # PDF/image analysis (Gemini 3 Flash)
├── sisyphus.ts # Primary orchestrator (504 lines)
├── oracle.ts # Strategic advisor
├── librarian.ts # Multi-repo research
├── explore.ts # Fast codebase grep
├── frontend-ui-ux-engineer.ts # UI generation
├── document-writer.ts # Technical docs
├── multimodal-looker.ts # PDF/image analysis
├── sisyphus-prompt-builder.ts # Sisyphus prompt construction
├── build-prompt.ts # Shared build agent prompt
├── plan-prompt.ts # Shared plan agent prompt
├── types.ts # AgentModelConfig interface
@@ -24,66 +25,40 @@ agents/
## AGENT MODELS
| Agent | Default Model | Fallback | Purpose |
|-------|---------------|----------|---------|
| Sisyphus | anthropic/claude-opus-4-5 | - | Primary orchestrator with extended thinking |
| oracle | openai/gpt-5.2 | - | Architecture, debugging, code review |
| librarian | anthropic/claude-sonnet-4-5 | google/gemini-3-flash | Docs, OSS research, GitHub examples |
| explore | opencode/grok-code | google/gemini-3-flash, anthropic/claude-haiku-4-5 | Fast contextual grep |
| frontend-ui-ux-engineer | google/gemini-3-pro-preview | - | UI/UX code generation |
| Agent | Model | Fallback | Purpose |
|-------|-------|----------|---------|
| Sisyphus | anthropic/claude-opus-4-5 | - | Orchestrator with extended thinking |
| oracle | openai/gpt-5.2 | - | Architecture, debugging, review |
| librarian | anthropic/claude-sonnet-4-5 | google/gemini-3-flash | Docs, GitHub research |
| explore | opencode/grok-code | gemini-3-flash, haiku-4-5 | Contextual grep |
| frontend-ui-ux-engineer | google/gemini-3-pro-preview | - | Beautiful UI code |
| document-writer | google/gemini-3-pro-preview | - | Technical writing |
| multimodal-looker | google/gemini-3-flash | - | PDF/image analysis |
| multimodal-looker | google/gemini-3-flash | - | Visual analysis |
## HOW TO ADD AN AGENT
## HOW TO ADD
1. Create `src/agents/my-agent.ts`:
```typescript
import type { AgentConfig } from "@opencode-ai/sdk"
export const myAgent: AgentConfig = {
model: "provider/model-name",
temperature: 0.1,
system: "Agent system prompt...",
tools: { include: ["tool1", "tool2"] }, // or exclude: [...]
system: "...",
tools: { include: ["tool1"] },
}
```
2. Add to `builtinAgents` in `src/agents/index.ts`
3. Update `types.ts` if adding new config options
2. Add to `builtinAgents` in index.ts
3. Update types.ts if new config options
## AGENT CONFIG OPTIONS
## MODEL FALLBACK
| Option | Type | Description |
|--------|------|-------------|
| model | string | Model identifier (provider/model-name) |
| temperature | number | 0.0-1.0, most use 0.1 for consistency |
| system | string | System prompt (can be multiline template literal) |
| tools | object | `{ include: [...] }` or `{ exclude: [...] }` |
| top_p | number | Optional nucleus sampling |
| maxTokens | number | Optional max output tokens |
`createBuiltinAgents()` handles fallback:
1. User config override
2. Installer settings (claude max20, gemini antigravity)
3. Default model
## MODEL FALLBACK LOGIC
## ANTI-PATTERNS
`createBuiltinAgents()` in utils.ts handles model fallback:
1. Check user config override (`agents.{name}.model`)
2. Check installer settings (claude max20, gemini antigravity)
3. Use default model
**Fallback order for explore**:
- If gemini antigravity enabled → `google/gemini-3-flash`
- If claude max20 enabled → `anthropic/claude-haiku-4-5`
- Default → `opencode/grok-code` (free)
## ANTI-PATTERNS (AGENTS)
- **High temperature**: Don't use >0.3 for code-related agents
- **Broad tool access**: Prefer explicit `include` over unrestricted access
- **Monolithic prompts**: Keep prompts focused; delegate to specialized agents
- **Missing fallbacks**: Consider free/cheap fallbacks for rate-limited models
## SHARED PROMPTS
- **build-prompt.ts**: Base prompt for build agents (OpenCode default + Sisyphus variants)
- **plan-prompt.ts**: Base prompt for plan agents (Planner-Sisyphus)
Used by `src/index.ts` when creating Builder-Sisyphus and Planner-Sisyphus variants.
- High temperature (>0.3) for code agents
- Broad tool access (prefer explicit `include`)
- Monolithic prompts (delegate to specialists)
- Missing fallbacks for rate-limited models

View File

@@ -2,56 +2,56 @@
## OVERVIEW
Google Antigravity OAuth implementation for Gemini models. Token management, fetch interception, thinking block extraction, and response transformation.
Google Antigravity OAuth for Gemini models. Token management, fetch interception, thinking block extraction.
## STRUCTURE
```
auth/
└── antigravity/
├── plugin.ts # Main plugin export, hooks registration
├── plugin.ts # Main export, hooks registration
├── oauth.ts # OAuth flow, token acquisition
├── token.ts # Token storage, refresh logic
├── fetch.ts # Fetch interceptor (622 lines) - URL rewriting, retry
├── response.ts # Response transformation, streaming
├── thinking.ts # Thinking block extraction/transformation
├── thought-signature-store.ts # Signature caching for thinking blocks
├── message-converter.ts # Message format conversion
├── request.ts # Request building, headers
├── fetch.ts # Fetch interceptor (621 lines)
├── response.ts # Response transformation (598 lines)
├── thinking.ts # Thinking block extraction (571 lines)
├── thought-signature-store.ts # Signature caching
├── message-converter.ts # Format conversion
├── request.ts # Request building
├── project.ts # Project ID management
├── tools.ts # Tool registration for OAuth
├── tools.ts # OAuth tool registration
├── constants.ts # API endpoints, model mappings
└── types.ts # TypeScript interfaces
└── types.ts
```
## KEY COMPONENTS
| File | Purpose |
|------|---------|
| `fetch.ts` | Core interceptor - rewrites URLs, manages tokens, handles retries |
| `thinking.ts` | Extracts `<antThinking>` blocks, transforms for OpenCode compatibility |
| `response.ts` | Handles streaming responses, SSE parsing |
| `oauth.ts` | Browser-based OAuth flow for Google accounts |
| `token.ts` | Token persistence, expiry checking, refresh |
| fetch.ts | URL rewriting, token injection, retries |
| thinking.ts | Extract `<antThinking>` blocks |
| response.ts | Streaming SSE parsing |
| oauth.ts | Browser-based OAuth flow |
| token.ts | Token persistence, expiry |
## HOW IT WORKS
1. **Intercept**: `fetch.ts` intercepts requests to Anthropic/Google endpoints
2. **Rewrite**: URLs rewritten to Antigravity proxy endpoints
3. **Auth**: Bearer token injected from stored OAuth credentials
4. **Response**: Streaming responses parsed, thinking blocks extracted
5. **Transform**: Response format normalized for OpenCode consumption
1. **Intercept**: fetch.ts intercepts Anthropic/Google requests
2. **Rewrite**: URLs Antigravity proxy endpoints
3. **Auth**: Bearer token from stored OAuth credentials
4. **Response**: Streaming parsed, thinking blocks extracted
5. **Transform**: Normalized for OpenCode
## ANTI-PATTERNS (AUTH)
## FEATURES
- **Direct API calls**: Always go through fetch interceptor
- **Storing tokens in code**: Use `token.ts` storage layer
- **Ignoring refresh**: Check token expiry before requests
- **Blocking on OAuth**: OAuth flow is async, never block main thread
- Multi-account (up to 10 Google accounts)
- Auto-fallback on rate limit
- Thinking blocks preserved
- Antigravity proxy for AI Studio access
## NOTES
## ANTI-PATTERNS
- **Multi-account**: Supports up to 10 Google accounts for load balancing
- **Fallback**: On rate limit, automatically switches to next available account
- **Thinking blocks**: Preserved and transformed for extended thinking features
- **Proxy**: Uses Antigravity proxy for Google AI Studio access
- Direct API calls (use fetch interceptor)
- Tokens in code (use token.ts storage)
- Ignoring refresh (check expiry first)
- Blocking on OAuth (always async)

View File

@@ -2,92 +2,67 @@
## OVERVIEW
Command-line interface for oh-my-opencode. Interactive installer, health diagnostics (doctor), and runtime commands. Entry point: `bunx oh-my-opencode`.
CLI for oh-my-opencode: interactive installer, health diagnostics (doctor), runtime launcher. Entry: `bunx oh-my-opencode`.
## STRUCTURE
```
cli/
├── index.ts # Commander.js entry point, subcommand routing
├── install.ts # Interactive TUI installer
├── config-manager.ts # Config detection, parsing, merging (669 lines)
├── index.ts # Commander.js entry, subcommand routing
├── install.ts # Interactive TUI installer (477 lines)
├── config-manager.ts # JSONC parsing, env detection (669 lines)
├── types.ts # CLI-specific types
├── doctor/ # Health check system
│ ├── index.ts # Doctor command entry
│ ├── constants.ts # Check categories, descriptions
│ ├── constants.ts # Check categories
│ ├── types.ts # Check result interfaces
│ └── checks/ # 17 individual health checks
├── get-local-version/ # Version detection utility
│ ├── index.ts
│ └── formatter.ts
│ └── checks/ # 17+ individual checks
├── get-local-version/ # Version detection
└── run/ # OpenCode session launcher
├── index.ts
└── completion.test.ts
```
## CLI COMMANDS
| Command | Purpose | Key File |
|---------|---------|----------|
| `install` | Interactive setup wizard | `install.ts` |
| `doctor` | Environment health checks | `doctor/index.ts` |
| `run` | Launch OpenCode session | `run/index.ts` |
| Command | Purpose |
|---------|---------|
| `install` | Interactive setup wizard |
| `doctor` | Environment health checks |
| `run` | Launch OpenCode session |
## DOCTOR CHECKS
17 checks in `doctor/checks/`:
17+ checks in `doctor/checks/`:
- version.ts (OpenCode >= 1.0.150)
- config.ts (plugin registered)
- bun.ts, node.ts, git.ts
- anthropic-auth.ts, openai-auth.ts, google-auth.ts
- lsp-*.ts, mcp-*.ts
| Check | Validates |
|-------|-----------|
| `version.ts` | OpenCode version >= 1.0.150 |
| `config.ts` | Plugin registered in opencode.json |
| `bun.ts` | Bun runtime available |
| `node.ts` | Node.js version compatibility |
| `git.ts` | Git installed |
| `anthropic-auth.ts` | Claude authentication |
| `openai-auth.ts` | OpenAI authentication |
| `google-auth.ts` | Google/Gemini authentication |
| `lsp-*.ts` | Language server availability |
| `mcp-*.ts` | MCP server connectivity |
## CONFIG-MANAGER (669 lines)
## INSTALLATION FLOW
- JSONC support (comments, trailing commas)
- Multi-source: User (~/.config/opencode/) + Project (.opencode/)
- Zod validation
- Legacy format migration
- Error aggregation for doctor
1. **Detection**: Find existing `opencode.json` / `opencode.jsonc`
2. **TUI Prompts**: Claude subscription? ChatGPT? Gemini?
3. **Config Generation**: Build `oh-my-opencode.json` based on answers
4. **Plugin Registration**: Add to `plugin` array in opencode.json
5. **Auth Guidance**: Instructions for `opencode auth login`
## CONFIG-MANAGER
The largest file (669 lines) handles:
- **JSONC support**: Parses comments and trailing commas
- **Multi-source detection**: User (~/.config/opencode/) + Project (.opencode/)
- **Schema validation**: Zod-based config validation
- **Migration**: Handles legacy config formats
- **Error collection**: Aggregates parsing errors for doctor
## HOW TO ADD A DOCTOR CHECK
## HOW TO ADD CHECK
1. Create `src/cli/doctor/checks/my-check.ts`:
```typescript
import type { DoctorCheck } from "../types"
export const myCheck: DoctorCheck = {
name: "my-check",
category: "environment",
check: async () => {
// Return { status: "pass" | "warn" | "fail", message: string }
return { status: "pass" | "warn" | "fail", message: "..." }
}
}
```
2. Add to `src/cli/doctor/checks/index.ts`
3. Update `constants.ts` if new category
## ANTI-PATTERNS (CLI)
## ANTI-PATTERNS
- **Blocking prompts in non-TTY**: Check `process.stdout.isTTY` before TUI
- **Hardcoded paths**: Use shared utilities for config paths
- **Ignoring JSONC**: User configs may have comments
- **Silent failures**: Doctor checks must return clear status/message
- Blocking prompts in non-TTY (check `process.stdout.isTTY`)
- Hardcoded paths (use shared utilities)
- JSON.parse for user files (use parseJsonc)
- Silent failures in doctor checks

View File

@@ -2,207 +2,65 @@
## OVERVIEW
Claude Code compatibility layer and core feature modules. Enables Claude Code configs/commands/skills/MCPs/hooks to work seamlessly in OpenCode.
Claude Code compatibility layer + core feature modules. Commands, skills, agents, MCPs, hooks from Claude Code work seamlessly.
## STRUCTURE
```
features/
├── background-agent/ # Background task management
│ ├── manager.ts # Task lifecycle, notifications
│ ├── manager.test.ts
│ └── types.ts
├── builtin-commands/ # Built-in slash command definitions
├── builtin-skills/ # Built-in skills (playwright, etc.)
│ └── */SKILL.md # Each skill in own directory
├── claude-code-agent-loader/ # Load agents from ~/.claude/agents/*.md
├── claude-code-command-loader/ # Load commands from ~/.claude/commands/*.md
├── claude-code-mcp-loader/ # Load MCPs from .mcp.json
├── background-agent/ # Task lifecycle, notifications (460 lines)
├── builtin-commands/ # Built-in slash commands
├── builtin-skills/ # Built-in skills (playwright)
├── claude-code-agent-loader/ # ~/.claude/agents/*.md
├── claude-code-command-loader/ # ~/.claude/commands/*.md
├── claude-code-mcp-loader/ # .mcp.json files
│ └── env-expander.ts # ${VAR} expansion
├── claude-code-plugin-loader/ # Load external plugins from installed_plugins.json
├── claude-code-plugin-loader/ # installed_plugins.json (484 lines)
├── claude-code-session-state/ # Session state persistence
├── opencode-skill-loader/ # Load skills from OpenCode and Claude paths
├── skill-mcp-manager/ # MCP servers embedded in skills
│ ├── manager.ts # Lazy-loading MCP client lifecycle
│ └── types.ts
├── opencode-skill-loader/ # Skills from OpenCode + Claude paths
├── skill-mcp-manager/ # MCP servers in skill YAML
└── hook-message-injector/ # Inject messages into conversation
```
## LOADER PRIORITY
Each loader reads from multiple directories (highest priority first):
| Loader | Priority Order |
|--------|---------------|
| Loader | Priority (highest first) |
|--------|--------------------------|
| Commands | `.opencode/command/` > `~/.config/opencode/command/` > `.claude/commands/` > `~/.claude/commands/` |
| Skills | `.opencode/skill/` > `~/.config/opencode/skill/` > `.claude/skills/` > `~/.claude/skills/` |
| Agents | `.claude/agents/` > `~/.claude/agents/` |
| MCPs | `.claude/.mcp.json` > `.mcp.json` > `~/.claude/.mcp.json` |
## HOW TO ADD A LOADER
1. Create directory: `src/features/claude-code-my-loader/`
2. Create files:
- `loader.ts`: Main loader logic with `load()` function
- `types.ts`: TypeScript interfaces
- `index.ts`: Barrel export
3. Pattern: Read from multiple dirs, merge with priority, return normalized config
## BACKGROUND AGENT SPECIFICS
- **Task lifecycle**: pending → running → completed/failed
- **Notifications**: OS notification on task complete (configurable)
- **Result retrieval**: `background_output` tool with task_id
- **Cancellation**: `background_cancel` with task_id or all=true
## CONFIG TOGGLES
Disable features in `oh-my-opencode.json`:
```json
{
"claude_code": {
"mcp": false, // Skip .mcp.json loading
"commands": false, // Skip commands/*.md loading
"skills": false, // Skip skills/*/SKILL.md loading
"agents": false, // Skip agents/*.md loading
"mcp": false, // Skip .mcp.json
"commands": false, // Skip commands/*.md
"skills": false, // Skip skills/*/SKILL.md
"agents": false, // Skip agents/*.md
"hooks": false // Skip settings.json hooks
}
}
```
## HOOK MESSAGE INJECTOR
## BACKGROUND AGENT
- **Purpose**: Inject system messages into conversation at specific points
- **Timing**: PreToolUse, PostToolUse, UserPromptSubmit, Stop
- **Format**: Returns `{ messages: [{ role: "user", content: "..." }] }`
- Lifecycle: pending → running → completed/failed
- OS notification on complete
- `background_output` to retrieve results
- `background_cancel` with task_id or all=true
## MCP LOADER (claude-code-mcp-loader)
## SKILL MCP
Loads MCP server configs from `.mcp.json` files. Full Claude Code compatibility.
- MCP servers embedded in skill YAML frontmatter
- Lazy client loading, session-scoped cleanup
- `skill_mcp` tool exposes capabilities
### File Locations (Priority Order)
## ANTI-PATTERNS
| Path | Scope | Description |
|------|-------|-------------|
| `~/.claude/.mcp.json` | user | User-global MCP servers |
| `./.mcp.json` | project | Project-specific MCP servers |
| `./.claude/.mcp.json` | local | Local overrides (git-ignored) |
### .mcp.json Format
```json
{
"mcpServers": {
"server-name": {
"type": "stdio|http|sse",
"command": "npx",
"args": ["-y", "@anthropics/mcp-server-example"],
"env": {
"API_KEY": "${MY_API_KEY}"
},
"disabled": false
}
}
}
```
### Server Types
| Type | Required Fields | Description |
|------|-----------------|-------------|
| `stdio` (default) | `command`, `args?`, `env?` | Local subprocess MCP |
| `http` | `url`, `headers?` | HTTP-based remote MCP |
| `sse` | `url`, `headers?` | SSE-based remote MCP |
### Environment Variable Expansion
Supports `${VAR}` syntax in all string fields:
```json
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["${HOME}/mcp-server/index.js"],
"env": {
"API_KEY": "${MY_API_KEY}",
"DEBUG": "${DEBUG:-false}"
}
}
}
}
```
### Examples
**stdio (Local subprocess)**:
```json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@anthropics/mcp-server-filesystem", "/path/to/dir"]
}
}
}
```
**http (Remote)**:
```json
{
"mcpServers": {
"remote-api": {
"type": "http",
"url": "https://mcp.example.com/api",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
}
```
**Disable a server**:
```json
{
"mcpServers": {
"expensive-server": {
"command": "...",
"disabled": true
}
}
}
```
### Transformation
Claude Code format → OpenCode format:
| Claude Code | OpenCode |
|-------------|----------|
| `type: "stdio"` | `type: "local"` |
| `type: "http\|sse"` | `type: "remote"` |
| `command` + `args` | `command: [cmd, ...args]` |
| `env` | `environment` |
| `headers` | `headers` |
## SKILL MCP MANAGER
- **Purpose**: Manage MCP servers embedded in skill YAML frontmatter
- **Lifecycle**: Lazy client loading, session-scoped cleanup
- **Config**: `mcp` field in skill's YAML frontmatter defines server config
- **Tool**: `skill_mcp` exposes MCP capabilities (tools, resources, prompts)
## BUILTIN SKILLS
- **Location**: `src/features/builtin-skills/*/SKILL.md`
- **Available**: `playwright` (browser automation)
- **Disable**: `disabled_skills: ["playwright"]` in config
## ANTI-PATTERNS (FEATURES)
- **Blocking on load**: Loaders run at startup, keep them fast
- **No error handling**: Always try/catch, log failures, return empty on error
- **Ignoring priority**: Higher priority dirs must override lower
- **Modifying user files**: Loaders read-only, never write to ~/.claude/
- Blocking on load (loaders run at startup)
- No error handling (always try/catch)
- Ignoring priority order
- Writing to ~/.claude/ (read-only)

View File

@@ -2,85 +2,65 @@
## OVERVIEW
Lifecycle hooks that intercept/modify agent behavior. Inject context, enforce rules, recover from errors, notify on events.
22 lifecycle hooks intercepting/modifying agent behavior. Context injection, error recovery, output control, notifications.
## STRUCTURE
```
hooks/
├── agent-usage-reminder/ # Remind to use specialized agents
├── anthropic-context-window-limit-recovery/ # Auto-compact Claude at token limit
├── auto-slash-command/ # Auto-detect and execute /command patterns
├── auto-update-checker/ # Version update notifications
├── background-notification/ # OS notify on background task complete
├── claude-code-hooks/ # Claude Code settings.json integration
├── anthropic-context-window-limit-recovery/ # Auto-compact at token limit (554 lines)
├── auto-slash-command/ # Detect and execute /command patterns
├── auto-update-checker/ # Version notifications, startup toast
├── background-notification/ # OS notify on task complete
├── claude-code-hooks/ # settings.json PreToolUse/PostToolUse/etc
├── comment-checker/ # Prevent excessive AI comments
── filters/ # Filtering rules (docstring, directive, bdd, etc.)
│ └── output/ # Output formatting
├── compaction-context-injector/ # Inject context during compaction
├── directory-agents-injector/ # Auto-inject AGENTS.md files
├── directory-readme-injector/ # Auto-inject README.md files
── filters/ # docstring, directive, bdd, etc
├── compaction-context-injector/ # Preserve context during compaction
├── directory-agents-injector/ # Auto-inject AGENTS.md
├── directory-readme-injector/ # Auto-inject README.md
├── empty-message-sanitizer/ # Sanitize empty messages
├── interactive-bash-session/ # Tmux session management
├── keyword-detector/ # Detect ultrawork/search keywords
├── non-interactive-env/ # CI/headless environment handling
├── preemptive-compaction/ # Pre-emptive session compaction
├── ralph-loop/ # Self-referential dev loop until completion
├── keyword-detector/ # ultrawork/search keyword activation
├── non-interactive-env/ # CI/headless handling
├── preemptive-compaction/ # Pre-emptive at 85% usage
├── ralph-loop/ # Self-referential dev loop
├── rules-injector/ # Conditional rules from .claude/rules/
├── session-recovery/ # Recover from session errors
├── session-recovery/ # Recover from errors (430 lines)
├── think-mode/ # Auto-detect thinking triggers
├── thinking-block-validator/ # Validate thinking blocks in messages
├── context-window-monitor.ts # Monitor context usage (standalone)
├── empty-task-response-detector.ts
├── session-notification.ts # OS notify on idle (standalone)
── todo-continuation-enforcer.ts # Force TODO completion (standalone)
└── tool-output-truncator.ts # Truncate verbose outputs (standalone)
├── agent-usage-reminder/ # Remind to use specialists
├── context-window-monitor.ts # Monitor usage (standalone)
├── session-notification.ts # OS notify on idle
├── todo-continuation-enforcer.ts # Force TODO completion
── tool-output-truncator.ts # Truncate verbose outputs
```
## HOOK CATEGORIES
| Category | Hooks | Purpose |
|----------|-------|---------|
| Context Injection | directory-agents-injector, directory-readme-injector, rules-injector, compaction-context-injector | Auto-inject relevant context |
| Session Management | session-recovery, anthropic-context-window-limit-recovery, preemptive-compaction, empty-message-sanitizer | Handle session lifecycle |
| Output Control | comment-checker, tool-output-truncator | Control agent output quality |
| Notifications | session-notification, background-notification, auto-update-checker | OS/user notifications |
| Behavior Enforcement | todo-continuation-enforcer, keyword-detector, think-mode, agent-usage-reminder | Enforce agent behavior |
| Environment | non-interactive-env, interactive-bash-session, context-window-monitor | Adapt to runtime environment |
| Compatibility | claude-code-hooks | Claude Code settings.json support |
## HOW TO ADD A HOOK
1. Create directory: `src/hooks/my-hook/`
2. Create files:
- `index.ts`: Export `createMyHook(input: PluginInput)`
- `constants.ts`: Hook name constant
- `types.ts`: TypeScript interfaces (optional)
- `storage.ts`: Persistent state (optional)
3. Return event handlers: `{ PreToolUse?, PostToolUse?, UserPromptSubmit?, Stop?, onSummarize? }`
4. Export from `src/hooks/index.ts`
5. Register in main plugin
## HOOK EVENTS
| Event | Timing | Can Block | Use Case |
|-------|--------|-----------|----------|
| PreToolUse | Before tool exec | Yes | Validate, modify input |
| PostToolUse | After tool exec | No | Add context, warnings |
| UserPromptSubmit | On user prompt | Yes | Inject messages, block |
| PreToolUse | Before tool | Yes | Validate, modify input |
| PostToolUse | After tool | No | Add context, warnings |
| UserPromptSubmit | On prompt | Yes | Inject messages, block |
| Stop | Session idle | No | Inject follow-ups |
| onSummarize | During compaction | No | Preserve critical context |
| onSummarize | Compaction | No | Preserve context |
## COMMON PATTERNS
## HOW TO ADD
- **Storage**: Use `storage.ts` with JSON file for persistent state across sessions
- **Once-per-session**: Track injected paths in Set to avoid duplicate injection
- **Message injection**: Return `{ messages: [...] }` from event handlers
- **Blocking**: Return `{ blocked: true, message: "reason" }` from PreToolUse
1. Create `src/hooks/my-hook/`
2. Files: `index.ts` (createMyHook), `constants.ts`, `types.ts` (optional)
3. Return: `{ PreToolUse?, PostToolUse?, UserPromptSubmit?, Stop?, onSummarize? }`
4. Export from `src/hooks/index.ts`
## ANTI-PATTERNS (HOOKS)
## PATTERNS
- **Heavy computation** in PreToolUse: Slows every tool call
- **Blocking without clear reason**: Always provide actionable message
- **Duplicate injection**: Track what's already injected per session
- **Ignoring errors**: Always try/catch, log failures, don't crash session
- **Storage**: JSON file for persistent state across sessions
- **Once-per-session**: Track injected paths in Set
- **Message injection**: Return `{ messages: [...] }`
- **Blocking**: Return `{ blocked: true, message: "..." }` from PreToolUse
## ANTI-PATTERNS
- Heavy computation in PreToolUse (slows every tool call)
- Blocking without actionable message
- Duplicate injection (track what's injected)
- Missing try/catch (don't crash session)

View File

@@ -2,81 +2,62 @@
## OVERVIEW
Cross-cutting utility functions used across agents, hooks, tools, and features. Path resolution, config management, text processing, and Claude Code compatibility helpers.
Cross-cutting utilities: path resolution, config management, text processing, Claude Code compatibility helpers.
## STRUCTURE
```
shared/
├── index.ts # Barrel export (import { x } from "../shared")
├── claude-config-dir.ts # Resolve ~/.claude directory
├── command-executor.ts # Shell command execution with variable expansion
├── config-errors.ts # Global config error tracking
├── config-path.ts # User/project config path resolution
├── data-path.ts # XDG data directory resolution
├── deep-merge.ts # Type-safe recursive object merging
├── dynamic-truncator.ts # Token-aware output truncation
├── file-reference-resolver.ts # @filename syntax resolution
├── file-utils.ts # Symlink resolution, markdown detection
├── index.ts # Barrel export
├── claude-config-dir.ts # ~/.claude resolution
├── command-executor.ts # Shell exec with variable expansion
├── config-errors.ts # Global error tracking
├── config-path.ts # User/project config paths
├── data-path.ts # XDG data directory
├── deep-merge.ts # Type-safe recursive merge
├── dynamic-truncator.ts # Token-aware truncation
├── file-reference-resolver.ts # @filename syntax
├── file-utils.ts # Symlink, markdown detection
├── frontmatter.ts # YAML frontmatter parsing
├── hook-disabled.ts # Check if hook is disabled in config
├── jsonc-parser.ts # JSON with Comments parsing
├── logger.ts # File-based logging to OS temp
├── migration.ts # Legacy name compatibility (omo -> Sisyphus)
├── hook-disabled.ts # Check if hook disabled
├── jsonc-parser.ts # JSON with Comments
├── logger.ts # File-based logging
├── migration.ts # Legacy name compat (omo Sisyphus)
├── model-sanitizer.ts # Normalize model names
├── pattern-matcher.ts # Tool name matching with wildcards
├── snake-case.ts # Case conversion for objects
└── tool-name.ts # Normalize tool names to PascalCase
├── pattern-matcher.ts # Tool name matching
├── snake-case.ts # Case conversion
└── tool-name.ts # PascalCase normalization
```
## UTILITY CATEGORIES
## WHEN TO USE
| Category | Utilities | Used By |
|----------|-----------|---------|
| Path Resolution | `getClaudeConfigDir`, `getUserConfigPath`, `getProjectConfigPath`, `getDataDir` | Features, Hooks |
| Config Management | `deepMerge`, `parseJsonc`, `isHookDisabled`, `configErrors` | index.ts, CLI |
| Text Processing | `resolveCommandsInText`, `resolveFileReferencesInText`, `parseFrontmatter` | Commands, Rules |
| Output Control | `dynamicTruncate` | Tools (Grep, LSP) |
| Normalization | `transformToolName`, `objectToSnakeCase`, `sanitizeModelName` | Hooks, Agents |
| Compatibility | `migration.ts` | Config loading |
## WHEN TO USE WHAT
| Task | Utility | Notes |
|------|---------|-------|
| Find Claude Code configs | `getClaudeConfigDir()` | Never hardcode `~/.claude` |
| Merge settings (default → user → project) | `deepMerge(base, override)` | Arrays replaced, objects merged |
| Parse user config files | `parseJsonc()` | Supports comments and trailing commas |
| Check if hook should run | `isHookDisabled(name, disabledHooks)` | Respects `disabled_hooks` config |
| Truncate large tool output | `dynamicTruncate(text, budget, reserved)` | Token-aware, prevents overflow |
| Resolve `@file` references | `resolveFileReferencesInText()` | maxDepth=3 prevents infinite loops |
| Execute shell commands | `resolveCommandsInText()` | Supports `!`\`command\`\` syntax |
| Handle legacy agent names | `migrateLegacyAgentNames()` | `omo``Sisyphus` |
| Task | Utility |
|------|---------|
| Find ~/.claude | `getClaudeConfigDir()` |
| Merge configs | `deepMerge(base, override)` |
| Parse user files | `parseJsonc()` |
| Check hook enabled | `isHookDisabled(name, list)` |
| Truncate output | `dynamicTruncate(text, budget)` |
| Resolve @file | `resolveFileReferencesInText()` |
| Execute shell | `resolveCommandsInText()` |
| Legacy names | `migrateLegacyAgentNames()` |
## CRITICAL PATTERNS
### Dynamic Truncation
```typescript
import { dynamicTruncate } from "../shared"
// Keep 50% headroom, max 50k tokens
// Dynamic truncation
const output = dynamicTruncate(result, remainingTokens, 0.5)
```
### Deep Merge Priority
```typescript
const final = deepMerge(defaults, userConfig)
final = deepMerge(final, projectConfig) // Project wins
```
// Deep merge priority
const final = deepMerge(deepMerge(defaults, userConfig), projectConfig)
### Safe JSONC Parsing
```typescript
// Safe JSONC
const { config, error } = parseJsoncSafe(content)
if (error) return fallback
```
## ANTI-PATTERNS (SHARED)
## ANTI-PATTERNS
- **Hardcoding paths**: Use `getClaudeConfigDir()`, `getUserConfigPath()`
- **Manual JSON.parse**: Use `parseJsonc()` for user files (comments allowed)
- **Ignoring truncation**: Large outputs MUST use `dynamicTruncate`
- **Direct string concat for configs**: Use `deepMerge` for proper priority
- Hardcoding paths (use getClaudeConfigDir, getUserConfigPath)
- JSON.parse for user files (use parseJsonc)
- Ignoring truncation (large outputs MUST use dynamicTruncate)
- Direct string concat for configs (use deepMerge)

View File

@@ -2,33 +2,26 @@
## OVERVIEW
Custom tools extending agent capabilities: LSP integration (11 tools), AST-aware code search/replace, file operations with timeouts, background task management.
Custom tools: 11 LSP tools, AST-aware search/replace, file ops with timeouts, background task management, session navigation.
## STRUCTURE
```
tools/
├── ast-grep/ # AST-aware code search/replace (25 languages)
│ ├── cli.ts # @ast-grep/cli subprocess
── napi.ts # @ast-grep/napi native binding (preferred)
│ ├── constants.ts, types.ts, tools.ts, utils.ts
│ ├── napi.ts # @ast-grep/napi binding (preferred)
── cli.ts # @ast-grep/cli fallback
├── background-task/ # Async agent task management
├── call-omo-agent/ # Spawn explore/librarian agents
├── glob/ # File pattern matching (timeout-safe)
├── grep/ # Content search (timeout-safe)
├── glob/ # File pattern matching (60s timeout)
├── grep/ # Content search (60s timeout)
├── interactive-bash/ # Tmux session management
├── look-at/ # Multimodal analysis (PDF, images)
├── lsp/ # 11 LSP tools
├── lsp/ # 11 LSP tools (611 lines client.ts)
│ ├── client.ts # LSP connection lifecycle
│ ├── config.ts # Server configurations
│ ├── tools.ts # Tool implementations
│ └── types.ts
├── session-manager/ # OpenCode session file management
│ ├── constants.ts # Storage paths, descriptions
│ ├── types.ts # Session data interfaces
│ ├── storage.ts # File I/O operations
│ ├── utils.ts # Formatting, filtering
│ └── tools.ts # Tool implementations
├── session-manager/ # OpenCode session file ops
├── skill/ # Skill loading and execution
├── skill-mcp/ # Skill-embedded MCP invocation
├── slashcommand/ # Slash command execution
@@ -37,47 +30,39 @@ tools/
## TOOL CATEGORIES
| Category | Tools | Purpose |
|----------|-------|---------|
| LSP | lsp_hover, lsp_goto_definition, lsp_find_references, lsp_document_symbols, lsp_workspace_symbols, lsp_diagnostics, lsp_servers, lsp_prepare_rename, lsp_rename, lsp_code_actions, lsp_code_action_resolve | IDE-like code intelligence |
| AST | ast_grep_search, ast_grep_replace | Pattern-based code search/replace |
| File Search | grep, glob | Content and file pattern matching |
| Session | session_list, session_read, session_search, session_info | OpenCode session file management |
| Background | background_task, background_output, background_cancel | Async agent orchestration |
| Multimodal | look_at | PDF/image analysis via Gemini |
| Terminal | interactive_bash | Tmux session control |
| Commands | slashcommand | Execute slash commands |
| Skills | skill, skill_mcp | Load skills, invoke skill-embedded MCPs |
| Agents | call_omo_agent | Spawn explore/librarian |
| Category | Tools |
|----------|-------|
| LSP | lsp_hover, lsp_goto_definition, lsp_find_references, lsp_document_symbols, lsp_workspace_symbols, lsp_diagnostics, lsp_servers, lsp_prepare_rename, lsp_rename, lsp_code_actions, lsp_code_action_resolve |
| AST | ast_grep_search, ast_grep_replace |
| File Search | grep, glob |
| Session | session_list, session_read, session_search, session_info |
| Background | background_task, background_output, background_cancel |
| Multimodal | look_at |
| Terminal | interactive_bash |
| Skills | skill, skill_mcp |
| Agents | call_omo_agent |
## HOW TO ADD A TOOL
## HOW TO ADD
1. Create directory: `src/tools/my-tool/`
2. Create files:
- `constants.ts`: `TOOL_NAME`, `TOOL_DESCRIPTION`
- `types.ts`: Parameter/result interfaces
- `tools.ts`: Tool implementation (returns OpenCode tool object)
- `index.ts`: Barrel export
- `utils.ts`: Helpers (optional)
1. Create `src/tools/my-tool/`
2. Files: `constants.ts`, `types.ts`, `tools.ts`, `index.ts`
3. Add to `builtinTools` in `src/tools/index.ts`
## LSP SPECIFICS
- **Client lifecycle**: Lazy init on first use, auto-shutdown on idle
- **Config priority**: opencode.json > oh-my-opencode.json > defaults
- **Supported servers**: typescript-language-server, pylsp, gopls, rust-analyzer, etc.
- **Custom servers**: Add via `lsp` config in oh-my-opencode.json
- Lazy init on first use, auto-shutdown on idle
- Config priority: opencode.json > oh-my-opencode.json > defaults
- Servers: typescript-language-server, pylsp, gopls, rust-analyzer
## AST-GREP SPECIFICS
- **Meta-variables**: `$VAR` (single node), `$$$` (multiple nodes)
- **Languages**: 25 supported (typescript, tsx, python, rust, go, etc.)
- **Binding**: Prefers @ast-grep/napi (native), falls back to @ast-grep/cli
- **Pattern must be valid AST**: `export async function $NAME($$$) { $$$ }` not fragments
- Meta-variables: `$VAR` (single), `$$$` (multiple)
- Pattern must be valid AST node, not fragment
- Prefers napi binding for performance
## ANTI-PATTERNS (TOOLS)
## ANTI-PATTERNS
- **No timeout**: Always use timeout for file operations (default 60s)
- **Blocking main thread**: Use async/await, never sync file ops
- **Ignoring LSP errors**: Gracefully handle server not found/crashed
- **Raw subprocess for ast-grep**: Prefer napi binding for performance
- No timeout on file ops (always use, default 60s)
- Sync file operations (use async/await)
- Ignoring LSP errors (graceful handling required)
- Raw subprocess for ast-grep (prefer napi)