oh-my-opencode 0.1.32 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +64 -8
- package/README.md +64 -20
- package/dist/features/hook-message-injector/constants.d.ts +3 -0
- package/dist/features/hook-message-injector/index.d.ts +2 -0
- package/dist/features/hook-message-injector/injector.d.ts +2 -0
- package/dist/features/hook-message-injector/types.d.ts +43 -0
- package/dist/hooks/claude-code-hooks/config-loader.d.ts +12 -0
- package/dist/hooks/claude-code-hooks/config.d.ts +3 -0
- package/dist/hooks/claude-code-hooks/index.d.ts +42 -0
- package/dist/hooks/claude-code-hooks/plugin-config.d.ts +8 -0
- package/dist/hooks/claude-code-hooks/post-tool-use.d.ts +40 -0
- package/dist/hooks/claude-code-hooks/pre-tool-use.d.ts +25 -0
- package/dist/hooks/claude-code-hooks/stop.d.ts +20 -0
- package/dist/hooks/claude-code-hooks/todo.d.ts +12 -0
- package/dist/hooks/claude-code-hooks/tool-input-cache.d.ts +5 -0
- package/dist/hooks/claude-code-hooks/transcript.d.ts +38 -0
- package/dist/hooks/claude-code-hooks/types.d.ts +166 -0
- package/dist/hooks/claude-code-hooks/user-prompt-submit.d.ts +22 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.js +1475 -307
- package/dist/shared/hook-disabled.d.ts +2 -0
- package/dist/shared/index.d.ts +4 -0
- package/dist/shared/pattern-matcher.d.ts +3 -0
- package/dist/shared/snake-case.d.ts +4 -0
- package/dist/shared/tool-name.d.ts +1 -0
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
- [내장 AST-Grep Tools](#내장-ast-grep-tools)
|
|
16
16
|
- [Grep](#grep)
|
|
17
17
|
- [내장 MCPs](#내장-mcps)
|
|
18
|
+
- [Claude Code 호환성](#claude-code-호환성)
|
|
18
19
|
- [기타 편의 기능](#기타-편의-기능)
|
|
19
20
|
- [설정](#설정)
|
|
20
21
|
- [작성자의 노트](#작성자의-노트)
|
|
@@ -224,17 +225,72 @@ OpenCode 는 아주 확장가능하고 아주 커스터마이저블합니다.
|
|
|
224
225
|
}
|
|
225
226
|
```
|
|
226
227
|
|
|
228
|
+
### Claude Code 호환성
|
|
229
|
+
|
|
230
|
+
Oh My OpenCode는 Claude Code 설정과 완벽하게 호환됩니다. Claude Code를 사용하셨다면, 기존 설정을 그대로 사용할 수 있습니다.
|
|
231
|
+
|
|
232
|
+
#### Hooks 통합
|
|
233
|
+
|
|
234
|
+
Claude Code의 `settings.json` 훅 시스템을 통해 커스텀 스크립트를 실행합니다. Oh My OpenCode는 다음 위치의 훅을 읽고 실행합니다:
|
|
235
|
+
|
|
236
|
+
- `~/.claude/settings.json` (사용자)
|
|
237
|
+
- `./.claude/settings.json` (프로젝트)
|
|
238
|
+
- `./.claude/settings.local.json` (로컬, git-ignored)
|
|
239
|
+
|
|
240
|
+
지원되는 훅 이벤트:
|
|
241
|
+
- **PreToolUse**: 도구 실행 전에 실행. 차단하거나 도구 입력을 수정할 수 있습니다.
|
|
242
|
+
- **PostToolUse**: 도구 실행 후에 실행. 경고나 컨텍스트를 추가할 수 있습니다.
|
|
243
|
+
- **UserPromptSubmit**: 사용자가 프롬프트를 제출할 때 실행. 차단하거나 메시지를 주입할 수 있습니다.
|
|
244
|
+
- **Stop**: 세션이 유휴 상태가 될 때 실행. 후속 프롬프트를 주입할 수 있습니다.
|
|
245
|
+
|
|
246
|
+
`settings.json` 예시:
|
|
247
|
+
```json
|
|
248
|
+
{
|
|
249
|
+
"hooks": {
|
|
250
|
+
"PostToolUse": [
|
|
251
|
+
{
|
|
252
|
+
"matcher": "Write|Edit",
|
|
253
|
+
"hooks": [{ "type": "command", "command": "eslint --fix $FILE" }]
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### 설정 로더
|
|
261
|
+
|
|
262
|
+
**Command Loader**: 4개 디렉토리에서 마크다운 기반 슬래시 명령어를 로드합니다:
|
|
263
|
+
- `~/.claude/commands/` (사용자)
|
|
264
|
+
- `./.claude/commands/` (프로젝트)
|
|
265
|
+
- `~/.config/opencode/command/` (opencode 전역)
|
|
266
|
+
- `./.opencode/command/` (opencode 프로젝트)
|
|
267
|
+
|
|
268
|
+
**Skill Loader**: `SKILL.md`가 있는 디렉토리 기반 스킬을 로드합니다:
|
|
269
|
+
- `~/.claude/skills/` (사용자)
|
|
270
|
+
- `./.claude/skills/` (프로젝트)
|
|
271
|
+
|
|
272
|
+
**Agent Loader**: 마크다운 파일에서 커스텀 에이전트 정의를 로드합니다:
|
|
273
|
+
- `~/.claude/agents/*.md` (사용자)
|
|
274
|
+
- `./.claude/agents/*.md` (프로젝트)
|
|
275
|
+
|
|
276
|
+
**MCP Loader**: `.mcp.json` 파일에서 MCP 서버 설정을 로드합니다:
|
|
277
|
+
- `~/.claude/.mcp.json` (사용자)
|
|
278
|
+
- `./.mcp.json` (프로젝트)
|
|
279
|
+
- `./.claude/.mcp.json` (로컬)
|
|
280
|
+
- 환경변수 확장 지원 (`${VAR}` 문법)
|
|
281
|
+
|
|
282
|
+
#### 데이터 저장소
|
|
283
|
+
|
|
284
|
+
**Todo 관리**: 세션 todo가 `~/.claude/todos/`에 Claude Code 호환 형식으로 저장됩니다.
|
|
285
|
+
|
|
286
|
+
**Transcript**: 세션 활동이 `~/.claude/transcripts/`에 JSONL 형식으로 기록되어 재생 및 분석이 가능합니다.
|
|
287
|
+
|
|
288
|
+
> **`claude-code-*` 네이밍에 대해**: `src/features/claude-code-*/` 아래의 기능들은 Claude Code의 설정 시스템에서 마이그레이션되었습니다. 이 네이밍 규칙은 어떤 기능이 Claude Code에서 유래했는지 명확히 식별합니다.
|
|
289
|
+
|
|
227
290
|
### 기타 편의 기능
|
|
228
291
|
|
|
229
292
|
- **Terminal Title**: 세션 상태에 따라 터미널 타이틀을 자동 업데이트합니다 (유휴 ○, 처리중 ◐, 도구 ⚡, 에러 ✖). tmux를 지원합니다.
|
|
230
|
-
- **
|
|
231
|
-
- User scope: `~/.claude/commands/`
|
|
232
|
-
- Project scope: `./.claude/commands/`
|
|
233
|
-
- OpenCode global: `~/.config/opencode/command/`
|
|
234
|
-
- OpenCode project: `./.opencode/command/`
|
|
235
|
-
- **Skill Loader**: 다음 디렉토리들에서 디렉토리 기반의 스킬들을 실행 가능한 명령어로 로드합니다:
|
|
236
|
-
- User scope: `~/.claude/skills/`
|
|
237
|
-
- Project scope: `./.claude/skills/`
|
|
293
|
+
- **Session State**: 이벤트 훅과 터미널 타이틀 업데이트에 사용되는 중앙집중식 세션 추적 모듈입니다.
|
|
238
294
|
|
|
239
295
|
## 설정
|
|
240
296
|
|
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ English | [한국어](README.ko.md)
|
|
|
15
15
|
- [Built-in AST-Grep Tools](#built-in-ast-grep-tools)
|
|
16
16
|
- [Grep](#grep)
|
|
17
17
|
- [Built-in MCPs](#built-in-mcps)
|
|
18
|
+
- [Claude Code Compatibility](#claude-code-compatibility)
|
|
18
19
|
- [Other Features](#other-features)
|
|
19
20
|
- [Configuration](#configuration)
|
|
20
21
|
- [Author's Note](#authors-note)
|
|
@@ -221,29 +222,72 @@ Don't need these? Disable them via `oh-my-opencode.json`:
|
|
|
221
222
|
}
|
|
222
223
|
```
|
|
223
224
|
|
|
225
|
+
### Claude Code Compatibility
|
|
226
|
+
|
|
227
|
+
Oh My OpenCode provides seamless Claude Code configuration compatibility. If you've been using Claude Code, your existing setup works out of the box.
|
|
228
|
+
|
|
229
|
+
#### Hooks Integration
|
|
230
|
+
|
|
231
|
+
Execute custom scripts via Claude Code's `settings.json` hook system. Oh My OpenCode reads and executes hooks defined in:
|
|
232
|
+
|
|
233
|
+
- `~/.claude/settings.json` (user)
|
|
234
|
+
- `./.claude/settings.json` (project)
|
|
235
|
+
- `./.claude/settings.local.json` (local, git-ignored)
|
|
236
|
+
|
|
237
|
+
Supported hook events:
|
|
238
|
+
- **PreToolUse**: Runs before tool execution. Can block or modify tool input.
|
|
239
|
+
- **PostToolUse**: Runs after tool execution. Can add warnings or context.
|
|
240
|
+
- **UserPromptSubmit**: Runs when user submits a prompt. Can block or inject messages.
|
|
241
|
+
- **Stop**: Runs when session goes idle. Can inject follow-up prompts.
|
|
242
|
+
|
|
243
|
+
Example `settings.json`:
|
|
244
|
+
```json
|
|
245
|
+
{
|
|
246
|
+
"hooks": {
|
|
247
|
+
"PostToolUse": [
|
|
248
|
+
{
|
|
249
|
+
"matcher": "Write|Edit",
|
|
250
|
+
"hooks": [{ "type": "command", "command": "eslint --fix $FILE" }]
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
#### Configuration Loaders
|
|
258
|
+
|
|
259
|
+
**Command Loader**: Loads markdown-based slash commands from 4 directories:
|
|
260
|
+
- `~/.claude/commands/` (user)
|
|
261
|
+
- `./.claude/commands/` (project)
|
|
262
|
+
- `~/.config/opencode/command/` (opencode global)
|
|
263
|
+
- `./.opencode/command/` (opencode project)
|
|
264
|
+
|
|
265
|
+
**Skill Loader**: Loads directory-based skills with `SKILL.md`:
|
|
266
|
+
- `~/.claude/skills/` (user)
|
|
267
|
+
- `./.claude/skills/` (project)
|
|
268
|
+
|
|
269
|
+
**Agent Loader**: Loads custom agent definitions from markdown files:
|
|
270
|
+
- `~/.claude/agents/*.md` (user)
|
|
271
|
+
- `./.claude/agents/*.md` (project)
|
|
272
|
+
|
|
273
|
+
**MCP Loader**: Loads MCP server configurations from `.mcp.json` files:
|
|
274
|
+
- `~/.claude/.mcp.json` (user)
|
|
275
|
+
- `./.mcp.json` (project)
|
|
276
|
+
- `./.claude/.mcp.json` (local)
|
|
277
|
+
- Supports environment variable expansion (`${VAR}` syntax)
|
|
278
|
+
|
|
279
|
+
#### Data Storage
|
|
280
|
+
|
|
281
|
+
**Todo Management**: Session todos are stored in Claude Code compatible format at `~/.claude/todos/`.
|
|
282
|
+
|
|
283
|
+
**Transcript**: Session activity is logged to `~/.claude/transcripts/` in JSONL format, enabling replay and analysis.
|
|
284
|
+
|
|
285
|
+
> **Note on `claude-code-*` naming**: Features under `src/features/claude-code-*/` are migrated from Claude Code's configuration system. This naming convention clearly identifies which features originated from Claude Code.
|
|
286
|
+
|
|
224
287
|
### Other Features
|
|
225
288
|
|
|
226
289
|
- **Terminal Title**: Auto-updates terminal title with session status (idle ○, processing ◐, tool ⚡, error ✖). Supports tmux.
|
|
227
|
-
- **
|
|
228
|
-
- User scope: `~/.claude/commands/`
|
|
229
|
-
- Project scope: `./.claude/commands/`
|
|
230
|
-
- OpenCode global: `~/.config/opencode/command/`
|
|
231
|
-
- OpenCode project: `./.opencode/command/`
|
|
232
|
-
- **Skill Loader** (`src/features/claude-code-skill-loader/`): Loads directory-based skills as executable commands:
|
|
233
|
-
- User scope: `~/.claude/skills/`
|
|
234
|
-
- Project scope: `./.claude/skills/`
|
|
235
|
-
- **Agent Loader** (`src/features/claude-code-agent-loader/`): Loads agent definitions from markdown files with YAML frontmatter:
|
|
236
|
-
- User scope: `~/.claude/agents/`
|
|
237
|
-
- Project scope: `./.claude/agents/`
|
|
238
|
-
- Format: `*.md` files with frontmatter (name, description, tools)
|
|
239
|
-
- **Session State** (`src/features/claude-code-session-state/`): Centralized session tracking module used by event hooks and terminal title updates.
|
|
240
|
-
- **MCP Loader** (`src/features/claude-code-mcp-loader/`): Loads MCP server configurations from `.mcp.json` files:
|
|
241
|
-
- User scope: `~/.claude/.mcp.json`
|
|
242
|
-
- Project scope: `./.mcp.json`
|
|
243
|
-
- Local scope: `./.claude/.mcp.json`
|
|
244
|
-
- Supports environment variable expansion (`${VAR}` syntax)
|
|
245
|
-
|
|
246
|
-
> **Note on `claude-code-*` naming**: Features under `src/features/claude-code-*/` are migrated from Claude Code's configuration system. This naming convention clearly identifies which features originated from Claude Code, such as `claude-code-command-loader`, `claude-code-skill-loader`, `claude-code-agent-loader`, and `claude-code-mcp-loader`.
|
|
290
|
+
- **Session State**: Centralized session tracking module used by event hooks and terminal title updates.
|
|
247
291
|
|
|
248
292
|
## Configuration
|
|
249
293
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface MessageMeta {
|
|
2
|
+
id: string;
|
|
3
|
+
sessionID: string;
|
|
4
|
+
role: "user" | "assistant";
|
|
5
|
+
time: {
|
|
6
|
+
created: number;
|
|
7
|
+
completed?: number;
|
|
8
|
+
};
|
|
9
|
+
agent?: string;
|
|
10
|
+
model?: {
|
|
11
|
+
providerID: string;
|
|
12
|
+
modelID: string;
|
|
13
|
+
};
|
|
14
|
+
path?: {
|
|
15
|
+
cwd: string;
|
|
16
|
+
root: string;
|
|
17
|
+
};
|
|
18
|
+
tools?: Record<string, boolean>;
|
|
19
|
+
}
|
|
20
|
+
export interface OriginalMessageContext {
|
|
21
|
+
agent?: string;
|
|
22
|
+
model?: {
|
|
23
|
+
providerID?: string;
|
|
24
|
+
modelID?: string;
|
|
25
|
+
};
|
|
26
|
+
path?: {
|
|
27
|
+
cwd?: string;
|
|
28
|
+
root?: string;
|
|
29
|
+
};
|
|
30
|
+
tools?: Record<string, boolean>;
|
|
31
|
+
}
|
|
32
|
+
export interface TextPart {
|
|
33
|
+
id: string;
|
|
34
|
+
type: "text";
|
|
35
|
+
text: string;
|
|
36
|
+
synthetic: boolean;
|
|
37
|
+
time: {
|
|
38
|
+
start: number;
|
|
39
|
+
end: number;
|
|
40
|
+
};
|
|
41
|
+
messageID: string;
|
|
42
|
+
sessionID: string;
|
|
43
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ClaudeHookEvent } from "./types";
|
|
2
|
+
export interface DisabledHooksConfig {
|
|
3
|
+
Stop?: string[];
|
|
4
|
+
PreToolUse?: string[];
|
|
5
|
+
PostToolUse?: string[];
|
|
6
|
+
UserPromptSubmit?: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface PluginExtendedConfig {
|
|
9
|
+
disabledHooks?: DisabledHooksConfig;
|
|
10
|
+
}
|
|
11
|
+
export declare function loadPluginExtendedConfig(): Promise<PluginExtendedConfig>;
|
|
12
|
+
export declare function isHookCommandDisabled(eventType: ClaudeHookEvent, command: string, config: PluginExtendedConfig | null): boolean;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { PluginConfig } from "./types";
|
|
3
|
+
export declare function createClaudeCodeHooksHook(ctx: PluginInput, config?: PluginConfig): {
|
|
4
|
+
"chat.message": (input: {
|
|
5
|
+
sessionID: string;
|
|
6
|
+
agent?: string;
|
|
7
|
+
model?: {
|
|
8
|
+
providerID: string;
|
|
9
|
+
modelID: string;
|
|
10
|
+
};
|
|
11
|
+
messageID?: string;
|
|
12
|
+
}, output: {
|
|
13
|
+
message: Record<string, unknown>;
|
|
14
|
+
parts: Array<{
|
|
15
|
+
type: string;
|
|
16
|
+
text?: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
}>;
|
|
19
|
+
}) => Promise<void>;
|
|
20
|
+
"tool.execute.before": (input: {
|
|
21
|
+
tool: string;
|
|
22
|
+
sessionID: string;
|
|
23
|
+
callID: string;
|
|
24
|
+
}, output: {
|
|
25
|
+
args: Record<string, unknown>;
|
|
26
|
+
}) => Promise<void>;
|
|
27
|
+
"tool.execute.after": (input: {
|
|
28
|
+
tool: string;
|
|
29
|
+
sessionID: string;
|
|
30
|
+
callID: string;
|
|
31
|
+
}, output: {
|
|
32
|
+
title: string;
|
|
33
|
+
output: string;
|
|
34
|
+
metadata: unknown;
|
|
35
|
+
}) => Promise<void>;
|
|
36
|
+
event: (input: {
|
|
37
|
+
event: {
|
|
38
|
+
type: string;
|
|
39
|
+
properties?: unknown;
|
|
40
|
+
};
|
|
41
|
+
}) => Promise<void>;
|
|
42
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ClaudeHooksConfig } from "./types";
|
|
2
|
+
import { type PluginExtendedConfig } from "./config-loader";
|
|
3
|
+
export interface PostToolUseClient {
|
|
4
|
+
session: {
|
|
5
|
+
messages: (opts: {
|
|
6
|
+
path: {
|
|
7
|
+
id: string;
|
|
8
|
+
};
|
|
9
|
+
query?: {
|
|
10
|
+
directory: string;
|
|
11
|
+
};
|
|
12
|
+
}) => Promise<unknown>;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface PostToolUseContext {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
toolName: string;
|
|
18
|
+
toolInput: Record<string, unknown>;
|
|
19
|
+
toolOutput: Record<string, unknown>;
|
|
20
|
+
cwd: string;
|
|
21
|
+
transcriptPath?: string;
|
|
22
|
+
toolUseId?: string;
|
|
23
|
+
client?: PostToolUseClient;
|
|
24
|
+
permissionMode?: "default" | "plan" | "acceptEdits" | "bypassPermissions";
|
|
25
|
+
}
|
|
26
|
+
export interface PostToolUseResult {
|
|
27
|
+
block: boolean;
|
|
28
|
+
reason?: string;
|
|
29
|
+
message?: string;
|
|
30
|
+
warnings?: string[];
|
|
31
|
+
elapsedMs?: number;
|
|
32
|
+
hookName?: string;
|
|
33
|
+
toolName?: string;
|
|
34
|
+
additionalContext?: string;
|
|
35
|
+
continue?: boolean;
|
|
36
|
+
stopReason?: string;
|
|
37
|
+
suppressOutput?: boolean;
|
|
38
|
+
systemMessage?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function executePostToolUseHooks(ctx: PostToolUseContext, config: ClaudeHooksConfig | null, extendedConfig?: PluginExtendedConfig | null): Promise<PostToolUseResult>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PermissionDecision, ClaudeHooksConfig } from "./types";
|
|
2
|
+
import { type PluginExtendedConfig } from "./config-loader";
|
|
3
|
+
export interface PreToolUseContext {
|
|
4
|
+
sessionId: string;
|
|
5
|
+
toolName: string;
|
|
6
|
+
toolInput: Record<string, unknown>;
|
|
7
|
+
cwd: string;
|
|
8
|
+
transcriptPath?: string;
|
|
9
|
+
toolUseId?: string;
|
|
10
|
+
permissionMode?: "default" | "plan" | "acceptEdits" | "bypassPermissions";
|
|
11
|
+
}
|
|
12
|
+
export interface PreToolUseResult {
|
|
13
|
+
decision: PermissionDecision;
|
|
14
|
+
reason?: string;
|
|
15
|
+
modifiedInput?: Record<string, unknown>;
|
|
16
|
+
elapsedMs?: number;
|
|
17
|
+
hookName?: string;
|
|
18
|
+
toolName?: string;
|
|
19
|
+
inputLines?: string;
|
|
20
|
+
continue?: boolean;
|
|
21
|
+
stopReason?: string;
|
|
22
|
+
suppressOutput?: boolean;
|
|
23
|
+
systemMessage?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function executePreToolUseHooks(ctx: PreToolUseContext, config: ClaudeHooksConfig | null, extendedConfig?: PluginExtendedConfig | null): Promise<PreToolUseResult>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ClaudeHooksConfig } from "./types";
|
|
2
|
+
import { type PluginExtendedConfig } from "./config-loader";
|
|
3
|
+
export declare function setStopHookActive(sessionId: string, active: boolean): void;
|
|
4
|
+
export declare function getStopHookActive(sessionId: string): boolean;
|
|
5
|
+
export interface StopContext {
|
|
6
|
+
sessionId: string;
|
|
7
|
+
parentSessionId?: string;
|
|
8
|
+
cwd: string;
|
|
9
|
+
transcriptPath?: string;
|
|
10
|
+
permissionMode?: "default" | "acceptEdits" | "bypassPermissions";
|
|
11
|
+
stopHookActive?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface StopResult {
|
|
14
|
+
block: boolean;
|
|
15
|
+
reason?: string;
|
|
16
|
+
stopHookActive?: boolean;
|
|
17
|
+
permissionMode?: "default" | "plan" | "acceptEdits" | "bypassPermissions";
|
|
18
|
+
injectPrompt?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function executeStopHooks(ctx: StopContext, config: ClaudeHooksConfig | null, extendedConfig?: PluginExtendedConfig | null): Promise<StopResult>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TodoFile } from "./types";
|
|
2
|
+
export declare function getTodoPath(sessionId: string): string;
|
|
3
|
+
export interface OpenCodeTodo {
|
|
4
|
+
content: string;
|
|
5
|
+
status: string;
|
|
6
|
+
priority: string;
|
|
7
|
+
id: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function loadTodoFile(sessionId: string): TodoFile | null;
|
|
10
|
+
export declare function saveTodoFile(sessionId: string, file: TodoFile): void;
|
|
11
|
+
export declare function saveOpenCodeTodos(sessionId: string, todos: OpenCodeTodo[]): void;
|
|
12
|
+
export declare function deleteTodoFile(sessionId: string): void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caches tool_input from PreToolUse for PostToolUse
|
|
3
|
+
*/
|
|
4
|
+
export declare function cacheToolInput(sessionId: string, toolName: string, invocationId: string, toolInput: Record<string, unknown>): void;
|
|
5
|
+
export declare function getToolInput(sessionId: string, toolName: string, invocationId: string): Record<string, unknown> | null;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { TranscriptEntry } from "./types";
|
|
2
|
+
export declare function getTranscriptPath(sessionId: string): string;
|
|
3
|
+
export declare function appendTranscriptEntry(sessionId: string, entry: TranscriptEntry): void;
|
|
4
|
+
export declare function recordToolUse(sessionId: string, toolName: string, toolInput: Record<string, unknown>): void;
|
|
5
|
+
export declare function recordToolResult(sessionId: string, toolName: string, toolInput: Record<string, unknown>, toolOutput: Record<string, unknown>): void;
|
|
6
|
+
export declare function recordUserMessage(sessionId: string, content: string): void;
|
|
7
|
+
export declare function recordAssistantMessage(sessionId: string, content: string): void;
|
|
8
|
+
/**
|
|
9
|
+
* Build Claude Code compatible transcript from session messages
|
|
10
|
+
*
|
|
11
|
+
* PORT FROM DISABLED: This calls client.session.messages() API to fetch
|
|
12
|
+
* the full session history and builds a JSONL file in Claude Code format.
|
|
13
|
+
*
|
|
14
|
+
* @param client OpenCode client instance
|
|
15
|
+
* @param sessionId Session ID
|
|
16
|
+
* @param directory Working directory
|
|
17
|
+
* @param currentToolName Current tool being executed (added as last entry)
|
|
18
|
+
* @param currentToolInput Current tool input
|
|
19
|
+
* @returns Temp file path (caller must call deleteTempTranscript!)
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildTranscriptFromSession(client: {
|
|
22
|
+
session: {
|
|
23
|
+
messages: (opts: {
|
|
24
|
+
path: {
|
|
25
|
+
id: string;
|
|
26
|
+
};
|
|
27
|
+
query?: {
|
|
28
|
+
directory: string;
|
|
29
|
+
};
|
|
30
|
+
}) => Promise<unknown>;
|
|
31
|
+
};
|
|
32
|
+
}, sessionId: string, directory: string, currentToolName: string, currentToolInput: Record<string, unknown>): Promise<string | null>;
|
|
33
|
+
/**
|
|
34
|
+
* Delete temp transcript file (call in finally block)
|
|
35
|
+
*
|
|
36
|
+
* PORT FROM DISABLED: Cleanup mechanism to avoid disk accumulation
|
|
37
|
+
*/
|
|
38
|
+
export declare function deleteTempTranscript(path: string | null): void;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Hooks Type Definitions
|
|
3
|
+
* Maps Claude Code hook concepts to OpenCode plugin events
|
|
4
|
+
*/
|
|
5
|
+
export type ClaudeHookEvent = "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop";
|
|
6
|
+
export interface HookMatcher {
|
|
7
|
+
matcher: string;
|
|
8
|
+
hooks: HookCommand[];
|
|
9
|
+
}
|
|
10
|
+
export interface HookCommand {
|
|
11
|
+
type: "command";
|
|
12
|
+
command: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ClaudeHooksConfig {
|
|
15
|
+
PreToolUse?: HookMatcher[];
|
|
16
|
+
PostToolUse?: HookMatcher[];
|
|
17
|
+
UserPromptSubmit?: HookMatcher[];
|
|
18
|
+
Stop?: HookMatcher[];
|
|
19
|
+
}
|
|
20
|
+
export interface PreToolUseInput {
|
|
21
|
+
session_id: string;
|
|
22
|
+
transcript_path?: string;
|
|
23
|
+
cwd: string;
|
|
24
|
+
permission_mode?: PermissionMode;
|
|
25
|
+
hook_event_name: "PreToolUse";
|
|
26
|
+
tool_name: string;
|
|
27
|
+
tool_input: Record<string, unknown>;
|
|
28
|
+
tool_use_id?: string;
|
|
29
|
+
hook_source?: HookSource;
|
|
30
|
+
}
|
|
31
|
+
export interface PostToolUseInput {
|
|
32
|
+
session_id: string;
|
|
33
|
+
transcript_path?: string;
|
|
34
|
+
cwd: string;
|
|
35
|
+
permission_mode?: PermissionMode;
|
|
36
|
+
hook_event_name: "PostToolUse";
|
|
37
|
+
tool_name: string;
|
|
38
|
+
tool_input: Record<string, unknown>;
|
|
39
|
+
tool_response: {
|
|
40
|
+
title?: string;
|
|
41
|
+
output?: string;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
};
|
|
44
|
+
tool_use_id?: string;
|
|
45
|
+
hook_source?: HookSource;
|
|
46
|
+
}
|
|
47
|
+
export interface UserPromptSubmitInput {
|
|
48
|
+
session_id: string;
|
|
49
|
+
cwd: string;
|
|
50
|
+
permission_mode?: PermissionMode;
|
|
51
|
+
hook_event_name: "UserPromptSubmit";
|
|
52
|
+
prompt: string;
|
|
53
|
+
session?: {
|
|
54
|
+
id: string;
|
|
55
|
+
};
|
|
56
|
+
hook_source?: HookSource;
|
|
57
|
+
}
|
|
58
|
+
export type PermissionMode = "default" | "plan" | "acceptEdits" | "bypassPermissions";
|
|
59
|
+
export type HookSource = "opencode-plugin";
|
|
60
|
+
export interface StopInput {
|
|
61
|
+
session_id: string;
|
|
62
|
+
transcript_path?: string;
|
|
63
|
+
cwd: string;
|
|
64
|
+
permission_mode?: PermissionMode;
|
|
65
|
+
hook_event_name: "Stop";
|
|
66
|
+
stop_hook_active: boolean;
|
|
67
|
+
todo_path?: string;
|
|
68
|
+
hook_source?: HookSource;
|
|
69
|
+
}
|
|
70
|
+
export type PermissionDecision = "allow" | "deny" | "ask";
|
|
71
|
+
/**
|
|
72
|
+
* Common JSON fields for all hook outputs (Claude Code spec)
|
|
73
|
+
*/
|
|
74
|
+
export interface HookCommonOutput {
|
|
75
|
+
/** If false, Claude stops entirely */
|
|
76
|
+
continue?: boolean;
|
|
77
|
+
/** Message shown to user when continue=false */
|
|
78
|
+
stopReason?: string;
|
|
79
|
+
/** Suppress output from transcript */
|
|
80
|
+
suppressOutput?: boolean;
|
|
81
|
+
/** Warning/message displayed to user */
|
|
82
|
+
systemMessage?: string;
|
|
83
|
+
}
|
|
84
|
+
export interface PreToolUseOutput extends HookCommonOutput {
|
|
85
|
+
/** Deprecated: use hookSpecificOutput.permissionDecision instead */
|
|
86
|
+
decision?: "allow" | "deny" | "approve" | "block" | "ask";
|
|
87
|
+
/** Deprecated: use hookSpecificOutput.permissionDecisionReason instead */
|
|
88
|
+
reason?: string;
|
|
89
|
+
hookSpecificOutput?: {
|
|
90
|
+
hookEventName: "PreToolUse";
|
|
91
|
+
permissionDecision: PermissionDecision;
|
|
92
|
+
permissionDecisionReason?: string;
|
|
93
|
+
updatedInput?: Record<string, unknown>;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export interface PostToolUseOutput extends HookCommonOutput {
|
|
97
|
+
decision?: "block";
|
|
98
|
+
reason?: string;
|
|
99
|
+
hookSpecificOutput?: {
|
|
100
|
+
hookEventName: "PostToolUse";
|
|
101
|
+
/** Additional context to provide to Claude */
|
|
102
|
+
additionalContext?: string;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export interface HookResult {
|
|
106
|
+
exitCode: number;
|
|
107
|
+
stdout?: string;
|
|
108
|
+
stderr?: string;
|
|
109
|
+
}
|
|
110
|
+
export interface TranscriptEntry {
|
|
111
|
+
type: "tool_use" | "tool_result" | "user" | "assistant";
|
|
112
|
+
timestamp: string;
|
|
113
|
+
tool_name?: string;
|
|
114
|
+
tool_input?: Record<string, unknown>;
|
|
115
|
+
tool_output?: Record<string, unknown>;
|
|
116
|
+
content?: string;
|
|
117
|
+
}
|
|
118
|
+
export interface TodoItem {
|
|
119
|
+
id: string;
|
|
120
|
+
content: string;
|
|
121
|
+
status: "pending" | "in_progress" | "completed" | "cancelled";
|
|
122
|
+
priority?: "low" | "medium" | "high";
|
|
123
|
+
created_at: string;
|
|
124
|
+
updated_at?: string;
|
|
125
|
+
}
|
|
126
|
+
export interface ClaudeCodeTodoItem {
|
|
127
|
+
content: string;
|
|
128
|
+
status: string;
|
|
129
|
+
activeForm: string;
|
|
130
|
+
}
|
|
131
|
+
export interface TodoFile {
|
|
132
|
+
session_id: string;
|
|
133
|
+
items: TodoItem[];
|
|
134
|
+
created_at: string;
|
|
135
|
+
updated_at: string;
|
|
136
|
+
}
|
|
137
|
+
export interface StopOutput {
|
|
138
|
+
decision?: "block" | "continue";
|
|
139
|
+
reason?: string;
|
|
140
|
+
stop_hook_active?: boolean;
|
|
141
|
+
permission_mode?: PermissionMode;
|
|
142
|
+
inject_prompt?: string;
|
|
143
|
+
}
|
|
144
|
+
export type ClaudeCodeContent = {
|
|
145
|
+
type: "text";
|
|
146
|
+
text: string;
|
|
147
|
+
} | {
|
|
148
|
+
type: "tool_use";
|
|
149
|
+
id: string;
|
|
150
|
+
name: string;
|
|
151
|
+
input: Record<string, unknown>;
|
|
152
|
+
} | {
|
|
153
|
+
type: "tool_result";
|
|
154
|
+
tool_use_id: string;
|
|
155
|
+
content: string;
|
|
156
|
+
};
|
|
157
|
+
export interface ClaudeCodeMessage {
|
|
158
|
+
type: "user" | "assistant";
|
|
159
|
+
message: {
|
|
160
|
+
role: "user" | "assistant";
|
|
161
|
+
content: ClaudeCodeContent[];
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
export interface PluginConfig {
|
|
165
|
+
disabledHooks?: boolean | ClaudeHookEvent[];
|
|
166
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ClaudeHooksConfig } from "./types";
|
|
2
|
+
import { type PluginExtendedConfig } from "./config-loader";
|
|
3
|
+
export interface MessagePart {
|
|
4
|
+
type: "text" | "tool_use" | "tool_result";
|
|
5
|
+
text?: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface UserPromptSubmitContext {
|
|
9
|
+
sessionId: string;
|
|
10
|
+
parentSessionId?: string;
|
|
11
|
+
prompt: string;
|
|
12
|
+
parts: MessagePart[];
|
|
13
|
+
cwd: string;
|
|
14
|
+
permissionMode?: "default" | "acceptEdits" | "bypassPermissions";
|
|
15
|
+
}
|
|
16
|
+
export interface UserPromptSubmitResult {
|
|
17
|
+
block: boolean;
|
|
18
|
+
reason?: string;
|
|
19
|
+
modifiedParts: MessagePart[];
|
|
20
|
+
messages: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function executeUserPromptSubmitHooks(ctx: UserPromptSubmitContext, config: ClaudeHooksConfig | null, extendedConfig?: PluginExtendedConfig | null): Promise<UserPromptSubmitResult>;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -8,3 +8,4 @@ export { createDirectoryAgentsInjectorHook } from "./directory-agents-injector";
|
|
|
8
8
|
export { createEmptyTaskResponseDetectorHook } from "./empty-task-response-detector";
|
|
9
9
|
export { createAnthropicAutoCompactHook } from "./anthropic-auto-compact";
|
|
10
10
|
export { createThinkModeHook } from "./think-mode";
|
|
11
|
+
export { createClaudeCodeHooksHook } from "./claude-code-hooks";
|