@mmmbuto/qwen-code-termux 0.14.1-termux → 0.15.5-termux

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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/bundled/batch/SKILL.md +304 -0
  3. package/bundled/loop/SKILL.md +1 -0
  4. package/bundled/qc-helper/SKILL.md +1 -0
  5. package/bundled/qc-helper/docs/configuration/auth.md +13 -6
  6. package/bundled/qc-helper/docs/configuration/settings.md +173 -108
  7. package/bundled/qc-helper/docs/features/_meta.ts +6 -0
  8. package/bundled/qc-helper/docs/features/approval-mode.md +16 -8
  9. package/bundled/qc-helper/docs/features/arena.md +3 -2
  10. package/bundled/qc-helper/docs/features/code-review.md +279 -0
  11. package/bundled/qc-helper/docs/features/commands.md +96 -26
  12. package/bundled/qc-helper/docs/features/dual-output.md +593 -0
  13. package/bundled/qc-helper/docs/features/followup-suggestions.md +6 -6
  14. package/bundled/qc-helper/docs/features/headless.md +61 -0
  15. package/bundled/qc-helper/docs/features/hooks.md +408 -120
  16. package/bundled/qc-helper/docs/features/mcp.md +100 -14
  17. package/bundled/qc-helper/docs/features/memory.md +168 -0
  18. package/bundled/qc-helper/docs/features/sandbox.md +9 -1
  19. package/bundled/qc-helper/docs/features/status-line.md +261 -0
  20. package/bundled/qc-helper/docs/features/sub-agents.md +126 -7
  21. package/bundled/qc-helper/docs/features/tips.md +54 -0
  22. package/bundled/qc-helper/docs/features/tool-use-summaries.md +178 -0
  23. package/bundled/qc-helper/docs/overview.md +4 -4
  24. package/bundled/qc-helper/docs/quickstart.md +15 -9
  25. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
  26. package/bundled/qc-helper/docs/support/tos-privacy.md +1 -1
  27. package/bundled/qc-helper/docs/support/troubleshooting.md +9 -3
  28. package/bundled/review/DESIGN.md +165 -0
  29. package/bundled/review/SKILL.md +359 -88
  30. package/cli.js +296184 -260145
  31. package/locales/ca.js +2143 -0
  32. package/locales/de.js +104 -14
  33. package/locales/en.js +113 -13
  34. package/locales/fr.js +2099 -0
  35. package/locales/ja.js +103 -14
  36. package/locales/pt.js +105 -14
  37. package/locales/ru.js +103 -14
  38. package/locales/zh-TW.js +1678 -0
  39. package/locales/zh.js +110 -13
  40. package/package.json +2 -2
  41. package/bundled/qc-helper/docs/configuration/memory.md +0 -0
@@ -1,4 +1,4 @@
1
- # Qwen Code Hooks Documentation
1
+ # Qwen Code Hooks
2
2
 
3
3
  ## Overview
4
4
 
@@ -28,46 +28,204 @@ Hooks are user-defined scripts or programs that are automatically executed by Qw
28
28
  - Integrate with external systems and services
29
29
  - Modify tool inputs or responses programmatically
30
30
 
31
- ## Hook Architecture
31
+ ## Hook Types
32
32
 
33
- The Qwen Code hook system consists of several key components:
33
+ Qwen Code supports three hook executor types:
34
34
 
35
- 1. **Hook Registry**: Stores and manages all configured hooks
36
- 2. **Hook Planner**: Determines which hooks should run for each event
37
- 3. **Hook Runner**: Executes individual hooks with proper context
38
- 4. **Hook Aggregator**: Combines results from multiple hooks
39
- 5. **Hook Event Handler**: Coordinates the firing of hooks for events
35
+ | Type | Description |
36
+ | :--------- | :--------------------------------------------------------------------------------------------- |
37
+ | `command` | Execute a shell command. Receives JSON via `stdin`, returns results via `stdout`. |
38
+ | `http` | Send JSON as a `POST` request body to a specified URL. Returns results via HTTP response body. |
39
+ | `function` | Directly call a registered JavaScript function (session-level hooks only). |
40
+
41
+ ### Command Hooks
42
+
43
+ Command hooks execute commands via child processes. Input JSON is passed through stdin, and output is returned via stdout.
44
+
45
+ **Configuration:**
46
+
47
+ | Field | Type | Required | Description |
48
+ | :-------------- | :----------------------- | :------- | :------------------------------------------ |
49
+ | `type` | `"command"` | Yes | Hook type |
50
+ | `command` | `string` | Yes | Command to execute |
51
+ | `name` | `string` | No | Hook name (for logging) |
52
+ | `description` | `string` | No | Hook description |
53
+ | `timeout` | `number` | No | Timeout in milliseconds, default 60000 |
54
+ | `async` | `boolean` | No | Whether to run asynchronously in background |
55
+ | `env` | `Record<string, string>` | No | Environment variables |
56
+ | `shell` | `"bash" \| "powershell"` | No | Shell to use |
57
+ | `statusMessage` | `string` | No | Status message displayed during execution |
58
+
59
+ **Example:**
60
+
61
+ ```json
62
+ {
63
+ "hooks": {
64
+ "PreToolUse": [
65
+ {
66
+ "matcher": "WriteFile",
67
+ "hooks": [
68
+ {
69
+ "type": "command",
70
+ "command": "$QWEN_PROJECT_DIR/.qwen/hooks/security-check.sh",
71
+ "name": "security-check",
72
+ "timeout": 10000
73
+ }
74
+ ]
75
+ }
76
+ ]
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### HTTP Hooks
82
+
83
+ HTTP hooks send hook input as POST requests to specified URLs. They support URL whitelists, DNS-level SSRF protection, environment variable interpolation, and other security features.
84
+
85
+ **Configuration:**
86
+
87
+ | Field | Type | Required | Description |
88
+ | :--------------- | :----------------------- | :------- | :-------------------------------------------------------- |
89
+ | `type` | `"http"` | Yes | Hook type |
90
+ | `url` | `string` | Yes | Target URL |
91
+ | `headers` | `Record<string, string>` | No | Request headers (supports env var interpolation) |
92
+ | `allowedEnvVars` | `string[]` | No | Whitelist of environment variables allowed in URL/headers |
93
+ | `timeout` | `number` | No | Timeout in seconds, default 600 |
94
+ | `name` | `string` | No | Hook name (for logging) |
95
+ | `statusMessage` | `string` | No | Status message displayed during execution |
96
+ | `once` | `boolean` | No | Execute only once per event per session (HTTP hooks only) |
97
+
98
+ **Security Features:**
99
+
100
+ - **URL Whitelist**: Configure allowed URL patterns via `allowedUrls`
101
+ - **SSRF Protection**: Blocks private IPs (10.x.x.x, 172.16-31.x.x, 192.168.x.x, etc.) but allows loopback addresses (127.0.0.1, ::1)
102
+ - **DNS Validation**: Validates domain resolution before requests to prevent DNS rebinding attacks
103
+ - **Environment Variable Interpolation**: `${VAR}` syntax, only allows variables in `allowedEnvVars` whitelist
104
+
105
+ **Example:**
106
+
107
+ ```json
108
+ {
109
+ "hooks": {
110
+ "PreToolUse": [
111
+ {
112
+ "matcher": "*",
113
+ "hooks": [
114
+ {
115
+ "type": "http",
116
+ "url": "http://127.0.0.1:8080/hooks/pre-tool-use",
117
+ "headers": {
118
+ "Authorization": "Bearer ${HOOK_API_KEY}"
119
+ },
120
+ "allowedEnvVars": ["HOOK_API_KEY"],
121
+ "timeout": 10,
122
+ "name": "remote-security-check"
123
+ }
124
+ ]
125
+ }
126
+ ]
127
+ }
128
+ }
129
+ ```
130
+
131
+ ### Function Hooks
132
+
133
+ Function hooks directly call registered JavaScript/TypeScript functions. They are used internally by the Skill system and are not currently exposed as a public API for end users.
134
+
135
+ **Note**: For most use cases, use **command hooks** or **HTTP hooks** instead, which can be configured in settings files.
40
136
 
41
137
  ## Hook Events
42
138
 
43
- Hooks fire at specific points during a Qwen Code session. When an event fires and a matcher matches, Qwen Code passes JSON context about the event to your hook handler. For command hooks, input arrives on stdin. Your handler can inspect the input, take action, and optionally return a decision. Some events fire once per session, while others fire repeatedly inside the agentic loop.
44
-
45
- <div align="center">
46
- <img src="https://img.alicdn.com/imgextra/i4/O1CN01sYWUTh1RDJl7Lz2ne_!!6000000002077-2-tps-812-1212.png" alt="Hook Lifecycle Diagram" width="400"/>
47
- </div>
48
-
49
- The following table lists all available hook events in Qwen Code:
50
-
51
- | Event Name | Description | Use Case |
52
- | -------------------- | ------------------------------------------- | ----------------------------------------------- |
53
- | `PreToolUse` | Fired before tool execution | Permission checking, input validation, logging |
54
- | `PostToolUse` | Fired after successful tool execution | Logging, output processing, monitoring |
55
- | `PostToolUseFailure` | Fired when tool execution fails | Error handling, alerting, remediation |
56
- | `Notification` | Fired when notifications are sent | Notification customization, logging |
57
- | `UserPromptSubmit` | Fired when user submits a prompt | Input processing, validation, context injection |
58
- | `SessionStart` | Fired when a new session starts | Initialization, context setup |
59
- | `Stop` | Fired before Qwen concludes its response | Finalization, cleanup |
60
- | `SubagentStart` | Fired when a subagent starts | Subagent initialization |
61
- | `SubagentStop` | Fired when a subagent stops | Subagent finalization |
62
- | `PreCompact` | Fired before conversation compaction | Pre-compaction processing |
63
- | `SessionEnd` | Fired when a session ends | Cleanup, reporting |
64
- | `PermissionRequest` | Fired when permission dialogs are displayed | Permission automation, policy enforcement |
139
+ Hooks fire at specific points during a Qwen Code session. Different events support different matchers to filter trigger conditions.
140
+
141
+ | Event | Triggered When | Matcher Target |
142
+ | :------------------- | :---------------------------------------- | :-------------------------------------------------------- |
143
+ | `PreToolUse` | Before tool execution | Tool name (`WriteFile`, `ReadFile`, `Bash`, etc.) |
144
+ | `PostToolUse` | After successful tool execution | Tool name |
145
+ | `PostToolUseFailure` | After tool execution fails | Tool name |
146
+ | `UserPromptSubmit` | After user submits prompt | None (always fires) |
147
+ | `SessionStart` | When session starts or resumes | Source (`startup`, `resume`, `clear`, `compact`) |
148
+ | `SessionEnd` | When session ends | Reason (`clear`, `logout`, `prompt_input_exit`, etc.) |
149
+ | `Stop` | When Claude prepares to conclude response | None (always fires) |
150
+ | `SubagentStart` | When subagent starts | Agent type (`Bash`, `Explorer`, `Plan`, etc.) |
151
+ | `SubagentStop` | When subagent stops | Agent type |
152
+ | `PreCompact` | Before conversation compaction | Trigger (`manual`, `auto`) |
153
+ | `Notification` | When notifications are sent | Type (`permission_prompt`, `idle_prompt`, `auth_success`) |
154
+ | `PermissionRequest` | When permission dialog is shown | Tool name |
155
+
156
+ ### Matcher Patterns
157
+
158
+ `matcher` is a regular expression used to filter trigger conditions.
159
+
160
+ | Event Type | Events | Matcher Support | Matcher Target |
161
+ | :------------------ | :--------------------------------------------------------------------- | :-------------- | :------------------------------------------------------- |
162
+ | Tool Events | `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` | ✅ Regex | Tool name: `WriteFile`, `ReadFile`, `Bash`, etc. |
163
+ | Subagent Events | `SubagentStart`, `SubagentStop` | ✅ Regex | Agent type: `Bash`, `Explorer`, etc. |
164
+ | Session Events | `SessionStart` | ✅ Regex | Source: `startup`, `resume`, `clear`, `compact` |
165
+ | Session Events | `SessionEnd` | ✅ Regex | Reason: `clear`, `logout`, `prompt_input_exit`, etc. |
166
+ | Notification Events | `Notification` | ✅ Exact match | Type: `permission_prompt`, `idle_prompt`, `auth_success` |
167
+ | Compact Events | `PreCompact` | ✅ Exact match | Trigger: `manual`, `auto` |
168
+ | Prompt Events | `UserPromptSubmit` | ❌ No | N/A |
169
+ | Stop Events | `Stop` | ❌ No | N/A |
170
+
171
+ **Matcher Syntax:**
172
+
173
+ - Empty string `""` or `"*"` matches all events of that type
174
+ - Standard regex syntax supported (e.g., `^Bash$`, `Read.*`, `(WriteFile|Edit)`)
175
+
176
+ **Examples:**
177
+
178
+ ```json
179
+ {
180
+ "hooks": {
181
+ "PreToolUse": [
182
+ {
183
+ "matcher": "^Bash$",
184
+ "hooks": [
185
+ {
186
+ "type": "command",
187
+ "command": "echo 'bash check' >> /tmp/hooks.log"
188
+ }
189
+ ]
190
+ },
191
+ {
192
+ "matcher": "Write.*",
193
+ "hooks": [
194
+ {
195
+ "type": "command",
196
+ "command": "echo 'write check' >> /tmp/hooks.log"
197
+ }
198
+ ]
199
+ },
200
+ {
201
+ "matcher": "*",
202
+ "hooks": [
203
+ { "type": "command", "command": "echo 'all tools' >> /tmp/hooks.log" }
204
+ ]
205
+ }
206
+ ],
207
+ "SubagentStart": [
208
+ {
209
+ "matcher": "^(Bash|Explorer)$",
210
+ "hooks": [
211
+ {
212
+ "type": "command",
213
+ "command": "echo 'subagent check' >> /tmp/hooks.log"
214
+ }
215
+ ]
216
+ }
217
+ ]
218
+ }
219
+ }
220
+ ```
65
221
 
66
222
  ## Input/Output Rules
67
223
 
68
224
  ### Hook Input Structure
69
225
 
70
- All hooks receive standardized input in JSON format through stdin. Common fields included in every hook event:
226
+ All hooks receive standardized input in JSON format through stdin (command) or POST body (http).
227
+
228
+ **Common Fields:**
71
229
 
72
230
  ```json
73
231
  {
@@ -79,7 +237,39 @@ All hooks receive standardized input in JSON format through stdin. Common fields
79
237
  }
80
238
  ```
81
239
 
82
- Event-specific fields are added based on the hook type. Below are the event-specific fields for each hook event:
240
+ Event-specific fields are added based on the hook type. When running in a subagent, `agent_id` and `agent_type` are additionally included.
241
+
242
+ ### Hook Output Structure
243
+
244
+ Hook output is returned via `stdout` (command) or HTTP response body (http) as JSON.
245
+
246
+ **Exit Code Behavior (Command Hooks):**
247
+
248
+ | Exit Code | Behavior |
249
+ | :-------- | :------------------------------------------------------------------------------------ |
250
+ | `0` | Success. Parse JSON in `stdout` to control behavior. |
251
+ | `2` | **Blocking error**. Ignores `stdout`, passes `stderr` as error feedback to the model. |
252
+ | Other | Non-blocking error. `stderr` only shown in debug mode, execution continues. |
253
+
254
+ **Output Structure:**
255
+
256
+ Hook output supports three categories of fields:
257
+
258
+ 1. **Common Fields**: `continue`, `stopReason`, `suppressOutput`, `systemMessage`
259
+ 2. **Top-level Decision**: `decision`, `reason` (used by some events)
260
+ 3. **Event-specific Control**: `hookSpecificOutput` (must include `hookEventName`)
261
+
262
+ ```json
263
+ {
264
+ "continue": true,
265
+ "decision": "allow",
266
+ "reason": "Operation approved",
267
+ "hookSpecificOutput": {
268
+ "hookEventName": "PreToolUse",
269
+ "additionalContext": "Additional context information"
270
+ }
271
+ }
272
+ ```
83
273
 
84
274
  ### Individual Hook Event Details
85
275
 
@@ -113,11 +303,8 @@ Event-specific fields are added based on the hook type. Below are the event-spec
113
303
  {
114
304
  "hookSpecificOutput": {
115
305
  "hookEventName": "PreToolUse",
116
- "permissionDecision": "allow",
117
- "permissionDecisionReason": "My reason here",
118
- "updatedInput": {
119
- "field_to_modify": "new value"
120
- },
306
+ "permissionDecision": "deny",
307
+ "permissionDecisionReason": "Security policy blocks database writes",
121
308
  "additionalContext": "Current environment: production. Proceed with caution."
122
309
  }
123
310
  }
@@ -299,6 +486,60 @@ Event-specific fields are added based on the hook type. Below are the event-spec
299
486
  }
300
487
  ```
301
488
 
489
+ #### StopFailure
490
+
491
+ **Purpose**: Executed when the turn ends due to an API error (instead of Stop). This is a **fire-and-forget** event - hook output and exit codes are ignored.
492
+
493
+ **Event-specific fields**:
494
+
495
+ ```json
496
+ {
497
+ "error": "rate_limit | authentication_failed | billing_error | invalid_request | server_error | max_output_tokens | unknown",
498
+ "error_details": "detailed error message (optional)",
499
+ "last_assistant_message": "the last message from the assistant before the error (optional)"
500
+ }
501
+ ```
502
+
503
+ **Matcher**: Matches against the `error` field. For example, `"matcher": "rate_limit"` will only trigger for rate limit errors.
504
+
505
+ **Output Options**:
506
+
507
+ - **None** - StopFailure is fire-and-forget. All hook output and exit codes are ignored.
508
+
509
+ **Exit Code Handling**:
510
+
511
+ | Exit Code | Behavior |
512
+ | --------- | ------------------------- |
513
+ | Any | Ignored (fire-and-forget) |
514
+
515
+ **Example Configuration**:
516
+
517
+ ```json
518
+ {
519
+ "hooks": {
520
+ "StopFailure": [
521
+ {
522
+ "matcher": "rate_limit",
523
+ "hooks": [
524
+ {
525
+ "type": "command",
526
+ "command": "/path/to/rate-limit-alert.sh",
527
+ "name": "rate-limit-alerter"
528
+ }
529
+ ]
530
+ }
531
+ ]
532
+ }
533
+ }
534
+ ```
535
+
536
+ **Use Cases**:
537
+
538
+ - Rate limit monitoring and alerting
539
+ - Authentication failure logging
540
+ - Billing error notifications
541
+ - Error statistics collection
542
+
302
543
  #### SubagentStart
303
544
 
304
545
  **Purpose**: Executed when a subagent (like the Task tool) is started to set up context or permissions.
@@ -387,6 +628,63 @@ Event-specific fields are added based on the hook type. Below are the event-spec
387
628
  }
388
629
  ```
389
630
 
631
+ #### PostCompact
632
+
633
+ **Purpose**: Executed after conversation compaction completes to archive summaries or track usage.
634
+
635
+ **Event-specific fields**:
636
+
637
+ ```json
638
+ {
639
+ "trigger": "manual | auto",
640
+ "compact_summary": "the summary generated by the compaction process"
641
+ }
642
+ ```
643
+
644
+ **Matcher**: Matches against the `trigger` field. For example, `"matcher": "manual"` will only trigger for manual compaction via `/compact` command.
645
+
646
+ **Output Options**:
647
+
648
+ - `hookSpecificOutput.additionalContext`: additional context (for logging only)
649
+ - Standard hook output fields (for logging only)
650
+
651
+ **Note**: PostCompact is **not** in the official decision mode supported events list. The `decision` field and other control fields do not produce any control effects - they are only used for logging purposes.
652
+
653
+ **Exit Code Handling**:
654
+
655
+ | Exit Code | Behavior |
656
+ | --------- | --------------------------------------------------------- |
657
+ | 0 | Success - stdout shown to user in verbose mode |
658
+ | Other | Non-blocking error - stderr shown to user in verbose mode |
659
+
660
+ **Example Configuration**:
661
+
662
+ ```json
663
+ {
664
+ "hooks": {
665
+ "PostCompact": [
666
+ {
667
+ "matcher": "manual",
668
+ "hooks": [
669
+ {
670
+ "type": "command",
671
+ "command": "/path/to/save-compact-summary.sh",
672
+ "name": "save-summary"
673
+ }
674
+ ]
675
+ }
676
+ ]
677
+ }
678
+ }
679
+ ```
680
+
681
+ **Use Cases**:
682
+
683
+ - Summary archiving to files or databases
684
+ - Usage statistics tracking
685
+ - Context change monitoring
686
+ - Audit logging for compaction operations
687
+
390
688
  #### Notification
391
689
 
392
690
  **Purpose**: Executed when notifications are sent to customize or intercept them.
@@ -465,12 +763,12 @@ Hooks are configured in Qwen Code settings, typically in `.qwen/settings.json` o
465
763
  "hooks": {
466
764
  "PreToolUse": [
467
765
  {
468
- "matcher": "^bash$", // Regex to match tool names
469
- "sequential": false, // Whether to run hooks sequentially
766
+ "matcher": "^Bash$",
767
+ "sequential": false,
470
768
  "hooks": [
471
769
  {
472
770
  "type": "command",
473
- "command": "/path/to/script.sh",
771
+ "command": "/path/to/security-check.sh",
474
772
  "name": "security-check",
475
773
  "description": "Run security checks before tool execution",
476
774
  "timeout": 30000
@@ -493,69 +791,58 @@ Hooks are configured in Qwen Code settings, typically in `.qwen/settings.json` o
493
791
  }
494
792
  ```
495
793
 
496
- ### Matcher Patterns
794
+ ## Hook Execution
497
795
 
498
- Matchers allow filtering hooks based on context. Not all hook events support matchers:
796
+ ### Parallel vs Sequential Execution
499
797
 
500
- | Event Type | Events | Matcher Support | Matcher Target (Values) |
501
- | ------------------- | ---------------------------------------------------------------------- | --------------- | -------------------------------------------------------------------------------------- |
502
- | Tool Events | `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` | Yes (regex) | Tool name: `bash`, `read_file`, `write_file`, `edit`, `glob`, `grep_search`, etc. |
503
- | Subagent Events | `SubagentStart`, `SubagentStop` | ✅ Yes (regex) | Agent type: `Bash`, `Explorer`, etc. |
504
- | Session Events | `SessionStart` | ✅ Yes (regex) | Source: `startup`, `resume`, `clear`, `compact` |
505
- | Session Events | `SessionEnd` | ✅ Yes (regex) | Reason: `clear`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` |
506
- | Notification Events | `Notification` | ✅ Yes (exact) | Type: `permission_prompt`, `idle_prompt`, `auth_success` |
507
- | Compact Events | `PreCompact` | ✅ Yes (exact) | Trigger: `manual`, `auto` |
508
- | Prompt Events | `UserPromptSubmit` | ❌ No | N/A |
509
- | Stop Events | `Stop` | ❌ No | N/A |
798
+ - By default, hooks execute in parallel for better performance
799
+ - Use `sequential: true` in hook definition to enforce order-dependent execution
800
+ - Sequential hooks can modify input for subsequent hooks in the chain
510
801
 
511
- **Matcher Syntax**:
802
+ ### Async Hooks
512
803
 
513
- - Regex pattern matched against the target field
514
- - Empty string `""` or `"*"` matches all events of that type
515
- - Standard regex syntax supported (e.g., `^bash$`, `read.*`, `(bash|run_shell_command)`)
804
+ Only `command` type supports asynchronous execution. Setting `"async": true` runs the hook in the background without blocking the main flow.
516
805
 
517
- **Examples**:
806
+ **Features:**
807
+
808
+ - Cannot return decision control (operation has already occurred)
809
+ - Results are injected in the next conversation turn via `systemMessage` or `additionalContext`
810
+ - Suitable for auditing, logging, background testing, etc.
811
+
812
+ **Example:**
518
813
 
519
814
  ```json
520
815
  {
521
816
  "hooks": {
522
- "PreToolUse": [
523
- {
524
- "matcher": "^bash$", // Only match bash tool
525
- "hooks": [...]
526
- },
527
- {
528
- "matcher": "read.*", // Match read_file, read_multiple_files, etc.
529
- "hooks": [...]
530
- },
531
- {
532
- "matcher": "", // Match all tools (same as "*" or omitting matcher)
533
- "hooks": [...]
534
- }
535
- ],
536
- "SubagentStart": [
537
- {
538
- "matcher": "^(Bash|Explorer)$", // Only match Bash and Explorer agents
539
- "hooks": [...]
540
- }
541
- ],
542
- "SessionStart": [
817
+ "PostToolUse": [
543
818
  {
544
- "matcher": "^(startup|resume)$", // Only match startup and resume sources
545
- "hooks": [...]
819
+ "matcher": "WriteFile|Edit",
820
+ "hooks": [
821
+ {
822
+ "type": "command",
823
+ "command": "$QWEN_PROJECT_DIR/.qwen/hooks/run-tests-async.sh",
824
+ "async": true,
825
+ "timeout": 300000
826
+ }
827
+ ]
546
828
  }
547
829
  ]
548
830
  }
549
831
  }
550
832
  ```
551
833
 
552
- ## Hook Execution
553
-
554
- ### Parallel vs Sequential Execution
555
-
556
- - By default, hooks execute in parallel for better performance
557
- - Use `sequential: true` in hook definition to enforce order-dependent execution
558
- - Sequential hooks can modify input for subsequent hooks in the chain
834
+ ```bash
835
+ #!/bin/bash
836
+ INPUT=$(cat)
837
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
838
+ if [[ "$FILE_PATH" != *.ts && "$FILE_PATH" != *.js ]]; then exit 0; fi
839
+ RESULT=$(npm test 2>&1)
840
+ if [ $? -eq 0 ]; then
841
+ echo "{\"systemMessage\": \"Tests passed after editing $FILE_PATH\"}"
842
+ else
843
+ echo "{\"systemMessage\": \"Tests failed: $RESULT\"}"
844
+ fi
845
+ ```
559
846
 
560
847
  ### Security Model
561
848
 
@@ -563,32 +850,6 @@ Matchers allow filtering hooks based on context. Not all hook events support mat
563
850
  - Project-level hooks require trusted folder status
564
851
  - Timeouts prevent hanging hooks (default: 60 seconds)
565
852
 
566
- ### Exit Codes
567
-
568
- Hook scripts communicate their result through exit codes:
569
-
570
- | Exit Code | Meaning | Behavior |
571
- | --------- | ------------------ | ----------------------------------------------- |
572
- | `0` | Success | stdout/stderr not shown |
573
- | `2` | Blocking error | Show stderr to model and block tool call |
574
- | Other | Non-blocking error | Show stderr to user only but continue tool call |
575
-
576
- **Examples**:
577
-
578
- ```bash
579
- #!/bin/bash
580
-
581
- # Success (exit 0 is default, can be omitted)
582
- echo '{"decision": "allow"}'
583
- exit 0
584
-
585
- # Blocking error - prevents operation
586
- echo "Dangerous operation blocked by security policy" >&2
587
- exit 2
588
- ```
589
-
590
- > **Note**: If no exit code is specified, the script defaults to `0` (success).
591
-
592
853
  ## Best Practices
593
854
 
594
855
  ### Example 1: Security Validation Hook
@@ -610,24 +871,20 @@ TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input')
610
871
  # Check for potentially dangerous operations
611
872
  if echo "$TOOL_INPUT" | grep -qiE "(rm.*-rf|mv.*\/|chmod.*777)"; then
612
873
  echo '{
613
- "decision": "deny",
614
- "reason": "Potentially dangerous operation detected",
615
874
  "hookSpecificOutput": {
616
875
  "hookEventName": "PreToolUse",
617
876
  "permissionDecision": "deny",
618
- "permissionDecisionReason": "Dangerous command blocked by security policy"
877
+ "permissionDecisionReason": "Security policy blocks dangerous command"
619
878
  }
620
879
  }'
621
880
  exit 2 # Blocking error
622
881
  fi
623
882
 
624
- # Allow the operation with a log
883
+ # Log the operation
625
884
  echo "INFO: Tool $TOOL_NAME executed safely at $(date)" >> /var/log/qwen-security.log
626
885
 
627
886
  # Allow with additional context
628
887
  echo '{
629
- "decision": "allow",
630
- "reason": "Operation approved by security checker",
631
888
  "hookSpecificOutput": {
632
889
  "hookEventName": "PreToolUse",
633
890
  "permissionDecision": "allow",
@@ -660,7 +917,36 @@ Configure in `.qwen/settings.json`:
660
917
  }
661
918
  ```
662
919
 
663
- ### Example 2: User Prompt Validation Hook
920
+ ### Example 2: HTTP Audit Hook
921
+
922
+ A PostToolUse HTTP hook that sends all tool execution records to a remote audit service:
923
+
924
+ ```json
925
+ {
926
+ "hooks": {
927
+ "PostToolUse": [
928
+ {
929
+ "matcher": "*",
930
+ "hooks": [
931
+ {
932
+ "type": "http",
933
+ "url": "https://audit.example.com/api/tool-execution",
934
+ "headers": {
935
+ "Authorization": "Bearer ${AUDIT_API_TOKEN}",
936
+ "Content-Type": "application/json"
937
+ },
938
+ "allowedEnvVars": ["AUDIT_API_TOKEN"],
939
+ "timeout": 10,
940
+ "name": "audit-logger"
941
+ }
942
+ ]
943
+ }
944
+ ]
945
+ }
946
+ }
947
+ ```
948
+
949
+ ### Example 3: User Prompt Validation Hook
664
950
 
665
951
  A UserPromptSubmit hook that validates user prompts for sensitive information and provides context for long prompts:
666
952
 
@@ -718,3 +1004,5 @@ exit(0)
718
1004
  - Verify hook script permissions and executability
719
1005
  - Ensure proper JSON formatting in hook outputs
720
1006
  - Use specific matcher patterns to avoid unintended hook execution
1007
+ - Use `--debug` mode to see detailed hook matching and execution information
1008
+ - Temporarily disable all hooks: add `"disableAllHooks": true` in settings