@protolabsai/proto 0.14.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/LICENSE +203 -0
- package/README.md +286 -0
- package/dist/bundled/adversarial-verification/SKILL.md +98 -0
- package/dist/bundled/brainstorming/SKILL.md +171 -0
- package/dist/bundled/coding-agent-standards/SKILL.md +67 -0
- package/dist/bundled/dispatching-parallel-agents/SKILL.md +193 -0
- package/dist/bundled/executing-plans/SKILL.md +77 -0
- package/dist/bundled/finishing-a-development-branch/SKILL.md +213 -0
- package/dist/bundled/loop/SKILL.md +61 -0
- package/dist/bundled/qc-helper/SKILL.md +151 -0
- package/dist/bundled/qc-helper/docs/_meta.ts +30 -0
- package/dist/bundled/qc-helper/docs/common-workflow.md +571 -0
- package/dist/bundled/qc-helper/docs/configuration/_meta.ts +10 -0
- package/dist/bundled/qc-helper/docs/configuration/auth.md +366 -0
- package/dist/bundled/qc-helper/docs/configuration/memory.md +0 -0
- package/dist/bundled/qc-helper/docs/configuration/model-providers.md +542 -0
- package/dist/bundled/qc-helper/docs/configuration/qwen-ignore.md +55 -0
- package/dist/bundled/qc-helper/docs/configuration/settings.md +652 -0
- package/dist/bundled/qc-helper/docs/configuration/themes.md +160 -0
- package/dist/bundled/qc-helper/docs/configuration/trusted-folders.md +61 -0
- package/dist/bundled/qc-helper/docs/extension/_meta.ts +9 -0
- package/dist/bundled/qc-helper/docs/extension/extension-releasing.md +121 -0
- package/dist/bundled/qc-helper/docs/extension/getting-started-extensions.md +299 -0
- package/dist/bundled/qc-helper/docs/extension/introduction.md +303 -0
- package/dist/bundled/qc-helper/docs/features/_meta.ts +18 -0
- package/dist/bundled/qc-helper/docs/features/approval-mode.md +263 -0
- package/dist/bundled/qc-helper/docs/features/arena.md +218 -0
- package/dist/bundled/qc-helper/docs/features/checkpointing.md +77 -0
- package/dist/bundled/qc-helper/docs/features/commands.md +312 -0
- package/dist/bundled/qc-helper/docs/features/headless.md +318 -0
- package/dist/bundled/qc-helper/docs/features/hooks.md +343 -0
- package/dist/bundled/qc-helper/docs/features/language.md +139 -0
- package/dist/bundled/qc-helper/docs/features/lsp.md +453 -0
- package/dist/bundled/qc-helper/docs/features/mcp.md +281 -0
- package/dist/bundled/qc-helper/docs/features/sandbox.md +241 -0
- package/dist/bundled/qc-helper/docs/features/scheduled-tasks.md +139 -0
- package/dist/bundled/qc-helper/docs/features/skills.md +289 -0
- package/dist/bundled/qc-helper/docs/features/sub-agents.md +307 -0
- package/dist/bundled/qc-helper/docs/features/token-caching.md +29 -0
- package/dist/bundled/qc-helper/docs/ide-integration/_meta.ts +4 -0
- package/dist/bundled/qc-helper/docs/ide-integration/ide-companion-spec.md +182 -0
- package/dist/bundled/qc-helper/docs/ide-integration/ide-integration.md +144 -0
- package/dist/bundled/qc-helper/docs/integration-github-action.md +241 -0
- package/dist/bundled/qc-helper/docs/integration-jetbrains.md +81 -0
- package/dist/bundled/qc-helper/docs/integration-vscode.md +39 -0
- package/dist/bundled/qc-helper/docs/integration-zed.md +72 -0
- package/dist/bundled/qc-helper/docs/overview.md +64 -0
- package/dist/bundled/qc-helper/docs/quickstart.md +273 -0
- package/dist/bundled/qc-helper/docs/reference/_meta.ts +4 -0
- package/dist/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +72 -0
- package/dist/bundled/qc-helper/docs/reference/sdk-api.md +524 -0
- package/dist/bundled/qc-helper/docs/support/Uninstall.md +42 -0
- package/dist/bundled/qc-helper/docs/support/_meta.ts +6 -0
- package/dist/bundled/qc-helper/docs/support/tos-privacy.md +112 -0
- package/dist/bundled/qc-helper/docs/support/troubleshooting.md +123 -0
- package/dist/bundled/receiving-code-review/SKILL.md +226 -0
- package/dist/bundled/requesting-code-review/SKILL.md +115 -0
- package/dist/bundled/review/SKILL.md +123 -0
- package/dist/bundled/subagent-driven-development/SKILL.md +292 -0
- package/dist/bundled/subagent-driven-development/code-quality-reviewer-prompt.md +27 -0
- package/dist/bundled/subagent-driven-development/implementer-prompt.md +113 -0
- package/dist/bundled/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/dist/bundled/systematic-debugging/SKILL.md +305 -0
- package/dist/bundled/test-driven-development/SKILL.md +396 -0
- package/dist/bundled/using-git-worktrees/SKILL.md +223 -0
- package/dist/bundled/using-superpowers/SKILL.md +117 -0
- package/dist/bundled/verification-before-completion/SKILL.md +147 -0
- package/dist/bundled/writing-plans/SKILL.md +159 -0
- package/dist/bundled/writing-skills/SKILL.md +716 -0
- package/dist/cli.js +483432 -0
- package/dist/sandbox-macos-permissive-closed.sb +32 -0
- package/dist/sandbox-macos-permissive-open.sb +27 -0
- package/dist/sandbox-macos-permissive-proxied.sb +37 -0
- package/dist/sandbox-macos-restrictive-closed.sb +93 -0
- package/dist/sandbox-macos-restrictive-open.sb +96 -0
- package/dist/sandbox-macos-restrictive-proxied.sb +98 -0
- package/dist/vendor/ripgrep/COPYING +3 -0
- package/dist/vendor/ripgrep/arm64-darwin/rg +0 -0
- package/dist/vendor/ripgrep/arm64-linux/rg +0 -0
- package/dist/vendor/ripgrep/x64-darwin/rg +0 -0
- package/dist/vendor/ripgrep/x64-linux/rg +0 -0
- package/dist/vendor/ripgrep/x64-win32/rg.exe +0 -0
- package/dist/vendor/tree-sitter/tree-sitter-bash.wasm +0 -0
- package/dist/vendor/tree-sitter/tree-sitter.wasm +0 -0
- package/package.json +143 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
# Headless Mode
|
|
2
|
+
|
|
3
|
+
Headless mode allows you to run Qwen Code programmatically from command line
|
|
4
|
+
scripts and automation tools without any interactive UI. This is ideal for
|
|
5
|
+
scripting, automation, CI/CD pipelines, and building AI-powered tools.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The headless mode provides a headless interface to Qwen Code that:
|
|
10
|
+
|
|
11
|
+
- Accepts prompts via command line arguments or stdin
|
|
12
|
+
- Returns structured output (text or JSON)
|
|
13
|
+
- Supports file redirection and piping
|
|
14
|
+
- Enables automation and scripting workflows
|
|
15
|
+
- Provides consistent exit codes for error handling
|
|
16
|
+
- Can resume previous sessions scoped to the current project for multi-step automation
|
|
17
|
+
|
|
18
|
+
## Basic Usage
|
|
19
|
+
|
|
20
|
+
### Direct Prompts
|
|
21
|
+
|
|
22
|
+
Use the `--prompt` (or `-p`) flag to run in headless mode:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
qwen --prompt "What is machine learning?"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Stdin Input
|
|
29
|
+
|
|
30
|
+
Pipe input to Qwen Code from your terminal:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
echo "Explain this code" | qwen
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Combining with File Input
|
|
37
|
+
|
|
38
|
+
Read from files and process with Qwen Code:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
cat README.md | qwen --prompt "Summarize this documentation"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Resume Previous Sessions (Headless)
|
|
45
|
+
|
|
46
|
+
Reuse conversation context from the current project in headless scripts:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Continue the most recent session for this project and run a new prompt
|
|
50
|
+
qwen --continue -p "Run the tests again and summarize failures"
|
|
51
|
+
|
|
52
|
+
# Resume a specific session ID directly (no UI)
|
|
53
|
+
qwen --resume 123e4567-e89b-12d3-a456-426614174000 -p "Apply the follow-up refactor"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> [!note]
|
|
57
|
+
>
|
|
58
|
+
> - Session data is project-scoped JSONL under `~/.qwen/projects/<sanitized-cwd>/chats`.
|
|
59
|
+
> - Restores conversation history, tool outputs, and chat-compression checkpoints before sending the new prompt.
|
|
60
|
+
|
|
61
|
+
## Customize the Main Session Prompt
|
|
62
|
+
|
|
63
|
+
You can change the main session system prompt for a single CLI run without editing shared memory files.
|
|
64
|
+
|
|
65
|
+
### Override the Built-in System Prompt
|
|
66
|
+
|
|
67
|
+
Use `--system-prompt` to replace Qwen Code's built-in main-session prompt for the current run:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
qwen -p "Review this patch" --system-prompt "You are a terse release reviewer. Report only blocking issues."
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Append Extra Instructions
|
|
74
|
+
|
|
75
|
+
Use `--append-system-prompt` to keep the built-in prompt and add extra instructions for this run:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
qwen -p "Review this patch" --append-system-prompt "Be terse and focus on concrete findings."
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
You can combine both flags when you want a custom base prompt plus an extra run-specific instruction:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
qwen -p "Summarize this repository" \
|
|
85
|
+
--system-prompt "You are a migration planner." \
|
|
86
|
+
--append-system-prompt "Return exactly three bullets."
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
> [!note]
|
|
90
|
+
>
|
|
91
|
+
> - `--system-prompt` applies only to the current run's main session.
|
|
92
|
+
> - Loaded memory and context files such as `QWEN.md` are still appended after `--system-prompt`.
|
|
93
|
+
> - `--append-system-prompt` is applied after the built-in prompt and loaded memory, and can be used together with `--system-prompt`.
|
|
94
|
+
|
|
95
|
+
## Output Formats
|
|
96
|
+
|
|
97
|
+
Qwen Code supports multiple output formats for different use cases:
|
|
98
|
+
|
|
99
|
+
### Text Output (Default)
|
|
100
|
+
|
|
101
|
+
Standard human-readable output:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
qwen -p "What is the capital of France?"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Response format:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
The capital of France is Paris.
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### JSON Output
|
|
114
|
+
|
|
115
|
+
Returns structured data as a JSON array. All messages are buffered and output together when the session completes. This format is ideal for programmatic processing and automation scripts.
|
|
116
|
+
|
|
117
|
+
The JSON output is an array of message objects. The output includes multiple message types: system messages (session initialization), assistant messages (AI responses), and result messages (execution summary).
|
|
118
|
+
|
|
119
|
+
#### Example Usage
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
qwen -p "What is the capital of France?" --output-format json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Output (at end of execution):
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
[
|
|
129
|
+
{
|
|
130
|
+
"type": "system",
|
|
131
|
+
"subtype": "session_start",
|
|
132
|
+
"uuid": "...",
|
|
133
|
+
"session_id": "...",
|
|
134
|
+
"model": "qwen3-coder-plus",
|
|
135
|
+
...
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"type": "assistant",
|
|
139
|
+
"uuid": "...",
|
|
140
|
+
"session_id": "...",
|
|
141
|
+
"message": {
|
|
142
|
+
"id": "...",
|
|
143
|
+
"type": "message",
|
|
144
|
+
"role": "assistant",
|
|
145
|
+
"model": "qwen3-coder-plus",
|
|
146
|
+
"content": [
|
|
147
|
+
{
|
|
148
|
+
"type": "text",
|
|
149
|
+
"text": "The capital of France is Paris."
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"usage": {...}
|
|
153
|
+
},
|
|
154
|
+
"parent_tool_use_id": null
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"type": "result",
|
|
158
|
+
"subtype": "success",
|
|
159
|
+
"uuid": "...",
|
|
160
|
+
"session_id": "...",
|
|
161
|
+
"is_error": false,
|
|
162
|
+
"duration_ms": 1234,
|
|
163
|
+
"result": "The capital of France is Paris.",
|
|
164
|
+
"usage": {...}
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Stream-JSON Output
|
|
170
|
+
|
|
171
|
+
Stream-JSON format emits JSON messages immediately as they occur during execution, enabling real-time monitoring. This format uses line-delimited JSON where each message is a complete JSON object on a single line.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
qwen -p "Explain TypeScript" --output-format stream-json
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Output (streaming as events occur):
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{"type":"system","subtype":"session_start","uuid":"...","session_id":"..."}
|
|
181
|
+
{"type":"assistant","uuid":"...","session_id":"...","message":{...}}
|
|
182
|
+
{"type":"result","subtype":"success","uuid":"...","session_id":"..."}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
When combined with `--include-partial-messages`, additional stream events are emitted in real-time (message_start, content_block_delta, etc.) for real-time UI updates.
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
qwen -p "Write a Python script" --output-format stream-json --include-partial-messages
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Input Format
|
|
192
|
+
|
|
193
|
+
The `--input-format` parameter controls how Qwen Code consumes input from standard input:
|
|
194
|
+
|
|
195
|
+
- **`text`** (default): Standard text input from stdin or command-line arguments
|
|
196
|
+
- **`stream-json`**: JSON message protocol via stdin for bidirectional communication
|
|
197
|
+
|
|
198
|
+
> **Note:** Stream-json input mode is currently under construction and is intended for SDK integration. It requires `--output-format stream-json` to be set.
|
|
199
|
+
|
|
200
|
+
### File Redirection
|
|
201
|
+
|
|
202
|
+
Save output to files or pipe to other commands:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Save to file
|
|
206
|
+
qwen -p "Explain Docker" > docker-explanation.txt
|
|
207
|
+
qwen -p "Explain Docker" --output-format json > docker-explanation.json
|
|
208
|
+
|
|
209
|
+
# Append to file
|
|
210
|
+
qwen -p "Add more details" >> docker-explanation.txt
|
|
211
|
+
|
|
212
|
+
# Pipe to other tools
|
|
213
|
+
qwen -p "What is Kubernetes?" --output-format json | jq '.response'
|
|
214
|
+
qwen -p "Explain microservices" | wc -w
|
|
215
|
+
qwen -p "List programming languages" | grep -i "python"
|
|
216
|
+
|
|
217
|
+
# Stream-JSON output for real-time processing
|
|
218
|
+
qwen -p "Explain Docker" --output-format stream-json | jq '.type'
|
|
219
|
+
qwen -p "Write code" --output-format stream-json --include-partial-messages | jq '.event.type'
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Configuration Options
|
|
223
|
+
|
|
224
|
+
Key command-line options for headless usage:
|
|
225
|
+
|
|
226
|
+
| Option | Description | Example |
|
|
227
|
+
| ---------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
|
|
228
|
+
| `--prompt`, `-p` | Run in headless mode | `qwen -p "query"` |
|
|
229
|
+
| `--output-format`, `-o` | Specify output format (text, json, stream-json) | `qwen -p "query" --output-format json` |
|
|
230
|
+
| `--input-format` | Specify input format (text, stream-json) | `qwen --input-format text --output-format stream-json` |
|
|
231
|
+
| `--include-partial-messages` | Include partial messages in stream-json output | `qwen -p "query" --output-format stream-json --include-partial-messages` |
|
|
232
|
+
| `--system-prompt` | Override the main session system prompt for this run | `qwen -p "query" --system-prompt "You are a terse reviewer."` |
|
|
233
|
+
| `--append-system-prompt` | Append extra instructions to the main session system prompt for this run | `qwen -p "query" --append-system-prompt "Focus on concrete findings."` |
|
|
234
|
+
| `--debug`, `-d` | Enable debug mode | `qwen -p "query" --debug` |
|
|
235
|
+
| `--all-files`, `-a` | Include all files in context | `qwen -p "query" --all-files` |
|
|
236
|
+
| `--include-directories` | Include additional directories | `qwen -p "query" --include-directories src,docs` |
|
|
237
|
+
| `--yolo`, `-y` | Auto-approve all actions | `qwen -p "query" --yolo` |
|
|
238
|
+
| `--approval-mode` | Set approval mode | `qwen -p "query" --approval-mode auto_edit` |
|
|
239
|
+
| `--continue` | Resume the most recent session for this project | `qwen --continue -p "Pick up where we left off"` |
|
|
240
|
+
| `--resume [sessionId]` | Resume a specific session (or choose interactively) | `qwen --resume 123e... -p "Finish the refactor"` |
|
|
241
|
+
|
|
242
|
+
For complete details on all available configuration options, settings files, and environment variables, see the [Configuration Guide](../configuration/settings).
|
|
243
|
+
|
|
244
|
+
## Examples
|
|
245
|
+
|
|
246
|
+
### Code review
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
cat src/auth.py | qwen -p "Review this authentication code for security issues" > security-review.txt
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Generate commit messages
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
result=$(git diff --cached | qwen -p "Write a concise commit message for these changes" --output-format json)
|
|
256
|
+
echo "$result" | jq -r '.response'
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### API documentation
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
result=$(cat api/routes.js | qwen -p "Generate OpenAPI spec for these routes" --output-format json)
|
|
263
|
+
echo "$result" | jq -r '.response' > openapi.json
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Batch code analysis
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
for file in src/*.py; do
|
|
270
|
+
echo "Analyzing $file..."
|
|
271
|
+
result=$(cat "$file" | qwen -p "Find potential bugs and suggest improvements" --output-format json)
|
|
272
|
+
echo "$result" | jq -r '.response' > "reports/$(basename "$file").analysis"
|
|
273
|
+
echo "Completed analysis for $(basename "$file")" >> reports/progress.log
|
|
274
|
+
done
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### PR code review
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
result=$(git diff origin/main...HEAD | qwen -p "Review these changes for bugs, security issues, and code quality" --output-format json)
|
|
281
|
+
echo "$result" | jq -r '.response' > pr-review.json
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Log analysis
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
grep "ERROR" /var/log/app.log | tail -20 | qwen -p "Analyze these errors and suggest root cause and fixes" > error-analysis.txt
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Release notes generation
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
result=$(git log --oneline v1.0.0..HEAD | qwen -p "Generate release notes from these commits" --output-format json)
|
|
294
|
+
response=$(echo "$result" | jq -r '.response')
|
|
295
|
+
echo "$response"
|
|
296
|
+
echo "$response" >> CHANGELOG.md
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Model and tool usage tracking
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
result=$(qwen -p "Explain this database schema" --include-directories db --output-format json)
|
|
303
|
+
total_tokens=$(echo "$result" | jq -r '.stats.models // {} | to_entries | map(.value.tokens.total) | add // 0')
|
|
304
|
+
models_used=$(echo "$result" | jq -r '.stats.models // {} | keys | join(", ") | if . == "" then "none" else . end')
|
|
305
|
+
tool_calls=$(echo "$result" | jq -r '.stats.tools.totalCalls // 0')
|
|
306
|
+
tools_used=$(echo "$result" | jq -r '.stats.tools.byName // {} | keys | join(", ") | if . == "" then "none" else . end')
|
|
307
|
+
echo "$(date): $total_tokens tokens, $tool_calls tool calls ($tools_used) used with models: $models_used" >> usage.log
|
|
308
|
+
echo "$result" | jq -r '.response' > schema-docs.md
|
|
309
|
+
echo "Recent usage trends:"
|
|
310
|
+
tail -5 usage.log
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Resources
|
|
314
|
+
|
|
315
|
+
- [CLI Configuration](../configuration/settings#command-line-arguments) - Complete configuration guide
|
|
316
|
+
- [Authentication](../configuration/settings#environment-variables-for-api-access) - Setup authentication
|
|
317
|
+
- [Commands](../features/commands) - Interactive commands reference
|
|
318
|
+
- [Tutorials](../quickstart) - Step-by-step automation guides
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# Hooks
|
|
2
|
+
|
|
3
|
+
Run custom scripts at key points in the proto lifecycle — before tool calls, after edits, at session boundaries, and during agent team coordination.
|
|
4
|
+
|
|
5
|
+
This page covers how to configure hooks, the available hook types and events, and the input/output contract for each event.
|
|
6
|
+
|
|
7
|
+
## Configure a hook
|
|
8
|
+
|
|
9
|
+
Hooks are defined in `.proto/settings.json` (project) or `~/.proto/settings.json` (global). Each hook attaches to an event name and optionally filters by a matcher pattern.
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"hooks": {
|
|
14
|
+
"PreToolUse": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "^bash$",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "./scripts/check-bash-safety.sh",
|
|
21
|
+
"timeout": 10000
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Hook types
|
|
31
|
+
|
|
32
|
+
| Type | Purpose | Key fields |
|
|
33
|
+
| --------- | ------------------------------------------------------------- | ---------------------------------- |
|
|
34
|
+
| `command` | Run a shell script. Event JSON on stdin, decisions on stdout. | `command`, `env`, `timeout` |
|
|
35
|
+
| `http` | POST event JSON to a webhook URL. | `url`, `headers`, `allowedEnvVars` |
|
|
36
|
+
| `prompt` | Ask an LLM to make a judgment call. | `prompt`, `model` |
|
|
37
|
+
|
|
38
|
+
#### Command hooks
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"type": "command",
|
|
43
|
+
"command": "/path/to/script.sh",
|
|
44
|
+
"timeout": 30000,
|
|
45
|
+
"env": { "CUSTOM_VAR": "value" }
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### HTTP hooks
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"type": "http",
|
|
54
|
+
"url": "https://hooks.example.com/proto",
|
|
55
|
+
"headers": { "Authorization": "Bearer $API_TOKEN" },
|
|
56
|
+
"allowedEnvVars": ["API_TOKEN"]
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Only variables listed in `allowedEnvVars` are interpolated in `url` and `headers`. Other `$VAR` references resolve to empty string.
|
|
61
|
+
|
|
62
|
+
#### Prompt hooks
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"type": "prompt",
|
|
67
|
+
"prompt": "Is this safe? Event: $ARGUMENTS. Respond with JSON: {\"decision\": \"allow\"} or {\"decision\": \"deny\", \"reason\": \"why\"}",
|
|
68
|
+
"model": "haiku"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`$ARGUMENTS` is replaced with the event JSON. Model options: `haiku` (default), `sonnet`, `opus`.
|
|
73
|
+
|
|
74
|
+
### Hook modifiers
|
|
75
|
+
|
|
76
|
+
**`async`** — Run the hook in the background without blocking. Output and decisions are ignored.
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{ "type": "command", "command": "log-to-slack.sh", "async": true }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**`if`** — Fine-grained filter using permission-rule syntax. Only fires when tool arguments match the pattern. Avoids spawning a hook process for non-matching calls.
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"matcher": "bash",
|
|
87
|
+
"hooks": [
|
|
88
|
+
{ "type": "command", "if": "Bash(git *)", "command": "check-git-policy.sh" }
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Syntax: `ToolName(glob)` where the glob matches the tool's primary argument (`command` for Bash, `file_path` for Edit/Write, `pattern` for Grep). Valid only for tool events.
|
|
94
|
+
|
|
95
|
+
## Events reference
|
|
96
|
+
|
|
97
|
+
### Lifecycle events
|
|
98
|
+
|
|
99
|
+
| Event | When it fires | Can block? |
|
|
100
|
+
| ------------------ | ---------------------------------------- | -------------------- |
|
|
101
|
+
| `SessionStart` | Session begins or resumes | No |
|
|
102
|
+
| `SessionEnd` | Session terminates | No |
|
|
103
|
+
| `PreCompact` | Before context compaction | No |
|
|
104
|
+
| `UserPromptSubmit` | User submits a prompt, before processing | Yes (exit 2) |
|
|
105
|
+
| `Stop` | Before the model concludes its response | Yes (exit 2 or JSON) |
|
|
106
|
+
|
|
107
|
+
### Tool events
|
|
108
|
+
|
|
109
|
+
| Event | When it fires | Can block? | Matcher target |
|
|
110
|
+
| -------------------- | ----------------------- | ---------- | ----------------- |
|
|
111
|
+
| `PreToolUse` | Before tool executes | Yes | Tool name (regex) |
|
|
112
|
+
| `PostToolUse` | After tool succeeds | Limited | Tool name (regex) |
|
|
113
|
+
| `PostToolUseFailure` | After tool fails | Limited | Tool name (regex) |
|
|
114
|
+
| `PermissionRequest` | Permission dialog shown | Yes | Tool name (regex) |
|
|
115
|
+
|
|
116
|
+
### Agent events
|
|
117
|
+
|
|
118
|
+
| Event | When it fires | Matcher target |
|
|
119
|
+
| --------------- | ----------------- | ------------------ |
|
|
120
|
+
| `SubagentStart` | Subagent spawned | Agent type (regex) |
|
|
121
|
+
| `SubagentStop` | Subagent finishes | Agent type (regex) |
|
|
122
|
+
|
|
123
|
+
### Team events
|
|
124
|
+
|
|
125
|
+
| Event | When it fires | Can block? |
|
|
126
|
+
| --------------- | ------------------------------ | --------------------------- |
|
|
127
|
+
| `TeammateIdle` | Background agent becomes idle | Yes (exit 2 sends feedback) |
|
|
128
|
+
| `TaskCreated` | Task added to shared task list | No |
|
|
129
|
+
| `TaskCompleted` | Task marked as completed | No |
|
|
130
|
+
|
|
131
|
+
### Notification events
|
|
132
|
+
|
|
133
|
+
| Event | When it fires | Matcher target |
|
|
134
|
+
| -------------- | ----------------- | -------------------------------------------------------- |
|
|
135
|
+
| `Notification` | Notification sent | Type: `permission_prompt`, `idle_prompt`, `auth_success` |
|
|
136
|
+
|
|
137
|
+
## Input/output contract
|
|
138
|
+
|
|
139
|
+
### Common input fields (all events)
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"session_id": "string",
|
|
144
|
+
"transcript_path": "string",
|
|
145
|
+
"cwd": "string",
|
|
146
|
+
"hook_event_name": "string",
|
|
147
|
+
"timestamp": "ISO 8601 string"
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Exit codes (command hooks)
|
|
152
|
+
|
|
153
|
+
| Exit code | Meaning | Behavior |
|
|
154
|
+
| --------- | ------------------ | ------------------------------------------------- |
|
|
155
|
+
| `0` | Success | Parse stdout as JSON for decisions |
|
|
156
|
+
| `1` | Non-blocking error | Continue; stderr logged but not shown to model |
|
|
157
|
+
| `2` | Blocking error | Block the action; stderr fed to model as feedback |
|
|
158
|
+
|
|
159
|
+
### JSON output format
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"continue": true,
|
|
164
|
+
"decision": "allow",
|
|
165
|
+
"reason": "explanation",
|
|
166
|
+
"hookSpecificOutput": {}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Event-specific fields
|
|
171
|
+
|
|
172
|
+
#### PreToolUse
|
|
173
|
+
|
|
174
|
+
**Additional input:** `permission_mode`, `tool_name`, `tool_input`, `tool_use_id`
|
|
175
|
+
|
|
176
|
+
**Output:** `hookSpecificOutput.permissionDecision` (`allow` | `deny` | `ask`), `hookSpecificOutput.permissionDecisionReason`, `hookSpecificOutput.updatedInput`
|
|
177
|
+
|
|
178
|
+
#### PostToolUse
|
|
179
|
+
|
|
180
|
+
**Additional input:** `permission_mode`, `tool_name`, `tool_input`, `tool_response`, `tool_use_id`
|
|
181
|
+
|
|
182
|
+
**Output:** `decision` (`allow` | `block`), `hookSpecificOutput.additionalContext`
|
|
183
|
+
|
|
184
|
+
#### PostToolUseFailure
|
|
185
|
+
|
|
186
|
+
**Additional input:** `permission_mode`, `tool_use_id`, `tool_name`, `tool_input`, `error`, `is_interrupt`
|
|
187
|
+
|
|
188
|
+
#### UserPromptSubmit
|
|
189
|
+
|
|
190
|
+
**Additional input:** `prompt`
|
|
191
|
+
|
|
192
|
+
**Output:** `decision` (`allow` | `block`), `hookSpecificOutput.additionalContext`
|
|
193
|
+
|
|
194
|
+
#### Stop
|
|
195
|
+
|
|
196
|
+
**Additional input:** `stop_hook_active`, `last_assistant_message`
|
|
197
|
+
|
|
198
|
+
**Output:** `decision` (`allow` | `block`), `reason`
|
|
199
|
+
|
|
200
|
+
When `stop_hook_active` is `true`, the hook has already triggered a continuation. Exit early to prevent infinite loops.
|
|
201
|
+
|
|
202
|
+
#### SessionStart
|
|
203
|
+
|
|
204
|
+
**Additional input:** `permission_mode`, `source` (`startup` | `resume` | `clear` | `compact`), `model`, `agent_type`
|
|
205
|
+
|
|
206
|
+
**Output:** `hookSpecificOutput.additionalContext` (injected into session context)
|
|
207
|
+
|
|
208
|
+
#### SessionEnd
|
|
209
|
+
|
|
210
|
+
**Additional input:** `reason` (`clear` | `logout` | `prompt_input_exit` | `other`)
|
|
211
|
+
|
|
212
|
+
#### SubagentStart / SubagentStop
|
|
213
|
+
|
|
214
|
+
**Additional input:** `permission_mode`, `agent_id`, `agent_type`
|
|
215
|
+
|
|
216
|
+
SubagentStop also includes: `stop_hook_active`, `agent_transcript_path`, `last_assistant_message`
|
|
217
|
+
|
|
218
|
+
#### PermissionRequest
|
|
219
|
+
|
|
220
|
+
**Additional input:** `permission_mode`, `tool_name`, `tool_input`, `permission_suggestions`
|
|
221
|
+
|
|
222
|
+
**Output:** `hookSpecificOutput.decision.behavior` (`allow` | `deny`), `hookSpecificOutput.decision.updatedInput`, `hookSpecificOutput.decision.message`
|
|
223
|
+
|
|
224
|
+
#### PreCompact
|
|
225
|
+
|
|
226
|
+
**Additional input:** `trigger` (`manual` | `auto`), `custom_instructions`
|
|
227
|
+
|
|
228
|
+
#### TeammateIdle
|
|
229
|
+
|
|
230
|
+
**Additional input:** `agent_id`, `agent_name`, `result_summary`, `success`
|
|
231
|
+
|
|
232
|
+
#### TaskCreated
|
|
233
|
+
|
|
234
|
+
**Additional input:** `task_id`, `task_title`, `task_description`, `created_by`
|
|
235
|
+
|
|
236
|
+
#### TaskCompleted
|
|
237
|
+
|
|
238
|
+
**Additional input:** `task_id`, `task_title`, `completed_by`, `output`
|
|
239
|
+
|
|
240
|
+
## Matcher patterns
|
|
241
|
+
|
|
242
|
+
Matchers are regex patterns that filter which occurrences of an event trigger a hook.
|
|
243
|
+
|
|
244
|
+
| Event type | Matches on | Example |
|
|
245
|
+
| ---------------------- | --------------- | ---------------------------------- |
|
|
246
|
+
| Tool events | Tool name | `^bash$`, `read.*`, `(bash\|edit)` |
|
|
247
|
+
| Subagent events | Agent type | `^Explore$`, `coordinator` |
|
|
248
|
+
| SessionStart | Source | `^(startup\|resume)$` |
|
|
249
|
+
| SessionEnd | Reason | `^clear$` |
|
|
250
|
+
| Notification | Type (exact) | `permission_prompt` |
|
|
251
|
+
| PreCompact | Trigger (exact) | `manual` |
|
|
252
|
+
| UserPromptSubmit, Stop | Not supported | Always fires |
|
|
253
|
+
|
|
254
|
+
Empty string `""` or `"*"` matches all.
|
|
255
|
+
|
|
256
|
+
## Execution model
|
|
257
|
+
|
|
258
|
+
- Hooks run **in parallel** by default. Use `sequential: true` on a hook definition to enforce order.
|
|
259
|
+
- When multiple hooks return conflicting decisions, the **most restrictive wins**: `deny` > `ask` > `allow`.
|
|
260
|
+
- Project hooks require trusted folder status.
|
|
261
|
+
- Default timeout: 60 seconds.
|
|
262
|
+
- Max output: 1 MB per hook.
|
|
263
|
+
|
|
264
|
+
## SDK hook callbacks
|
|
265
|
+
|
|
266
|
+
When using the [TypeScript SDK](../reference/sdk-api.md), register hook callbacks directly in code instead of writing shell scripts or HTTP endpoints. The SDK registers callbacks with the CLI during initialization and invokes them when hook events fire.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { query, type HookCallback } from '@qwen-code/sdk';
|
|
270
|
+
|
|
271
|
+
const auditLogger: HookCallback = async (input, toolUseId) => {
|
|
272
|
+
const data = input as { tool_name?: string };
|
|
273
|
+
console.log(`[audit] ${data.tool_name} (${toolUseId})`);
|
|
274
|
+
return {};
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const securityGate: HookCallback = async (input) => {
|
|
278
|
+
const data = input as {
|
|
279
|
+
tool_name?: string;
|
|
280
|
+
tool_input?: Record<string, unknown>;
|
|
281
|
+
};
|
|
282
|
+
if (data.tool_name === 'Bash') {
|
|
283
|
+
const cmd = String(data.tool_input?.command ?? '');
|
|
284
|
+
if (cmd.includes('rm -rf') || cmd.includes('sudo')) {
|
|
285
|
+
return { shouldSkip: true, message: 'Blocked: destructive command' };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return {};
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const conversation = query({
|
|
292
|
+
prompt: 'Refactor the auth module',
|
|
293
|
+
options: {
|
|
294
|
+
hookCallbacks: {
|
|
295
|
+
PreToolUse: [auditLogger, securityGate],
|
|
296
|
+
PostToolUse: async (input) => {
|
|
297
|
+
const data = input as { tool_output?: string };
|
|
298
|
+
if (data.tool_output?.includes('FATAL')) {
|
|
299
|
+
return { shouldInterrupt: true, message: 'Fatal error detected' };
|
|
300
|
+
}
|
|
301
|
+
return {};
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Callback return values
|
|
309
|
+
|
|
310
|
+
| Field | Type | Effect |
|
|
311
|
+
| ----------------- | --------- | --------------------------------------------------------------- |
|
|
312
|
+
| `shouldSkip` | `boolean` | Skip this tool call entirely. Only meaningful for `PreToolUse`. |
|
|
313
|
+
| `shouldInterrupt` | `boolean` | Stop the agent immediately. |
|
|
314
|
+
| `suppressOutput` | `boolean` | Suppress the tool's output from the conversation. |
|
|
315
|
+
| `message` | `string` | Feedback string sent to the agent. |
|
|
316
|
+
|
|
317
|
+
Returning `{}` lets the tool proceed normally.
|
|
318
|
+
|
|
319
|
+
### Supported SDK events
|
|
320
|
+
|
|
321
|
+
| Event | When it fires |
|
|
322
|
+
| -------------- | ------------------------------- |
|
|
323
|
+
| `PreToolUse` | Before a tool executes |
|
|
324
|
+
| `PostToolUse` | After a tool returns its result |
|
|
325
|
+
| `Stop` | When the agent is about to stop |
|
|
326
|
+
| `Notification` | On agent notifications |
|
|
327
|
+
| `SubagentStop` | When a subagent finishes |
|
|
328
|
+
|
|
329
|
+
When multiple callbacks are registered for one event (as an array), they execute in order. The first `shouldSkip` or `shouldInterrupt` result short-circuits the rest.
|
|
330
|
+
|
|
331
|
+
See the [SDK hooks examples](../../developers/examples/sdk-hooks.md) for more patterns.
|
|
332
|
+
|
|
333
|
+
## Environment variables
|
|
334
|
+
|
|
335
|
+
Command hooks inherit `process.env` plus:
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
GEMINI_PROJECT_DIR — project root
|
|
339
|
+
CLAUDE_PROJECT_DIR — same (compatibility alias)
|
|
340
|
+
QWEN_PROJECT_DIR — same (compatibility alias)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Custom variables can be added via the `env` field on command hooks.
|