@betrue/openclaw-claude-code-plugin 1.0.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.md +599 -0
- package/index.ts +158 -0
- package/openclaw.plugin.json +20 -0
- package/package.json +38 -0
- package/src/commands/claude-bg.ts +52 -0
- package/src/commands/claude-fg.ts +71 -0
- package/src/commands/claude-kill.ts +42 -0
- package/src/commands/claude-respond.ts +92 -0
- package/src/commands/claude-resume.ts +114 -0
- package/src/commands/claude-sessions.ts +27 -0
- package/src/commands/claude-stats.ts +20 -0
- package/src/commands/claude.ts +61 -0
- package/src/gateway.ts +185 -0
- package/src/notifications.ts +405 -0
- package/src/session-manager.ts +481 -0
- package/src/session.ts +455 -0
- package/src/shared.ts +194 -0
- package/src/tools/claude-bg.ts +100 -0
- package/src/tools/claude-fg.ts +106 -0
- package/src/tools/claude-kill.ts +66 -0
- package/src/tools/claude-launch.ts +173 -0
- package/src/tools/claude-output.ts +80 -0
- package/src/tools/claude-respond.ts +113 -0
- package/src/tools/claude-sessions.ts +63 -0
- package/src/tools/claude-stats.ts +33 -0
- package/src/types.ts +77 -0
package/README.md
ADDED
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
# Claude Code Plugin
|
|
2
|
+
|
|
3
|
+
**An OpenClaw plugin that orchestrates Claude Code sessions as managed background processes.**
|
|
4
|
+
|
|
5
|
+
Claude Code Plugin lets you launch, monitor, and interact with multiple Claude Code SDK sessions directly from any OpenClaw channel (Telegram, Discord, etc.). It turns OpenClaw into a control plane for autonomous coding agents — launch tasks, stream output in real time, send follow-up messages, resume previous conversations, and catch up on missed output — all without leaving your chat interface.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Features](#features)
|
|
12
|
+
- [Architecture](#architecture)
|
|
13
|
+
- [Installation](#installation)
|
|
14
|
+
- [Configuration](#configuration)
|
|
15
|
+
- [Usage](#usage)
|
|
16
|
+
- [Chat Commands](#chat-commands)
|
|
17
|
+
- [Agent Tools](#agent-tools)
|
|
18
|
+
- [Gateway RPC Methods](#gateway-rpc-methods)
|
|
19
|
+
- [API Reference](#api-reference)
|
|
20
|
+
- [Tools](#tools)
|
|
21
|
+
- [Commands](#commands)
|
|
22
|
+
- [RPC Methods](#rpc-methods)
|
|
23
|
+
- [Notification System](#notification-system)
|
|
24
|
+
- [Skill Example: Coding Agent Workflow](#skill-example-coding-agent-workflow)
|
|
25
|
+
- [Development](#development)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- **Multi-session management** — Run up to N concurrent Claude Code sessions (configurable), each tracked with a unique ID and human-readable name.
|
|
32
|
+
- **Foreground / background model** — Sessions run in the background by default. Bring any session to the foreground to stream output in real time, then detach without interrupting work.
|
|
33
|
+
- **Foreground catchup** — When you bring a session to the foreground with `claude_fg`, any output produced while it was in the background is displayed under a "📋 Catchup (N missed outputs):" header before live streaming begins, so you never miss anything.
|
|
34
|
+
- **Multi-turn conversations** — Launch sessions in multi-turn mode to send follow-up messages, refine instructions, or have iterative dialogues with a running agent.
|
|
35
|
+
- **Session resume & fork** — Resume any completed session from where it left off, or fork it into a new branch of conversation.
|
|
36
|
+
- **Real-time notifications** — Completion alerts, session-limit warnings, long-running session reminders, and live tool-use indicators delivered to your chat.
|
|
37
|
+
- **Channel propagation** — `claude_launch`, `claude_fg`, and `claude_bg` accept an optional `channel` parameter (e.g. `"telegram:123456789"`) so notifications are routed to the correct user channel instead of falling back to `"unknown"`.
|
|
38
|
+
- **Waiting-for-input wake events** — When any session (single or multi-turn) becomes idle and waiting for input, an `openclaw system event` is fired to wake the orchestrator. Uses end-of-turn detection for multi-turn results plus a 15-second safety-net timer. A `waitingForInputFired` guard prevents duplicate events.
|
|
39
|
+
- **Background visibility** — Even when sessions run in the background, users see `🔔 Claude asks:` when the agent needs input and `↩️ Responded:` when a follow-up is sent — the full conversation stays visible in-channel.
|
|
40
|
+
- **Session metrics** — Per-session tracking, session counts by status, average duration, and notable-session reporting (internally tracked).
|
|
41
|
+
- **Triple interface** — Every operation is available as a chat command (for humans), an agent tool (for the OpenClaw AI), and a gateway RPC method (for external systems).
|
|
42
|
+
- **Automatic cleanup** — Completed sessions are garbage-collected after 1 hour; persisted session IDs survive for resume support (up to a configurable cap).
|
|
43
|
+
- **Agent event triggers** — When a session completes or becomes idle waiting for input, an OpenClaw system event is fired so the AI agent can immediately process the result or provide follow-up instructions.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Architecture
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
┌─────────────────────────────────────────────────────┐
|
|
51
|
+
│ index.ts │
|
|
52
|
+
│ (Plugin entry point) │
|
|
53
|
+
│ Registers tools, commands, RPC methods, service │
|
|
54
|
+
└──────────────┬──────────────────────────────────────┘
|
|
55
|
+
│
|
|
56
|
+
┌────────┼─────────────────┐
|
|
57
|
+
│ │ │
|
|
58
|
+
▼ ▼ ▼
|
|
59
|
+
Tools Commands Gateway RPC
|
|
60
|
+
(8) (8) (5 methods)
|
|
61
|
+
│ │ │
|
|
62
|
+
└────────┼─────────────────┘
|
|
63
|
+
│
|
|
64
|
+
▼
|
|
65
|
+
┌─────────────┐ ┌────────────────────┐
|
|
66
|
+
│ shared.ts │────▶│ SessionManager │
|
|
67
|
+
│ (globals, │ │ (spawn, resolve, │
|
|
68
|
+
│ helpers) │ │ kill, cleanup, │
|
|
69
|
+
│ │ │ metrics, persist)│
|
|
70
|
+
└─────────────┘ └────────┬───────────┘
|
|
71
|
+
│
|
|
72
|
+
┌────────┴───────────┐
|
|
73
|
+
│ Session │
|
|
74
|
+
│ (Claude SDK │
|
|
75
|
+
│ query() wrapper, │
|
|
76
|
+
│ message stream, │
|
|
77
|
+
│ abort, output) │
|
|
78
|
+
└────────────────────┘
|
|
79
|
+
│
|
|
80
|
+
┌────────┴───────────┐
|
|
81
|
+
│ NotificationRouter │
|
|
82
|
+
│ (foreground │
|
|
83
|
+
│ streaming, │
|
|
84
|
+
│ catchup display, │
|
|
85
|
+
│ completion, │
|
|
86
|
+
│ session-limit, │
|
|
87
|
+
│ long-run remind) │
|
|
88
|
+
└────────────────────┘
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Key Components
|
|
92
|
+
|
|
93
|
+
| Component | File | Responsibility |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| **Session** | `src/session.ts` | Wraps the Claude Agent SDK `query()` call. Manages the async message stream, output buffering (last 200 blocks), abort control, multi-turn `MessageStream`, idle timeouts, waiting-for-input detection (end-of-turn + 15s safety-net timer with `waitingForInputFired` guard), and event callbacks (`onOutput`, `onToolUse`, `onComplete`, `onSessionLimitReached`). |
|
|
96
|
+
| **SessionManager** | `src/session-manager.ts` | Manages the pool of active sessions. Enforces `maxSessions`, generates unique names, wires notification callbacks, persists Claude session IDs for resume, records metrics, triggers agent events on completion and waiting-for-input, and runs periodic garbage collection. |
|
|
97
|
+
| **NotificationRouter** | `src/notifications.ts` | Routes events to the right chat channels. Debounces foreground text streaming (500ms), shows compact tool-use indicators, sends completion/failure/session-limit notifications, foreground catchup display, and periodically checks for sessions running longer than 10 minutes. |
|
|
98
|
+
| **Gateway** | `src/gateway.ts` | Exposes 5 JSON-RPC methods for external/programmatic access. |
|
|
99
|
+
| **Shared** | `src/shared.ts` | Global singletons (`sessionManager`, `notificationRouter`, `pluginConfig`), helper functions (name generation, duration formatting, session listing, stats formatting), and channel resolution logic. |
|
|
100
|
+
| **Types** | `src/types.ts` | TypeScript interfaces: `SessionConfig`, `ClaudeSession`, `PluginConfig`, `SessionStatus`, `PermissionMode`. |
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
105
|
+
|
|
106
|
+
### From npm
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
openclaw plugins install @betrue/openclaw-claude-code-plugin
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### From source (git clone)
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
git clone git@github.com:alizarion/openclaw-claude-code-plugin.git
|
|
116
|
+
openclaw plugins install ./openclaw-claude-code-plugin
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### For development (symlink)
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
git clone git@github.com:alizarion/openclaw-claude-code-plugin.git
|
|
123
|
+
openclaw plugins install --link ./openclaw-claude-code-plugin
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### After installation
|
|
127
|
+
|
|
128
|
+
Restart the gateway to load the plugin:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
openclaw gateway restart
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Ensure `openclaw` CLI is available in your PATH — the plugin shells out to `openclaw message send` for notifications and `openclaw system event` for agent triggers.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Configuration
|
|
139
|
+
|
|
140
|
+
Configuration is defined in `openclaw.plugin.json` under `configSchema` and passed to the plugin at service start via `api.getConfig()`.
|
|
141
|
+
|
|
142
|
+
| Option | Type | Default | Description |
|
|
143
|
+
|---|---|---|---|
|
|
144
|
+
| `maxSessions` | `number` | `5` | Maximum number of concurrently active (starting/running) sessions. |
|
|
145
|
+
| `defaultBudgetUsd` | `number` | `5` | Default max budget in USD for new sessions when not explicitly specified. |
|
|
146
|
+
| `defaultModel` | `string` | — | Default model for new sessions (e.g. `"sonnet"`, `"opus"`). |
|
|
147
|
+
| `defaultWorkdir` | `string` | — | Default working directory for new sessions. Falls back to `process.cwd()`. |
|
|
148
|
+
| `idleTimeoutMinutes` | `number` | `30` | Idle timeout for multi-turn sessions. If no follow-up message is sent within this window, the session is auto-killed. |
|
|
149
|
+
| `maxPersistedSessions` | `number` | `50` | Maximum number of completed sessions to keep in memory for resume support. Oldest sessions are evicted when the cap is exceeded. |
|
|
150
|
+
| `fallbackChannel` | `string` | — | Fallback notification channel (e.g. `"telegram:123456789"`). Used when the origin channel cannot be determined. |
|
|
151
|
+
| `permissionMode` | `string` | `"bypassPermissions"` | Default permission mode for Claude Code sessions. One of: `"default"`, `"plan"`, `"acceptEdits"`, `"bypassPermissions"`. |
|
|
152
|
+
|
|
153
|
+
### Example configuration
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"maxSessions": 3,
|
|
158
|
+
"defaultBudgetUsd": 10,
|
|
159
|
+
"defaultModel": "sonnet",
|
|
160
|
+
"defaultWorkdir": "/home/user/projects",
|
|
161
|
+
"idleTimeoutMinutes": 60,
|
|
162
|
+
"maxPersistedSessions": 100,
|
|
163
|
+
"fallbackChannel": "telegram:123456789",
|
|
164
|
+
"permissionMode": "bypassPermissions"
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Usage
|
|
171
|
+
|
|
172
|
+
### Chat Commands
|
|
173
|
+
|
|
174
|
+
Commands are invoked by humans in chat (Telegram, Discord, etc.) with a `/` prefix.
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
/claude Fix the authentication bug in src/auth.ts
|
|
178
|
+
/claude --name fix-auth Fix the authentication bug in src/auth.ts
|
|
179
|
+
/claude_sessions
|
|
180
|
+
/claude_fg fix-auth
|
|
181
|
+
/claude_bg
|
|
182
|
+
/claude_bg fix-auth
|
|
183
|
+
/claude_kill fix-auth
|
|
184
|
+
/claude_respond fix-auth Also add unit tests for the fix
|
|
185
|
+
/claude_respond --interrupt fix-auth Stop, use a different approach
|
|
186
|
+
/claude_resume --list
|
|
187
|
+
/claude_resume fix-auth Add error handling to the login flow
|
|
188
|
+
/claude_resume --fork fix-auth Try a completely different approach
|
|
189
|
+
/claude_stats
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Agent Tools
|
|
193
|
+
|
|
194
|
+
Tools are invoked by the OpenClaw AI agent programmatically. They follow the MCP tool calling convention.
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
claude_launch(prompt: "Fix auth bug", workdir: "/app", name: "fix-auth")
|
|
198
|
+
claude_launch(prompt: "Refactor DB layer", multi_turn: true, channel: "telegram:123456789")
|
|
199
|
+
claude_launch(prompt: "Continue", resume_session_id: "abc123", fork_session: true)
|
|
200
|
+
claude_sessions(status: "running")
|
|
201
|
+
claude_output(session: "fix-auth", full: true)
|
|
202
|
+
claude_fg(session: "fix-auth", channel: "telegram:123456789")
|
|
203
|
+
claude_bg(session: "fix-auth", channel: "telegram:123456789")
|
|
204
|
+
claude_kill(session: "fix-auth")
|
|
205
|
+
claude_respond(session: "fix-auth", message: "Also add tests", interrupt: false)
|
|
206
|
+
claude_stats()
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Gateway RPC Methods
|
|
210
|
+
|
|
211
|
+
RPC methods are called by external clients (dashboards, APIs, other plugins) via the OpenClaw gateway.
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
// Launch a session
|
|
215
|
+
{ "method": "claude-code.launch", "params": { "prompt": "Fix auth", "workdir": "/app" } }
|
|
216
|
+
|
|
217
|
+
// List sessions
|
|
218
|
+
{ "method": "claude-code.sessions", "params": { "status": "running" } }
|
|
219
|
+
|
|
220
|
+
// Get output
|
|
221
|
+
{ "method": "claude-code.output", "params": { "session": "fix-auth", "full": true } }
|
|
222
|
+
|
|
223
|
+
// Kill a session
|
|
224
|
+
{ "method": "claude-code.kill", "params": { "session": "fix-auth" } }
|
|
225
|
+
|
|
226
|
+
// Get stats
|
|
227
|
+
{ "method": "claude-code.stats" }
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## API Reference
|
|
233
|
+
|
|
234
|
+
### Tools
|
|
235
|
+
|
|
236
|
+
#### `claude_launch`
|
|
237
|
+
|
|
238
|
+
Launch a new Claude Code session.
|
|
239
|
+
|
|
240
|
+
| Parameter | Type | Required | Description |
|
|
241
|
+
|---|---|---|---|
|
|
242
|
+
| `prompt` | `string` | Yes | The task prompt to execute. |
|
|
243
|
+
| `name` | `string` | No | Human-readable name (kebab-case). Auto-generated from prompt if omitted. |
|
|
244
|
+
| `workdir` | `string` | No | Working directory. Defaults to config `defaultWorkdir` or `cwd`. |
|
|
245
|
+
| `model` | `string` | No | Model name (e.g. `"sonnet"`, `"opus"`). |
|
|
246
|
+
| `max_budget_usd` | `number` | No | Maximum budget in USD. Default: `5`. |
|
|
247
|
+
| `system_prompt` | `string` | No | Additional system prompt appended to the session. |
|
|
248
|
+
| `allowed_tools` | `string[]` | No | Explicit list of allowed tools. |
|
|
249
|
+
| `resume_session_id` | `string` | No | Claude session ID (or name/internal ID) to resume from. |
|
|
250
|
+
| `fork_session` | `boolean` | No | Fork instead of continuing when resuming. |
|
|
251
|
+
| `multi_turn` | `boolean` | No | Enable multi-turn mode for follow-up messages via `claude_respond`. |
|
|
252
|
+
| `permission_mode` | `string` | No | One of `"default"`, `"plan"`, `"acceptEdits"`, `"bypassPermissions"`. |
|
|
253
|
+
| `channel` | `string` | No | Origin channel for notifications (e.g. `"telegram:123456789"`). Prevents `"unknown"` routing. |
|
|
254
|
+
|
|
255
|
+
#### `claude_sessions`
|
|
256
|
+
|
|
257
|
+
List all sessions with status and progress.
|
|
258
|
+
|
|
259
|
+
| Parameter | Type | Required | Description |
|
|
260
|
+
|---|---|---|---|
|
|
261
|
+
| `status` | `string` | No | Filter: `"all"` (default), `"running"`, `"completed"`, `"failed"`. |
|
|
262
|
+
|
|
263
|
+
#### `claude_output`
|
|
264
|
+
|
|
265
|
+
Show output from a session.
|
|
266
|
+
|
|
267
|
+
| Parameter | Type | Required | Description |
|
|
268
|
+
|---|---|---|---|
|
|
269
|
+
| `session` | `string` | Yes | Session name or ID. |
|
|
270
|
+
| `lines` | `number` | No | Number of recent lines to show (default 50). |
|
|
271
|
+
| `full` | `boolean` | No | Show all available output (up to 200 buffered blocks). |
|
|
272
|
+
|
|
273
|
+
#### `claude_fg`
|
|
274
|
+
|
|
275
|
+
Bring a session to foreground — displays any missed background output under a "📋 Catchup (N missed outputs):" header, then starts streaming new output to the current channel in real time.
|
|
276
|
+
|
|
277
|
+
| Parameter | Type | Required | Description |
|
|
278
|
+
|---|---|---|---|
|
|
279
|
+
| `session` | `string` | Yes | Session name or ID. |
|
|
280
|
+
| `lines` | `number` | No | Number of recent buffered lines to show (default 30). |
|
|
281
|
+
| `channel` | `string` | No | Target channel for streaming (e.g. `"telegram:123456789"`). Prevents `"unknown"` routing. |
|
|
282
|
+
|
|
283
|
+
#### `claude_bg`
|
|
284
|
+
|
|
285
|
+
Send a session back to background (stop streaming).
|
|
286
|
+
|
|
287
|
+
| Parameter | Type | Required | Description |
|
|
288
|
+
|---|---|---|---|
|
|
289
|
+
| `session` | `string` | No | Session name or ID. If omitted, detaches all foreground sessions for the current channel. |
|
|
290
|
+
| `channel` | `string` | No | Channel to detach from (e.g. `"telegram:123456789"`). Prevents `"unknown"` routing. |
|
|
291
|
+
|
|
292
|
+
#### `claude_kill`
|
|
293
|
+
|
|
294
|
+
Terminate a running session.
|
|
295
|
+
|
|
296
|
+
| Parameter | Type | Required | Description |
|
|
297
|
+
|---|---|---|---|
|
|
298
|
+
| `session` | `string` | Yes | Session name or ID. |
|
|
299
|
+
|
|
300
|
+
#### `claude_respond`
|
|
301
|
+
|
|
302
|
+
Send a follow-up message to a running session.
|
|
303
|
+
|
|
304
|
+
| Parameter | Type | Required | Description |
|
|
305
|
+
|---|---|---|---|
|
|
306
|
+
| `session` | `string` | Yes | Session name or ID. |
|
|
307
|
+
| `message` | `string` | Yes | The message to send. |
|
|
308
|
+
| `interrupt` | `boolean` | No | Interrupt the current turn before sending. Useful to redirect mid-response. |
|
|
309
|
+
|
|
310
|
+
#### `claude_stats`
|
|
311
|
+
|
|
312
|
+
Show usage metrics. Takes no parameters.
|
|
313
|
+
|
|
314
|
+
Returns: session counts by status, average duration, and notable session (sorted by cost internally — cost values are not shown in user-facing output).
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
### Commands
|
|
319
|
+
|
|
320
|
+
All commands require authentication (`requireAuth: true`).
|
|
321
|
+
|
|
322
|
+
| Command | Arguments | Description |
|
|
323
|
+
|---|---|---|
|
|
324
|
+
| `/claude [--name <name>] <prompt>` | Required: prompt | Launch a new session. |
|
|
325
|
+
| `/claude_sessions` | None | List all sessions. |
|
|
326
|
+
| `/claude_kill <name-or-id>` | Required: session ref | Terminate a session. |
|
|
327
|
+
| `/claude_fg <name-or-id>` | Required: session ref | Bring a session to foreground. |
|
|
328
|
+
| `/claude_bg [name-or-id]` | Optional: session ref | Detach foreground session(s). |
|
|
329
|
+
| `/claude_resume <ref> [prompt]` | Required: session ref | Resume a completed session. |
|
|
330
|
+
| `/claude_resume --list` | Flag | List all resumable sessions. |
|
|
331
|
+
| `/claude_resume --fork <ref> [prompt]` | Required: session ref | Fork a completed session. |
|
|
332
|
+
| `/claude_respond <ref> <message>` | Required: session ref + message | Send a follow-up message. |
|
|
333
|
+
| `/claude_respond --interrupt <ref> <msg>` | Flag + session ref + message | Interrupt then send. |
|
|
334
|
+
| `/claude_stats` | None | Show usage metrics. |
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
### RPC Methods
|
|
339
|
+
|
|
340
|
+
All methods return `respond(true, data)` on success or `respond(false, { error })` on failure.
|
|
341
|
+
|
|
342
|
+
#### `claude-code.sessions`
|
|
343
|
+
|
|
344
|
+
| Parameter | Type | Description |
|
|
345
|
+
|---|---|---|
|
|
346
|
+
| `status` | `string` | Filter: `"all"`, `"running"`, `"completed"`, `"failed"`. |
|
|
347
|
+
|
|
348
|
+
**Response:** `{ sessions: [...], count: number }`
|
|
349
|
+
|
|
350
|
+
Each session object includes: `id`, `name`, `status`, `prompt`, `workdir`, `model`, `startedAt`, `completedAt`, `durationMs`, `claudeSessionId`, `foreground`, `multiTurn`, `display`.
|
|
351
|
+
|
|
352
|
+
#### `claude-code.launch`
|
|
353
|
+
|
|
354
|
+
| Parameter | Type | Description |
|
|
355
|
+
|---|---|---|
|
|
356
|
+
| `prompt` | `string` | **(required)** Task prompt. |
|
|
357
|
+
| `name` | `string` | Session name. |
|
|
358
|
+
| `workdir` | `string` | Working directory. |
|
|
359
|
+
| `model` | `string` | Model name. |
|
|
360
|
+
| `maxBudgetUsd` / `max_budget_usd` | `number` | Budget cap. |
|
|
361
|
+
| `systemPrompt` / `system_prompt` | `string` | System prompt. |
|
|
362
|
+
| `allowedTools` / `allowed_tools` | `string[]` | Allowed tools. |
|
|
363
|
+
| `resumeSessionId` / `resume_session_id` | `string` | Session ID to resume. |
|
|
364
|
+
| `forkSession` / `fork_session` | `boolean` | Fork on resume. |
|
|
365
|
+
| `multiTurn` / `multi_turn` | `boolean` | Multi-turn mode. |
|
|
366
|
+
| `originChannel` | `string` | Origin channel for notifications. |
|
|
367
|
+
|
|
368
|
+
**Response:** `{ id, name, status, workdir, model }`
|
|
369
|
+
|
|
370
|
+
#### `claude-code.kill`
|
|
371
|
+
|
|
372
|
+
| Parameter | Type | Description |
|
|
373
|
+
|---|---|---|
|
|
374
|
+
| `session` / `id` | `string` | **(required)** Session name or ID. |
|
|
375
|
+
|
|
376
|
+
**Response:** `{ id, name, status, message }`
|
|
377
|
+
|
|
378
|
+
#### `claude-code.output`
|
|
379
|
+
|
|
380
|
+
| Parameter | Type | Description |
|
|
381
|
+
|---|---|---|
|
|
382
|
+
| `session` / `id` | `string` | **(required)** Session name or ID. |
|
|
383
|
+
| `lines` | `number` | Number of lines (default 50). |
|
|
384
|
+
| `full` | `boolean` | Return all buffered output. |
|
|
385
|
+
|
|
386
|
+
**Response:** `{ id, name, status, durationMs, duration, lines, lineCount, result }`
|
|
387
|
+
|
|
388
|
+
#### `claude-code.stats`
|
|
389
|
+
|
|
390
|
+
No parameters.
|
|
391
|
+
|
|
392
|
+
**Response:**
|
|
393
|
+
```json
|
|
394
|
+
{
|
|
395
|
+
"sessionsByStatus": { "completed": 10, "failed": 2, "killed": 1, "running": 1 },
|
|
396
|
+
"totalLaunched": 14,
|
|
397
|
+
"averageDurationMs": 45000,
|
|
398
|
+
"notableSession": { "id": "abc123", "name": "refactor-db", "prompt": "..." },
|
|
399
|
+
"display": "📊 Claude Code Plugin Stats\n..."
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## Notification System
|
|
406
|
+
|
|
407
|
+
The `NotificationRouter` implements a notification matrix based on session state and channel mode:
|
|
408
|
+
|
|
409
|
+
| Event | Background session | Foreground session |
|
|
410
|
+
|---|---|---|
|
|
411
|
+
| Session started | Silent | Silent (streaming begins) |
|
|
412
|
+
| Assistant text output | Silent | Streamed to chat (500ms debounce) |
|
|
413
|
+
| Tool call | Silent | Compact indicator (e.g. `🔧 Bash — git status`) |
|
|
414
|
+
| Tool result | Silent | Silent |
|
|
415
|
+
| Session completed (success) | Notify origin channel | Notify all channels |
|
|
416
|
+
| Session completed (error) | Notify origin channel | Notify all channels |
|
|
417
|
+
| Session limit reached | Notify origin channel | Notify all channels |
|
|
418
|
+
| Session > 10 minutes | One-time reminder | Silent (user sees output) |
|
|
419
|
+
| Waiting for input | `🔔 [name] Claude asks:` + preview to origin channel + fire `openclaw system event` | `💬 Session waiting for input` + fire `openclaw system event` |
|
|
420
|
+
| Agent responds (`claude_respond`) | `↩️ [name] Responded:` echoed to origin channel | `↩️ [name] Responded:` echoed to origin channel |
|
|
421
|
+
|
|
422
|
+
### Notification delivery
|
|
423
|
+
|
|
424
|
+
Notifications are sent via the `openclaw message send` CLI command. The channel ID format is `"channel:target"` (e.g. `"telegram:123456789"`, `"discord:987654321"`). Bare numeric IDs are assumed to be Telegram chat IDs.
|
|
425
|
+
|
|
426
|
+
### Background visibility
|
|
427
|
+
|
|
428
|
+
When a session is running in the background, users can follow the conversation without foregrounding:
|
|
429
|
+
|
|
430
|
+
- **🔔 Claude asks** — When a session becomes idle and waiting for input (e.g. Claude asked a question or needs a decision), the origin channel receives a `🔔 [name] Claude asks:` message with a preview of the last output, so the user sees what Claude needs.
|
|
431
|
+
- **↩️ Responded** — When the agent (or user via `claude_respond`) sends a follow-up message, a `↩️ [name] Responded:` message is echoed to the origin channel with the response content, so the full conversation is visible in-channel.
|
|
432
|
+
|
|
433
|
+
This makes the plugin a transparent transport layer — the user sees both sides of the conversation in their chat, even when sessions run in the background.
|
|
434
|
+
|
|
435
|
+
### Agent event triggers
|
|
436
|
+
|
|
437
|
+
When a session completes, an `openclaw system event` is fired with a summary of the session result, prompting the OpenClaw AI agent to process the output and relay it to the user.
|
|
438
|
+
|
|
439
|
+
When any session (single or multi-turn) becomes idle and waiting for input, an `openclaw system event` is also fired to wake the orchestrator. Idle detection uses end-of-turn detection (for multi-turn results) combined with a 15-second safety-net timer. A `waitingForInputFired` flag prevents duplicate wake events from being fired for the same idle period.
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Skill Example: Coding Agent Workflow
|
|
444
|
+
|
|
445
|
+
Claude Code Plugin is a **transparent transport layer** — it spawns sessions, streams output, and delivers notifications, but it has no opinion about *how* to orchestrate coding agents. Business logic lives in **OpenClaw skills**.
|
|
446
|
+
|
|
447
|
+
Here's an example skill that defines a coding agent workflow: it auto-responds to certain Claude questions and forwards others to the user.
|
|
448
|
+
|
|
449
|
+
### `coding-agent.skill.yaml`
|
|
450
|
+
|
|
451
|
+
```yaml
|
|
452
|
+
id: coding-agent
|
|
453
|
+
name: Coding Agent Orchestrator
|
|
454
|
+
description: >
|
|
455
|
+
Orchestrates Claude Code sessions with smart auto-response rules.
|
|
456
|
+
Automatically handles routine questions and forwards important decisions
|
|
457
|
+
to the user.
|
|
458
|
+
|
|
459
|
+
instructions: |
|
|
460
|
+
You are a coding agent orchestrator. You manage Claude Code sessions
|
|
461
|
+
via the claude-code plugin tools.
|
|
462
|
+
|
|
463
|
+
## Auto-response rules
|
|
464
|
+
|
|
465
|
+
When a Claude Code session asks a question (🔔 wake event), analyze the
|
|
466
|
+
question and decide whether to auto-respond or forward to the user:
|
|
467
|
+
|
|
468
|
+
### Auto-respond (use claude_respond immediately):
|
|
469
|
+
- Permission requests for file reads, writes, or bash commands
|
|
470
|
+
→ Respond: "Yes, proceed."
|
|
471
|
+
- Confirmation prompts like "Should I continue?" or "Do you want me to apply these changes?"
|
|
472
|
+
→ Respond: "Yes, continue."
|
|
473
|
+
- Questions about which approach to take when only one is reasonable
|
|
474
|
+
→ Respond with the obvious choice
|
|
475
|
+
- Requests for clarification about the codebase (file locations, conventions)
|
|
476
|
+
→ Respond with the info if you know it, or "Use your best judgment."
|
|
477
|
+
|
|
478
|
+
### Forward to user (relay the question to the chat):
|
|
479
|
+
- Architecture decisions (e.g. "Should I use Redis or PostgreSQL for caching?")
|
|
480
|
+
- Destructive operations (e.g. "Should I delete the old migration files?")
|
|
481
|
+
- Ambiguous requirements (e.g. "The spec doesn't mention error handling — what should I do?")
|
|
482
|
+
- Budget or scope changes (e.g. "This will require refactoring 15 files — should I proceed?")
|
|
483
|
+
- Anything involving credentials, secrets, or production environments
|
|
484
|
+
|
|
485
|
+
## Workflow
|
|
486
|
+
|
|
487
|
+
1. User sends a coding task → launch a multi-turn session:
|
|
488
|
+
claude_launch(prompt: "<task>", multi_turn: true, channel: "<origin>")
|
|
489
|
+
|
|
490
|
+
2. Session runs in background. Monitor via wake events.
|
|
491
|
+
|
|
492
|
+
3. On 🔔 wake event → read the question with claude_output, then:
|
|
493
|
+
- If auto-respond rule matches → claude_respond(session, answer)
|
|
494
|
+
- If forward rule matches → relay the question to the user
|
|
495
|
+
|
|
496
|
+
4. On user reply to a forwarded question → claude_respond with their answer
|
|
497
|
+
|
|
498
|
+
5. On ✅ completion → summarize the result and notify the user
|
|
499
|
+
|
|
500
|
+
## Important
|
|
501
|
+
|
|
502
|
+
- Always use multi_turn: true for tasks that may need follow-up
|
|
503
|
+
- Always pass the channel parameter to maintain notification routing
|
|
504
|
+
- Never auto-respond to questions about production deployments
|
|
505
|
+
- When in doubt, forward to the user — it's better to ask than to guess
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### How it works
|
|
509
|
+
|
|
510
|
+
This skill demonstrates the key architectural principle: **Claude Code Plugin provides the transport, skills provide the brain.**
|
|
511
|
+
|
|
512
|
+
| Layer | Responsibility |
|
|
513
|
+
|---|---|
|
|
514
|
+
| **Claude Code Plugin** (this plugin) | Spawn sessions, stream output, deliver `🔔`/`↩️` notifications, fire wake events |
|
|
515
|
+
| **Skill** (e.g. `coding-agent`) | Decide what to auto-respond, what to forward, how to summarize results |
|
|
516
|
+
| **User** | Receives forwarded questions, provides high-level instructions |
|
|
517
|
+
|
|
518
|
+
The same Claude Code Plugin plugin can power completely different workflows — a code review skill, a CI/CD skill, a documentation skill — simply by swapping the skill definition. The plugin itself remains a generic, reusable transport layer.
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
## Development
|
|
523
|
+
|
|
524
|
+
### Project Structure
|
|
525
|
+
|
|
526
|
+
```
|
|
527
|
+
claude-code/
|
|
528
|
+
├── index.ts # Plugin entry point (register function)
|
|
529
|
+
├── openclaw.plugin.json # Plugin manifest and config schema
|
|
530
|
+
├── package.json # Dependencies
|
|
531
|
+
├── src/
|
|
532
|
+
│ ├── types.ts # TypeScript interfaces
|
|
533
|
+
│ ├── shared.ts # Global state, helpers, formatting
|
|
534
|
+
│ ├── session.ts # Session class (SDK wrapper)
|
|
535
|
+
│ ├── session-manager.ts # Session pool management
|
|
536
|
+
│ ├── notifications.ts # NotificationRouter
|
|
537
|
+
│ ├── gateway.ts # RPC method registration
|
|
538
|
+
│ ├── tools/
|
|
539
|
+
│ │ ├── claude-launch.ts # claude_launch tool
|
|
540
|
+
│ │ ├── claude-sessions.ts # claude_sessions tool
|
|
541
|
+
│ │ ├── claude-output.ts # claude_output tool
|
|
542
|
+
│ │ ├── claude-fg.ts # claude_fg tool
|
|
543
|
+
│ │ ├── claude-bg.ts # claude_bg tool
|
|
544
|
+
│ │ ├── claude-kill.ts # claude_kill tool
|
|
545
|
+
│ │ ├── claude-respond.ts # claude_respond tool
|
|
546
|
+
│ │ └── claude-stats.ts # claude_stats tool
|
|
547
|
+
│ └── commands/
|
|
548
|
+
│ ├── claude.ts # /claude command
|
|
549
|
+
│ ├── claude-sessions.ts # /claude_sessions command
|
|
550
|
+
│ ├── claude-fg.ts # /claude_fg command
|
|
551
|
+
│ ├── claude-bg.ts # /claude_bg command
|
|
552
|
+
│ ├── claude-kill.ts # /claude_kill command
|
|
553
|
+
│ ├── claude-resume.ts # /claude_resume command
|
|
554
|
+
│ ├── claude-respond.ts # /claude_respond command
|
|
555
|
+
│ └── claude-stats.ts # /claude_stats command
|
|
556
|
+
└── docs/
|
|
557
|
+
└── plans/ # Design documents
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### Dependencies
|
|
561
|
+
|
|
562
|
+
| Package | Purpose |
|
|
563
|
+
|---|---|
|
|
564
|
+
| `@anthropic-ai/claude-agent-sdk` | Claude Code SDK — the `query()` function that powers each session. |
|
|
565
|
+
| `@sinclair/typebox` | JSON Schema type builder for tool parameter definitions. |
|
|
566
|
+
| `nanoid` | Generates short unique session IDs (8 characters). |
|
|
567
|
+
|
|
568
|
+
### Key design decisions
|
|
569
|
+
|
|
570
|
+
1. **Foreground is per-channel, not per-session.** Multiple channels can watch the same session simultaneously, and one channel can have multiple sessions in foreground.
|
|
571
|
+
|
|
572
|
+
2. **Multi-turn uses `AsyncIterable` prompts.** The `MessageStream` class implements `Symbol.asyncIterator` to feed user messages into the SDK's `query()` function as an async generator, keeping the session alive across turns.
|
|
573
|
+
|
|
574
|
+
3. **Persisted sessions survive GC.** When a session is garbage-collected (1 hour after completion), its Claude session ID is retained in a separate `persistedSessions` map so it can be resumed later. Entries are stored under three keys (internal ID, name, Claude UUID) for flexible lookup.
|
|
575
|
+
|
|
576
|
+
4. **Notifications use CLI shelling.** Since the plugin API doesn't expose a runtime `sendMessage` method, outbound notifications go through `openclaw message send` via `child_process.execFile`.
|
|
577
|
+
|
|
578
|
+
5. **Metrics are in-memory only.** Session metrics are aggregated in the `SessionManager` and reset on service restart. They are not persisted to disk. Cost data is tracked internally but not exposed in any user-facing output.
|
|
579
|
+
|
|
580
|
+
6. **Waiting-for-input uses dual detection.** End-of-turn detection (when a multi-turn result resolves) is the primary signal, backed by a 15-second safety-net timer for edge cases. A `waitingForInputFired` flag prevents duplicate wake events.
|
|
581
|
+
|
|
582
|
+
7. **Channel `"unknown"` falls through.** If `channelId` is `"unknown"`, the notification system explicitly falls through to `fallbackChannel` rather than attempting delivery to an invalid destination.
|
|
583
|
+
|
|
584
|
+
### Adding a new tool or command
|
|
585
|
+
|
|
586
|
+
1. Create a new file under `src/tools/` or `src/commands/`.
|
|
587
|
+
2. Export a `registerXxxTool(api)` or `registerXxxCommand(api)` function.
|
|
588
|
+
3. Import and call it in `index.ts` inside the `register()` function.
|
|
589
|
+
|
|
590
|
+
### Service lifecycle
|
|
591
|
+
|
|
592
|
+
- **`start()`** — Creates `SessionManager` and `NotificationRouter`, wires them together, starts the long-running reminder check interval (60s), and starts a GC interval (5 min).
|
|
593
|
+
- **`stop()`** — Stops the notification router, kills all active sessions, clears intervals, and nulls singletons.
|
|
594
|
+
|
|
595
|
+
---
|
|
596
|
+
|
|
597
|
+
## License
|
|
598
|
+
|
|
599
|
+
See the project repository for license information.
|