@maincode-ai/matilda-code 0.21.13 → 0.22.0-nightly.20261102.db95a17c4

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 (252) hide show
  1. package/chunks/agent-4GIFJO5G.js +3 -0
  2. package/chunks/agent-headless-DXJESNI4.js +3 -0
  3. package/chunks/{askUserQuestion-BNSWGD26.js → askUserQuestion-7PM7G5YF.js} +3 -3
  4. package/chunks/ca-JKEHLTNL.js +23 -0
  5. package/chunks/chunk-225CZWD7.js +89 -0
  6. package/chunks/chunk-2QIC3OCV.js +9 -0
  7. package/chunks/chunk-33UVJMVE.js +120 -0
  8. package/chunks/chunk-35BBGAHD.js +2604 -0
  9. package/chunks/{chunk-DHDD5YJC.js → chunk-4KS2KEXK.js} +69 -69
  10. package/chunks/chunk-4MLFC664.js +3 -0
  11. package/chunks/{chunk-RNKDFE2S.js → chunk-5B2QERWR.js} +1 -1
  12. package/chunks/chunk-66WJUORA.js +8 -0
  13. package/chunks/chunk-6U5VOTWB.js +56 -0
  14. package/chunks/chunk-7MUWF4DK.js +80 -0
  15. package/chunks/{chunk-6M5G5FBH.js → chunk-BVTXZTL3.js} +1 -1
  16. package/chunks/chunk-CVGGYRNK.js +31 -0
  17. package/chunks/chunk-DUB7JMQV.js +13 -0
  18. package/chunks/chunk-ESNPNLMQ.js +8 -0
  19. package/chunks/chunk-GT6MSEK4.js +3 -0
  20. package/chunks/chunk-HEJO7OBH.js +3 -0
  21. package/chunks/chunk-JNHB73E3.js +9 -0
  22. package/chunks/chunk-JR5CSCG4.js +8 -0
  23. package/chunks/{chunk-EZDV7A76.js → chunk-KRVXBQRC.js} +1 -1
  24. package/chunks/{chunk-AOOZREGV.js → chunk-LBQNFSZ2.js} +1 -1
  25. package/chunks/{chunk-MEV5XQI2.js → chunk-QBXL5UBB.js} +1 -1
  26. package/chunks/{chunk-P5TG5CON.js → chunk-QDWS3VZT.js} +1 -1
  27. package/chunks/{chunk-QZI2ZGZY.js → chunk-QMZREVY3.js} +1 -1
  28. package/chunks/chunk-QUYQBKDE.js +8 -0
  29. package/chunks/chunk-QXSBPCBA.js +8 -0
  30. package/chunks/chunk-S2E5ZRPH.js +14 -0
  31. package/chunks/chunk-TUKNB5CQ.js +33 -0
  32. package/chunks/chunk-UM6CLO7D.js +7 -0
  33. package/chunks/{chunk-6T2GIM76.js → chunk-VVUY7VKR.js} +1 -1
  34. package/chunks/{chunk-5OHGYMKP.js → chunk-WENVHSCJ.js} +1 -1
  35. package/chunks/{chunk-27Q5KW3A.js → chunk-ZABH4QIL.js} +10 -10
  36. package/chunks/chunk-ZSGBDQXU.js +11 -0
  37. package/chunks/{computer-use-J4GAM4M6.js → computer-use-IZGLKENV.js} +1 -1
  38. package/chunks/{cron-create-IDWSZENI.js → cron-create-BTSJUVNT.js} +1 -1
  39. package/chunks/cron-delete-PTE3RC2W.js +3 -0
  40. package/chunks/cron-list-SINKHOIZ.js +5 -0
  41. package/chunks/de-GMGNR5CZ.js +23 -0
  42. package/chunks/{devtools-XRQ4YJ5S.js → devtools-7YNCRYZV.js} +1 -1
  43. package/chunks/{chunk-OOEH6ZSV.js → dist-UWUWLWTO.js} +2 -2
  44. package/chunks/{edit-X2S2ZXRN.js → edit-MDQEZ7BA.js} +1 -1
  45. package/chunks/en-3NQMLVKW.js +23 -0
  46. package/chunks/{enter-worktree-TUCGNCLO.js → enter-worktree-SZK65VXF.js} +1 -1
  47. package/chunks/enterPlanMode-5VWIIVHI.js +18 -0
  48. package/chunks/{exit-worktree-7FLITFZI.js → exit-worktree-OBHUK4TF.js} +1 -1
  49. package/chunks/{exitPlanMode-O5UUJ3GM.js → exitPlanMode-SXFQC4G2.js} +2 -2
  50. package/chunks/fr-WS3EBB36.js +23 -0
  51. package/chunks/{getMachineId-bsd-ZYBNK2JG.js → getMachineId-bsd-ETKQTB6C.js} +1 -1
  52. package/chunks/{getMachineId-darwin-CM2MQGUI.js → getMachineId-darwin-AKNRWOWB.js} +1 -1
  53. package/chunks/{getMachineId-linux-SYE2KMCW.js → getMachineId-linux-2QSD7FTP.js} +1 -1
  54. package/chunks/{getMachineId-unsupported-6IHVG2XO.js → getMachineId-unsupported-UXSV7I24.js} +1 -1
  55. package/chunks/{getMachineId-win-S3J3JSUM.js → getMachineId-win-4MTFXGP3.js} +1 -1
  56. package/chunks/glob-JKIZ3ZJQ.js +22 -0
  57. package/chunks/{goal-tools-YQOA6OKU.js → goal-tools-YJMECZYD.js} +3 -3
  58. package/chunks/{grep-VAB2VSXM.js → grep-Q4T5AE6K.js} +1 -1
  59. package/chunks/ja-GBCDQ43R.js +23 -0
  60. package/chunks/keychain-token-storage-4PY5J6U6.js +3 -0
  61. package/chunks/ls-BQCCCPIX.js +15 -0
  62. package/chunks/{lsp-NGLDRHZU.js → lsp-MHJJJ7K3.js} +1 -1
  63. package/chunks/mcp-client-CSF5QZEY.js +3 -0
  64. package/chunks/monitor-JUAVWVLY.js +32 -0
  65. package/chunks/{multipart-parser-JI75T2O5.js → multipart-parser-FKHYAVGR.js} +1 -1
  66. package/chunks/notebook-edit-NNOMEUER.js +17 -0
  67. package/chunks/openaiContentGenerator-DTKOYRBL.js +47 -0
  68. package/chunks/pt-VID6J2CM.js +23 -0
  69. package/chunks/read-file-4EX4B3TB.js +3 -0
  70. package/chunks/ripGrep-JL6UDNCR.js +3 -0
  71. package/chunks/ru-EB6V6EAN.js +23 -0
  72. package/chunks/scheduler-GCGZAI7D.js +8 -0
  73. package/chunks/send-message-S4P5QKSW.js +8 -0
  74. package/chunks/shell-J7EX7B57.js +3 -0
  75. package/chunks/{skill-ETQM5NI3.js → skill-V6NTJ4O4.js} +1 -1
  76. package/chunks/src-LZEU4AYF.js +5 -0
  77. package/chunks/symbol-search-5QJNW7PY.js +19 -0
  78. package/chunks/{syntheticOutput-WZDPECYS.js → syntheticOutput-3XIAIUIR.js} +1 -1
  79. package/chunks/task-create-KGPY7O4J.js +3 -0
  80. package/chunks/{task-detach-TBAVUOTC.js → task-detach-ZD3A7225.js} +1 -1
  81. package/chunks/task-list-P7GQWYAD.js +9 -0
  82. package/chunks/{task-stop-HDSARSJ6.js → task-stop-VFJRBA6P.js} +1 -1
  83. package/chunks/{task-update-MW2VT2XV.js → task-update-OOMH4WRA.js} +1 -1
  84. package/chunks/{team-create-VMYNLZCC.js → team-create-POMZOM44.js} +2 -2
  85. package/chunks/team-delete-ZJBEQDPE.js +8 -0
  86. package/chunks/todoWrite-EWYRFK7W.js +3 -0
  87. package/chunks/{tool-search-WX6FOE35.js → tool-search-5Z7MO565.js} +1 -1
  88. package/chunks/{web-fetch-CKYBHGLF.js → web-fetch-M4TUYAFG.js} +17 -17
  89. package/chunks/web-search-CBKF36JM.js +26 -0
  90. package/chunks/{workflow-WBSRQG3N.js → workflow-F57TWWPS.js} +2 -2
  91. package/chunks/write-file-UK4BVL3M.js +15 -0
  92. package/cli.js +642 -678
  93. package/examples/starter/README.md +0 -3
  94. package/locales/ca.js +3 -87
  95. package/locales/de.js +3 -91
  96. package/locales/en.js +3 -91
  97. package/locales/fr.js +3 -88
  98. package/locales/ja.js +3 -92
  99. package/locales/pt.js +3 -92
  100. package/locales/ru.js +3 -91
  101. package/package.json +2 -2
  102. package/sandbox-macos-permissive-proxied.sb +1 -1
  103. package/sandbox-macos-restrictive-closed.sb +14 -1
  104. package/sandbox-macos-restrictive-open.sb +14 -1
  105. package/sandbox-macos-restrictive-proxied.sb +15 -2
  106. package/bundled/mainy/SKILL.md +0 -157
  107. package/bundled/mainy/docs/_meta.ts +0 -32
  108. package/bundled/mainy/docs/common-workflow.md +0 -571
  109. package/bundled/mainy/docs/configuration/_meta.ts +0 -7
  110. package/bundled/mainy/docs/configuration/auth.md +0 -82
  111. package/bundled/mainy/docs/configuration/matilda-ignore.md +0 -55
  112. package/bundled/mainy/docs/configuration/model-providers.md +0 -516
  113. package/bundled/mainy/docs/configuration/settings.md +0 -818
  114. package/bundled/mainy/docs/configuration/themes.md +0 -199
  115. package/bundled/mainy/docs/configuration/trusted-folders.md +0 -67
  116. package/bundled/mainy/docs/extension/_meta.ts +0 -9
  117. package/bundled/mainy/docs/extension/extension-releasing.md +0 -204
  118. package/bundled/mainy/docs/extension/getting-started-extensions.md +0 -299
  119. package/bundled/mainy/docs/extension/introduction.md +0 -338
  120. package/bundled/mainy/docs/features/_meta.ts +0 -27
  121. package/bundled/mainy/docs/features/approval-mode.md +0 -388
  122. package/bundled/mainy/docs/features/arena.md +0 -219
  123. package/bundled/mainy/docs/features/auto-mode.md +0 -308
  124. package/bundled/mainy/docs/features/channels/_meta.ts +0 -5
  125. package/bundled/mainy/docs/features/channels/overview.md +0 -328
  126. package/bundled/mainy/docs/features/channels/plugins.md +0 -87
  127. package/bundled/mainy/docs/features/channels/telegram.md +0 -120
  128. package/bundled/mainy/docs/features/code-review.md +0 -291
  129. package/bundled/mainy/docs/features/commands.md +0 -528
  130. package/bundled/mainy/docs/features/dual-output.md +0 -627
  131. package/bundled/mainy/docs/features/followup-suggestions.md +0 -109
  132. package/bundled/mainy/docs/features/headless.md +0 -448
  133. package/bundled/mainy/docs/features/hooks.md +0 -1308
  134. package/bundled/mainy/docs/features/language.md +0 -144
  135. package/bundled/mainy/docs/features/lsp.md +0 -496
  136. package/bundled/mainy/docs/features/markdown-rendering.md +0 -183
  137. package/bundled/mainy/docs/features/mcp.md +0 -423
  138. package/bundled/mainy/docs/features/memory.md +0 -185
  139. package/bundled/mainy/docs/features/sandbox.md +0 -249
  140. package/bundled/mainy/docs/features/scheduled-tasks.md +0 -139
  141. package/bundled/mainy/docs/features/skills.md +0 -347
  142. package/bundled/mainy/docs/features/status-line.md +0 -397
  143. package/bundled/mainy/docs/features/structured-output.md +0 -309
  144. package/bundled/mainy/docs/features/sub-agents.md +0 -737
  145. package/bundled/mainy/docs/features/tips.md +0 -54
  146. package/bundled/mainy/docs/features/token-caching.md +0 -29
  147. package/bundled/mainy/docs/features/tool-use-summaries.md +0 -178
  148. package/bundled/mainy/docs/features/worktree.md +0 -343
  149. package/bundled/mainy/docs/ide-integration/_meta.ts +0 -4
  150. package/bundled/mainy/docs/ide-integration/ide-companion-spec.md +0 -182
  151. package/bundled/mainy/docs/ide-integration/ide-integration.md +0 -144
  152. package/bundled/mainy/docs/integration-github-action.md +0 -241
  153. package/bundled/mainy/docs/integration-jetbrains.md +0 -81
  154. package/bundled/mainy/docs/integration-vscode.md +0 -39
  155. package/bundled/mainy/docs/integration-zed.md +0 -72
  156. package/bundled/mainy/docs/matilda-serve-deploy-local.md +0 -221
  157. package/bundled/mainy/docs/matilda-serve.md +0 -661
  158. package/bundled/mainy/docs/overview.md +0 -64
  159. package/bundled/mainy/docs/quickstart.md +0 -234
  160. package/bundled/mainy/docs/reference/_meta.ts +0 -3
  161. package/bundled/mainy/docs/reference/keyboard-shortcuts.md +0 -91
  162. package/bundled/mainy/docs/support/Uninstall.md +0 -65
  163. package/bundled/mainy/docs/support/_meta.ts +0 -6
  164. package/bundled/mainy/docs/support/tos-privacy.md +0 -94
  165. package/bundled/mainy/docs/support/troubleshooting.md +0 -127
  166. package/chunks/agent-SRAIVZEE.js +0 -3
  167. package/chunks/agent-headless-XRDOZESG.js +0 -3
  168. package/chunks/anthropicContentGenerator-LLDIKDMQ.js +0 -39
  169. package/chunks/ca-NPYL24ME.js +0 -25
  170. package/chunks/chunk-27HUYW23.js +0 -22
  171. package/chunks/chunk-2HTPVSGT.js +0 -3
  172. package/chunks/chunk-3B2HABK7.js +0 -30
  173. package/chunks/chunk-3MTZTNAU.js +0 -101
  174. package/chunks/chunk-3YLXGE6T.js +0 -8
  175. package/chunks/chunk-47XR7IMP.js +0 -8
  176. package/chunks/chunk-4F4DA5UI.js +0 -8
  177. package/chunks/chunk-4Q2SNBUH.js +0 -18
  178. package/chunks/chunk-6EQMZNIY.js +0 -8
  179. package/chunks/chunk-6I6VGTKD.js +0 -8
  180. package/chunks/chunk-DC7LAFZZ.js +0 -8
  181. package/chunks/chunk-DE3HKC2W.js +0 -9
  182. package/chunks/chunk-FWDMPRKU.js +0 -3
  183. package/chunks/chunk-G7R2XEEF.js +0 -7
  184. package/chunks/chunk-GOJCMVJJ.js +0 -8
  185. package/chunks/chunk-GTVCJCHR.js +0 -8
  186. package/chunks/chunk-IJEGHQ7Z.js +0 -32
  187. package/chunks/chunk-JCE3JAVC.js +0 -25
  188. package/chunks/chunk-KHHJYBR5.js +0 -9
  189. package/chunks/chunk-LUNDTQ3G.js +0 -8
  190. package/chunks/chunk-LWARA7JY.js +0 -37
  191. package/chunks/chunk-M53RP3YP.js +0 -31
  192. package/chunks/chunk-MTMU7JYZ.js +0 -11
  193. package/chunks/chunk-O44XK65C.js +0 -8
  194. package/chunks/chunk-OA56BXPD.js +0 -3
  195. package/chunks/chunk-PEKAUGYV.js +0 -2621
  196. package/chunks/chunk-PGUG43HG.js +0 -24
  197. package/chunks/chunk-PGXQZVLX.js +0 -8
  198. package/chunks/chunk-QKYGQLWC.js +0 -8
  199. package/chunks/chunk-QN6Y6NPA.js +0 -3
  200. package/chunks/chunk-RI54U73U.js +0 -56
  201. package/chunks/chunk-RPFSFS7Z.js +0 -39
  202. package/chunks/chunk-SDTWBD62.js +0 -8
  203. package/chunks/chunk-SOEIVSM5.js +0 -113
  204. package/chunks/chunk-SVSY6AWS.js +0 -59
  205. package/chunks/chunk-T2T2UEPY.js +0 -4
  206. package/chunks/chunk-TISQNFB5.js +0 -3
  207. package/chunks/chunk-TWJLOEAI.js +0 -31
  208. package/chunks/chunk-VI74YQQO.js +0 -8
  209. package/chunks/chunk-VYZOOSMP.js +0 -30
  210. package/chunks/chunk-W4QSMIWO.js +0 -9
  211. package/chunks/chunk-WC2VTVCE.js +0 -27
  212. package/chunks/chunk-YV3PUOBU.js +0 -65
  213. package/chunks/chunk-ZX34M2GF.js +0 -14
  214. package/chunks/contextCommand-5F5M7NA4.js +0 -3
  215. package/chunks/cron-delete-NQCDZDUI.js +0 -3
  216. package/chunks/cron-list-Z4XMC3TO.js +0 -5
  217. package/chunks/de-34YZHGC6.js +0 -25
  218. package/chunks/dist-7UYRLSLE.js +0 -3
  219. package/chunks/dist-PH6JW7XD.js +0 -42
  220. package/chunks/en-QLGMD6OS.js +0 -25
  221. package/chunks/enterPlanMode-SQEZAAIR.js +0 -18
  222. package/chunks/fileFromPath-7UCWPD4W.js +0 -3
  223. package/chunks/fr-EDNBQACJ.js +0 -25
  224. package/chunks/geminiContentGenerator-FIZFLPU3.js +0 -8
  225. package/chunks/glob-GSFTYAS2.js +0 -22
  226. package/chunks/ja-LV4RLM3M.js +0 -25
  227. package/chunks/keychain-token-storage-KQK6MNOJ.js +0 -3
  228. package/chunks/ls-IZJ3CKZY.js +0 -15
  229. package/chunks/matildaAgentContentGenerator-QQHPCFJ5.js +0 -8
  230. package/chunks/matildaContentGenerator-W7Z33ONU.js +0 -8
  231. package/chunks/matildaOAuth2-7COTQQR2.js +0 -3
  232. package/chunks/mcp-client-DXUNIEIB.js +0 -3
  233. package/chunks/monitor-4PFIGAGG.js +0 -32
  234. package/chunks/notebook-edit-MWJYAATJ.js +0 -17
  235. package/chunks/openaiContentGenerator-NDVJL6QL.js +0 -3
  236. package/chunks/pt-5SQ4DGL7.js +0 -25
  237. package/chunks/read-file-WPZKPXWA.js +0 -3
  238. package/chunks/ripGrep-7LZDZFTX.js +0 -3
  239. package/chunks/ru-7K24S53N.js +0 -25
  240. package/chunks/scheduler-DK2MVKXX.js +0 -8
  241. package/chunks/send-message-TCPX5UDU.js +0 -8
  242. package/chunks/serve-GSZPJI2O.js +0 -1026
  243. package/chunks/shell-PRS47PDP.js +0 -3
  244. package/chunks/src-UB7DZRYK.js +0 -3
  245. package/chunks/src-WZTRMETQ.js +0 -5
  246. package/chunks/symbol-search-HARHZ5AH.js +0 -19
  247. package/chunks/task-create-XRNIDT4T.js +0 -3
  248. package/chunks/task-list-Z6BDZZID.js +0 -9
  249. package/chunks/team-delete-F7QDC2TE.js +0 -8
  250. package/chunks/todoWrite-SCF5M24M.js +0 -3
  251. package/chunks/web-search-67DFNS5V.js +0 -26
  252. package/chunks/write-file-S5FAX4JJ.js +0 -15
@@ -1,1308 +0,0 @@
1
- # Matilda Code Hooks
2
-
3
- ## Overview
4
-
5
- Matilda Code hooks provide a powerful mechanism for extending and customizing the behavior of the Matilda Code application. Hooks allow users to execute custom scripts or programs at specific points in the application lifecycle, such as before tool execution, after tool execution, at session start/end, and during other key events.
6
-
7
- Hooks are enabled by default. You can temporarily disable all hooks by setting `disableAllHooks` to `true` in your settings file (at the top level, alongside `hooks`):
8
-
9
- ```json
10
- {
11
- "disableAllHooks": true,
12
- "hooks": {
13
- "PreToolUse": [...]
14
- }
15
- }
16
- ```
17
-
18
- This disables all hooks without deleting their configurations.
19
-
20
- ## What are Hooks?
21
-
22
- Hooks are user-defined scripts or programs that are automatically executed by Matilda Code at predefined points in the application flow. They allow users to:
23
-
24
- - Monitor and audit tool usage
25
- - Enforce security policies
26
- - Inject additional context into conversations
27
- - Customize application behavior based on events
28
- - Integrate with external systems and services
29
- - Modify tool inputs or responses programmatically
30
-
31
- ## Hook Types
32
-
33
- Matilda Code supports four hook executor types:
34
-
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
- | `prompt` | Use an LLM to evaluate hook input and return a decision. |
41
-
42
- ### Command Hooks
43
-
44
- Command hooks execute commands via child processes. Input JSON is passed through stdin, and output is returned via stdout.
45
-
46
- **Configuration:**
47
-
48
- | Field | Type | Required | Description |
49
- | :-------------- | :----------------------- | :------- | :------------------------------------------ |
50
- | `type` | `"command"` | Yes | Hook type |
51
- | `command` | `string` | Yes | Command to execute |
52
- | `name` | `string` | No | Hook name (for logging) |
53
- | `description` | `string` | No | Hook description |
54
- | `timeout` | `number` | No | Timeout in seconds, default 60 |
55
- | `async` | `boolean` | No | Whether to run asynchronously in background |
56
- | `env` | `Record<string, string>` | No | Environment variables |
57
- | `shell` | `"bash" \| "powershell"` | No | Shell to use |
58
- | `statusMessage` | `string` | No | Status message displayed during execution |
59
-
60
- `timeout` is in seconds for command, HTTP and prompt hooks, as in Claude Code; SDK-registered function hooks keep milliseconds. Earlier versions read command hook timeouts as milliseconds, so rewrite any such value in seconds, for example `10000` as `10`; otherwise it is read as 10000 seconds. A command hook `timeout` that is not a positive number, such as `"30s"`, is ignored and the 60 second default applies, and one longer than about 24.8 days, the longest a timer supports, is capped there.
61
-
62
- **Example:**
63
-
64
- ```json
65
- {
66
- "hooks": {
67
- "PreToolUse": [
68
- {
69
- "matcher": "WriteFile",
70
- "hooks": [
71
- {
72
- "type": "command",
73
- "command": "$MATILDA_PROJECT_DIR/.matilda/hooks/security-check.sh",
74
- "name": "security-check",
75
- "timeout": 10
76
- }
77
- ]
78
- }
79
- ]
80
- }
81
- }
82
- ```
83
-
84
- ### HTTP Hooks
85
-
86
- 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.
87
-
88
- **Configuration:**
89
-
90
- | Field | Type | Required | Description |
91
- | :--------------- | :----------------------- | :------- | :-------------------------------------------------------- |
92
- | `type` | `"http"` | Yes | Hook type |
93
- | `url` | `string` | Yes | Target URL |
94
- | `headers` | `Record<string, string>` | No | Request headers (supports env var interpolation) |
95
- | `allowedEnvVars` | `string[]` | No | Whitelist of environment variables allowed in URL/headers |
96
- | `timeout` | `number` | No | Timeout in seconds, default 600 |
97
- | `name` | `string` | No | Hook name (for logging) |
98
- | `statusMessage` | `string` | No | Status message displayed during execution |
99
- | `once` | `boolean` | No | Execute only once per event per session (HTTP hooks only) |
100
-
101
- **Security Features:**
102
-
103
- - **URL Whitelist**: Configure allowed URL patterns via `allowedUrls`
104
- - **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)
105
- - **DNS Validation**: Validates domain resolution before requests to prevent DNS rebinding attacks
106
- - **Environment Variable Interpolation**: `${VAR}` syntax, only allows variables in `allowedEnvVars` whitelist
107
-
108
- **Example:**
109
-
110
- ```json
111
- {
112
- "hooks": {
113
- "PreToolUse": [
114
- {
115
- "matcher": "*",
116
- "hooks": [
117
- {
118
- "type": "http",
119
- "url": "http://127.0.0.1:8080/hooks/pre-tool-use",
120
- "headers": {
121
- "Authorization": "Bearer ${HOOK_API_KEY}"
122
- },
123
- "allowedEnvVars": ["HOOK_API_KEY"],
124
- "timeout": 10,
125
- "name": "remote-security-check"
126
- }
127
- ]
128
- }
129
- ]
130
- }
131
- }
132
- ```
133
-
134
- ### Function Hooks
135
-
136
- 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.
137
-
138
- **Note**: For most use cases, use **command hooks** or **HTTP hooks** instead, which can be configured in settings files.
139
-
140
- ### Prompt Hooks
141
-
142
- Prompt hooks use an LLM to evaluate hook input and return a decision. This is useful for making intelligent decisions based on context, such as determining whether to allow or block an operation.
143
-
144
- **How it works:**
145
-
146
- 1. The hook input JSON is injected into your prompt using the `$ARGUMENTS` placeholder
147
- 2. The prompt is sent to an LLM (default: your current model)
148
- 3. The LLM returns a JSON response with the decision
149
- 4. Matilda Code processes the decision and continues or blocks execution accordingly
150
-
151
- **Configuration:**
152
-
153
- | Field | Type | Required | Description |
154
- | :-------------- | :--------- | :------- | :-------------------------------------------------- |
155
- | `type` | `"prompt"` | Yes | Hook type |
156
- | `prompt` | `string` | Yes | Prompt sent to LLM. Use `$ARGUMENTS` for hook input |
157
- | `model` | `string` | No | Model to use (defaults to your current model) |
158
- | `timeout` | `number` | No | Timeout in seconds, default 30 |
159
- | `name` | `string` | No | Hook name (for logging) |
160
- | `description` | `string` | No | Hook description |
161
- | `statusMessage` | `string` | No | Status message displayed during execution |
162
-
163
- **Response Format:**
164
-
165
- The LLM must return JSON with the following structure:
166
-
167
- ```json
168
- {
169
- "ok": true,
170
- "reason": "Explanation of the decision",
171
- "additionalContext": "Optional context to inject into the conversation"
172
- }
173
- ```
174
-
175
- | Field | Description |
176
- | :------------------ | :------------------------------------------------------------------------- |
177
- | `ok` | `true` to allow/continue, `false` to block/stop |
178
- | `reason` | Required when `ok` is `false`. Shown to the model to explain the block |
179
- | `additionalContext` | Optional. Additional context to inject into the conversation when allowing |
180
-
181
- **Supported Events:**
182
-
183
- Prompt hooks can be used with most hook events, including:
184
-
185
- - `PreToolUse` - Evaluate whether to allow a tool call
186
- - `PostToolUse` - Evaluate tool results and potentially inject context
187
- - `Stop` - Determine whether to continue or stop
188
- - `SubagentStop` - Evaluate subagent results
189
- - `UserPromptSubmit` - Evaluate or enrich user prompts
190
-
191
- **Example: Stop Hook**
192
-
193
- ```json
194
- {
195
- "hooks": {
196
- "Stop": [
197
- {
198
- "hooks": [
199
- {
200
- "type": "prompt",
201
- "prompt": "You are evaluating whether Matilda Code should stop working. Context: $ARGUMENTS\n\nAnalyze the conversation and determine if:\n1. All user-requested tasks are complete\n2. Any errors need to be addressed\n3. Follow-up work is needed\n\nRespond with JSON: {\"ok\": true} to allow stopping, or {\"ok\": false, \"reason\": \"your explanation\"} to continue working.",
202
- "timeout": 30
203
- }
204
- ]
205
- }
206
- ]
207
- }
208
- }
209
- ```
210
-
211
- When `ok` is `false`, Matilda Code will continue working and use the `reason` as context for the next response.
212
-
213
- **Example: PreToolUse Hook**
214
-
215
- ```json
216
- {
217
- "hooks": {
218
- "PreToolUse": [
219
- {
220
- "matcher": "Bash",
221
- "hooks": [
222
- {
223
- "type": "prompt",
224
- "prompt": "Evaluate this tool call for security concerns. Tool input: $ARGUMENTS\n\nCheck for:\n- Dangerous commands (rm -rf, curl | sh, etc.)\n- Unauthorized access attempts\n- Data exfiltration patterns\n\nRespond with {\"ok\": true} if safe, or {\"ok\": false, \"reason\": \"concern\"} if blocked.",
225
- "model": "sonnet",
226
- "timeout": 30,
227
- "name": "security-evaluator"
228
- }
229
- ]
230
- }
231
- ]
232
- }
233
- }
234
- ```
235
-
236
- ## Hook Events
237
-
238
- Hooks fire at specific points during a Matilda Code session. Different events support different matchers to filter trigger conditions.
239
-
240
- | Event | Triggered When | Matcher Target |
241
- | :------------------- | :---------------------------------------- | :-------------------------------------------------------- |
242
- | `PreToolUse` | Before tool execution | Tool name (`WriteFile`, `ReadFile`, `Bash`, etc.) |
243
- | `PostToolUse` | After successful tool execution | Tool name |
244
- | `PostToolUseFailure` | After tool execution fails | Tool name |
245
- | `UserPromptSubmit` | After user submits prompt | None (always fires) |
246
- | `SessionStart` | When session starts or resumes | Source (`startup`, `resume`, `clear`, `compact`) |
247
- | `SessionEnd` | When session ends | Reason (`clear`, `logout`, `prompt_input_exit`, etc.) |
248
- | `Stop` | When Claude prepares to conclude response | None (always fires) |
249
- | `SubagentStart` | When subagent starts | Agent type (`Bash`, `Explorer`, `Plan`, etc.) |
250
- | `SubagentStop` | When subagent stops | Agent type |
251
- | `PreCompact` | Before conversation compaction | Trigger (`manual`, `auto`) |
252
- | `Notification` | When notifications are sent | Type (`permission_prompt`, `idle_prompt`, `auth_success`) |
253
- | `PermissionRequest` | When permission dialog is shown | Tool name |
254
- | `TodoCreated` | When a new todo item is created | None (always fires) |
255
- | `TodoCompleted` | When a todo item is marked as completed | None (always fires) |
256
-
257
- ### Matcher Patterns
258
-
259
- `matcher` is a regular expression used to filter trigger conditions.
260
-
261
- | Event Type | Events | Matcher Support | Matcher Target |
262
- | :------------------ | :--------------------------------------------------------------------- | :-------------- | :------------------------------------------------------- |
263
- | Tool Events | `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` | ✅ Regex | Tool name: `WriteFile`, `ReadFile`, `Bash`, etc. |
264
- | Subagent Events | `SubagentStart`, `SubagentStop` | ✅ Regex | Agent type: `Bash`, `Explorer`, etc. |
265
- | Session Events | `SessionStart` | ✅ Regex | Source: `startup`, `resume`, `clear`, `compact` |
266
- | Session Events | `SessionEnd` | ✅ Regex | Reason: `clear`, `logout`, `prompt_input_exit`, etc. |
267
- | Notification Events | `Notification` | ✅ Exact match | Type: `permission_prompt`, `idle_prompt`, `auth_success` |
268
- | Compact Events | `PreCompact` | ✅ Exact match | Trigger: `manual`, `auto` |
269
- | Todo Events | `TodoCreated`, `TodoCompleted` | ❌ No | N/A |
270
- | Prompt Events | `UserPromptSubmit` | ❌ No | N/A |
271
- | Stop Events | `Stop` | ❌ No | N/A |
272
-
273
- **Matcher Syntax:**
274
-
275
- - Empty string `""` or `"*"` matches all events of that type
276
- - Standard regex syntax supported (e.g., `^Bash$`, `Read.*`, `(WriteFile|Edit)`)
277
-
278
- **Examples:**
279
-
280
- ```json
281
- {
282
- "hooks": {
283
- "PreToolUse": [
284
- {
285
- "matcher": "^Bash$",
286
- "hooks": [
287
- {
288
- "type": "command",
289
- "command": "echo 'bash check' >> /tmp/hooks.log"
290
- }
291
- ]
292
- },
293
- {
294
- "matcher": "Write.*",
295
- "hooks": [
296
- {
297
- "type": "command",
298
- "command": "echo 'write check' >> /tmp/hooks.log"
299
- }
300
- ]
301
- },
302
- {
303
- "matcher": "*",
304
- "hooks": [
305
- { "type": "command", "command": "echo 'all tools' >> /tmp/hooks.log" }
306
- ]
307
- }
308
- ],
309
- "SubagentStart": [
310
- {
311
- "matcher": "^(Bash|Explorer)$",
312
- "hooks": [
313
- {
314
- "type": "command",
315
- "command": "echo 'subagent check' >> /tmp/hooks.log"
316
- }
317
- ]
318
- }
319
- ]
320
- }
321
- }
322
- ```
323
-
324
- ## Input/Output Rules
325
-
326
- ### Hook Input Structure
327
-
328
- All hooks receive standardized input in JSON format through stdin (command) or POST body (http).
329
-
330
- **Common Fields:**
331
-
332
- ```json
333
- {
334
- "session_id": "string",
335
- "transcript_path": "string",
336
- "cwd": "string",
337
- "hook_event_name": "string",
338
- "timestamp": "string"
339
- }
340
- ```
341
-
342
- Event-specific fields are added based on the hook type. When running in a subagent, `agent_id` and `agent_type` are additionally included.
343
-
344
- ### Hook Output Structure
345
-
346
- Hook output is returned via `stdout` (command) or HTTP response body (http) as JSON.
347
-
348
- **Exit Code Behavior (Command Hooks):**
349
-
350
- | Exit Code | Behavior |
351
- | :-------- | :------------------------------------------------------------------------------------ |
352
- | `0` | Success. Parse JSON in `stdout` to control behavior. |
353
- | `2` | **Blocking error**. Ignores `stdout`, passes `stderr` as error feedback to the model. |
354
- | Other | Non-blocking error. `stderr` only shown in debug mode, execution continues. |
355
-
356
- **Output Structure:**
357
-
358
- Hook output supports three categories of fields:
359
-
360
- 1. **Common Fields**: `continue`, `stopReason`, `suppressOutput`, `systemMessage`
361
- 2. **Top-level Decision**: `decision`, `reason` (used by some events)
362
- 3. **Event-specific Control**: `hookSpecificOutput` (must include `hookEventName`)
363
-
364
- ```json
365
- {
366
- "continue": true,
367
- "decision": "allow",
368
- "reason": "Operation approved",
369
- "hookSpecificOutput": {
370
- "hookEventName": "PreToolUse",
371
- "additionalContext": "Additional context information"
372
- }
373
- }
374
- ```
375
-
376
- ### Individual Hook Event Details
377
-
378
- #### PreToolUse
379
-
380
- **Purpose**: Executed before a tool is used to allow for permission checks, input validation, or context injection.
381
-
382
- **Event-specific fields**:
383
-
384
- ```json
385
- {
386
- "permission_mode": "default | plan | auto_edit | yolo",
387
- "tool_name": "name of the tool being executed",
388
- "tool_input": "object containing the tool's input parameters",
389
- "tool_use_id": "unique identifier for this tool use instance"
390
- }
391
- ```
392
-
393
- **Output Options**:
394
-
395
- - `hookSpecificOutput.permissionDecision`: "allow", "deny", or "ask" (REQUIRED)
396
- - `hookSpecificOutput.permissionDecisionReason`: explanation for the decision (REQUIRED)
397
- - `hookSpecificOutput.updatedInput`: modified tool input parameters to use instead of original
398
- - `hookSpecificOutput.additionalContext`: additional context information
399
-
400
- **Note**: While standard hook output fields like `decision` and `reason` are technically supported by the underlying class, the official interface expects the `hookSpecificOutput` with `permissionDecision` and `permissionDecisionReason`.
401
-
402
- **Example Output**:
403
-
404
- ```json
405
- {
406
- "hookSpecificOutput": {
407
- "hookEventName": "PreToolUse",
408
- "permissionDecision": "deny",
409
- "permissionDecisionReason": "Security policy blocks database writes",
410
- "additionalContext": "Current environment: production. Proceed with caution."
411
- }
412
- }
413
- ```
414
-
415
- #### PostToolUse
416
-
417
- **Purpose**: Executed after a tool completes successfully to process results, log outcomes, or inject additional context.
418
-
419
- **Event-specific fields**:
420
-
421
- ```json
422
- {
423
- "permission_mode": "default | plan | auto_edit | yolo",
424
- "tool_name": "name of the tool that was executed",
425
- "tool_input": "object containing the tool's input parameters",
426
- "tool_response": "object containing the tool's response",
427
- "tool_use_id": "unique identifier for this tool use instance"
428
- }
429
- ```
430
-
431
- **Output Options**:
432
-
433
- - `decision`: "allow", "deny", "block" (defaults to "allow" if not specified)
434
- - `reason`: reason for the decision
435
- - `hookSpecificOutput.additionalContext`: additional information to be included
436
-
437
- **Example Output**:
438
-
439
- ```json
440
- {
441
- "decision": "allow",
442
- "reason": "Tool executed successfully",
443
- "hookSpecificOutput": {
444
- "additionalContext": "File modification recorded in audit log"
445
- }
446
- }
447
- ```
448
-
449
- #### PostToolUseFailure
450
-
451
- **Purpose**: Executed when a tool execution fails to handle errors, send alerts, or record failures.
452
-
453
- **Event-specific fields**:
454
-
455
- ```json
456
- {
457
- "permission_mode": "default | plan | auto_edit | yolo",
458
- "tool_use_id": "unique identifier for the tool use",
459
- "tool_name": "name of the tool that failed",
460
- "tool_input": "object containing the tool's input parameters",
461
- "error": "error message describing the failure",
462
- "is_interrupt": "boolean indicating if failure was due to user interruption (optional)"
463
- }
464
- ```
465
-
466
- **Output Options**:
467
-
468
- - `hookSpecificOutput.additionalContext`: error handling information
469
- - Standard hook output fields
470
-
471
- **Example Output**:
472
-
473
- ```json
474
- {
475
- "hookSpecificOutput": {
476
- "additionalContext": "Error: File not found. Failure logged in monitoring system."
477
- }
478
- }
479
- ```
480
-
481
- #### UserPromptSubmit
482
-
483
- **Purpose**: Executed when the user submits a prompt to modify, validate, or enrich the input.
484
-
485
- **Event-specific fields**:
486
-
487
- ```json
488
- {
489
- "prompt": "the user's submitted prompt text"
490
- }
491
- ```
492
-
493
- **Output Options**:
494
-
495
- - `decision`: "allow", "deny", "block", or "ask"
496
- - `reason`: human-readable explanation for the decision
497
- - `hookSpecificOutput.additionalContext`: additional context to append to the prompt (optional)
498
-
499
- **Note**: Since UserPromptSubmitOutput extends HookOutput, all standard fields are available but only additionalContext in hookSpecificOutput is specifically defined for this event.
500
-
501
- **Example Output**:
502
-
503
- ```json
504
- {
505
- "decision": "allow",
506
- "reason": "Prompt reviewed and approved",
507
- "hookSpecificOutput": {
508
- "additionalContext": "Remember to follow company coding standards."
509
- }
510
- }
511
- ```
512
-
513
- #### SessionStart
514
-
515
- **Purpose**: Executed when a new session starts to perform initialization tasks.
516
-
517
- **Event-specific fields**:
518
-
519
- ```json
520
- {
521
- "permission_mode": "default | plan | auto_edit | yolo",
522
- "source": "startup | resume | clear | compact",
523
- "model": "the model being used",
524
- "agent_type": "the type of agent if applicable (optional)"
525
- }
526
- ```
527
-
528
- **Output Options**:
529
-
530
- - `hookSpecificOutput.additionalContext`: context to be available in the session
531
- - Standard hook output fields
532
-
533
- **Example Output**:
534
-
535
- ```json
536
- {
537
- "hookSpecificOutput": {
538
- "additionalContext": "Session started with security policies enabled."
539
- }
540
- }
541
- ```
542
-
543
- #### SessionEnd
544
-
545
- **Purpose**: Executed when a session ends to perform cleanup tasks.
546
-
547
- **Event-specific fields**:
548
-
549
- ```json
550
- {
551
- "reason": "clear | logout | prompt_input_exit | bypass_permissions_disabled | other"
552
- }
553
- ```
554
-
555
- **Output Options**:
556
-
557
- - Standard hook output fields (typically not used for blocking)
558
-
559
- #### Stop
560
-
561
- **Purpose**: Executed before Matilda concludes its response to provide final feedback or summaries.
562
-
563
- **Event-specific fields**:
564
-
565
- ```json
566
- {
567
- "stop_hook_active": "boolean indicating if stop hook is active",
568
- "last_assistant_message": "the last message from the assistant"
569
- }
570
- ```
571
-
572
- **Output Options**:
573
-
574
- - `decision`: "allow", "deny", "block", or "ask"
575
- - `reason`: human-readable explanation for the decision
576
- - `stopReason`: feedback to include in the stop response
577
- - `continue`: set to false to stop execution
578
- - `hookSpecificOutput.additionalContext`: additional context information
579
-
580
- **Note**: Since StopOutput extends HookOutput, all standard fields are available but the stopReason field is particularly relevant for this event.
581
-
582
- **Example Output**:
583
-
584
- ```json
585
- {
586
- "decision": "block",
587
- "reason": "Must be provided when Matilda Code is blocked from stopping"
588
- }
589
- ```
590
-
591
- #### StopFailure
592
-
593
- **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.
594
-
595
- **Event-specific fields**:
596
-
597
- ```json
598
- {
599
- "error": "rate_limit | authentication_failed | billing_error | invalid_request | server_error | max_output_tokens | unknown",
600
- "error_details": "detailed error message (optional)",
601
- "last_assistant_message": "the last message from the assistant before the error (optional)"
602
- }
603
- ```
604
-
605
- **Matcher**: Matches against the `error` field. For example, `"matcher": "rate_limit"` will only trigger for rate limit errors.
606
-
607
- **Output Options**:
608
-
609
- - **None** - StopFailure is fire-and-forget. All hook output and exit codes are ignored.
610
-
611
- **Exit Code Handling**:
612
-
613
- | Exit Code | Behavior |
614
- | --------- | ------------------------- |
615
- | Any | Ignored (fire-and-forget) |
616
-
617
- **Example Configuration**:
618
-
619
- ```json
620
- {
621
- "hooks": {
622
- "StopFailure": [
623
- {
624
- "matcher": "rate_limit",
625
- "hooks": [
626
- {
627
- "type": "command",
628
- "command": "/path/to/rate-limit-alert.sh",
629
- "name": "rate-limit-alerter"
630
- }
631
- ]
632
- }
633
- ]
634
- }
635
- }
636
- ```
637
-
638
- **Use Cases**:
639
-
640
- - Rate limit monitoring and alerting
641
- - Authentication failure logging
642
- - Billing error notifications
643
- - Error statistics collection
644
-
645
- #### SubagentStart
646
-
647
- **Purpose**: Executed when a subagent (like the Task tool) is started to set up context or permissions.
648
-
649
- **Event-specific fields**:
650
-
651
- ```json
652
- {
653
- "permission_mode": "default | plan | auto_edit | yolo",
654
- "agent_id": "identifier for the subagent",
655
- "agent_type": "type of agent (Bash, Explorer, Plan, Custom, etc.)"
656
- }
657
- ```
658
-
659
- **Output Options**:
660
-
661
- - `hookSpecificOutput.additionalContext`: initial context for the subagent
662
- - Standard hook output fields
663
-
664
- **Example Output**:
665
-
666
- ```json
667
- {
668
- "hookSpecificOutput": {
669
- "additionalContext": "Subagent initialized with restricted permissions."
670
- }
671
- }
672
- ```
673
-
674
- #### SubagentStop
675
-
676
- **Purpose**: Executed when a subagent finishes to perform finalization tasks.
677
-
678
- **Event-specific fields**:
679
-
680
- ```json
681
- {
682
- "permission_mode": "default | plan | auto_edit | yolo",
683
- "stop_hook_active": "boolean indicating if stop hook is active",
684
- "agent_id": "identifier for the subagent",
685
- "agent_type": "type of agent",
686
- "agent_transcript_path": "path to the subagent's transcript",
687
- "last_assistant_message": "the last message from the subagent"
688
- }
689
- ```
690
-
691
- **Output Options**:
692
-
693
- - `decision`: "allow", "deny", "block", or "ask"
694
- - `reason`: human-readable explanation for the decision
695
-
696
- **Example Output**:
697
-
698
- ```json
699
- {
700
- "decision": "block",
701
- "reason": "Must be provided when Matilda Code is blocked from stopping"
702
- }
703
- ```
704
-
705
- #### PreCompact
706
-
707
- **Purpose**: Executed before conversation compaction to prepare or log the compaction.
708
-
709
- **Event-specific fields**:
710
-
711
- ```json
712
- {
713
- "trigger": "manual | auto",
714
- "custom_instructions": "custom instructions currently set"
715
- }
716
- ```
717
-
718
- **Output Options**:
719
-
720
- - `hookSpecificOutput.additionalContext`: context to include before compaction
721
- - Standard hook output fields
722
-
723
- **Example Output**:
724
-
725
- ```json
726
- {
727
- "hookSpecificOutput": {
728
- "additionalContext": "Compacting conversation to maintain optimal context window."
729
- }
730
- }
731
- ```
732
-
733
- #### PostCompact
734
-
735
- **Purpose**: Executed after conversation compaction completes to archive summaries or track usage.
736
-
737
- **Event-specific fields**:
738
-
739
- ```json
740
- {
741
- "trigger": "manual | auto",
742
- "compact_summary": "the summary generated by the compaction process"
743
- }
744
- ```
745
-
746
- **Matcher**: Matches against the `trigger` field. For example, `"matcher": "manual"` will only trigger for manual compaction via `/compact` command.
747
-
748
- **Output Options**:
749
-
750
- - `hookSpecificOutput.additionalContext`: additional context (for logging only)
751
- - Standard hook output fields (for logging only)
752
-
753
- **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.
754
-
755
- **Exit Code Handling**:
756
-
757
- | Exit Code | Behavior |
758
- | --------- | --------------------------------------------------------- |
759
- | 0 | Success - stdout shown to user in verbose mode |
760
- | Other | Non-blocking error - stderr shown to user in verbose mode |
761
-
762
- **Example Configuration**:
763
-
764
- ```json
765
- {
766
- "hooks": {
767
- "PostCompact": [
768
- {
769
- "matcher": "manual",
770
- "hooks": [
771
- {
772
- "type": "command",
773
- "command": "/path/to/save-compact-summary.sh",
774
- "name": "save-summary"
775
- }
776
- ]
777
- }
778
- ]
779
- }
780
- }
781
- ```
782
-
783
- **Use Cases**:
784
-
785
- - Summary archiving to files or databases
786
- - Usage statistics tracking
787
- - Context change monitoring
788
- - Audit logging for compaction operations
789
-
790
- #### Notification
791
-
792
- **Purpose**: Executed when notifications are sent to customize or intercept them.
793
-
794
- **Event-specific fields**:
795
-
796
- ```json
797
- {
798
- "message": "notification message content",
799
- "title": "notification title (optional)",
800
- "notification_type": "permission_prompt | idle_prompt | auth_success"
801
- }
802
- ```
803
-
804
- > **Note**: `elicitation_dialog` type is defined but not currently implemented.
805
-
806
- **Output Options**:
807
-
808
- - `hookSpecificOutput.additionalContext`: additional information to include
809
- - Standard hook output fields
810
-
811
- **Example Output**:
812
-
813
- ```json
814
- {
815
- "hookSpecificOutput": {
816
- "additionalContext": "Notification processed by monitoring system."
817
- }
818
- }
819
- ```
820
-
821
- #### PermissionRequest
822
-
823
- **Purpose**: Executed when permission dialogs are displayed to automate decisions or update permissions.
824
-
825
- **Event-specific fields**:
826
-
827
- ```json
828
- {
829
- "permission_mode": "default | plan | auto_edit | yolo",
830
- "tool_name": "name of the tool requesting permission",
831
- "tool_input": "object containing the tool's input parameters",
832
- "permission_suggestions": "array of suggested permissions (optional)"
833
- }
834
- ```
835
-
836
- **Output Options**:
837
-
838
- - `hookSpecificOutput.decision`: structured object with permission decision details:
839
- - `behavior`: "allow" or "deny"
840
- - `updatedInput`: modified tool input (optional)
841
- - `updatedPermissions`: modified permissions (optional)
842
- - `message`: message to show to user (optional)
843
- - `interrupt`: whether to interrupt the workflow (optional)
844
-
845
- **Example Output**:
846
-
847
- ```json
848
- {
849
- "hookSpecificOutput": {
850
- "decision": {
851
- "behavior": "allow",
852
- "message": "Permission granted based on security policy",
853
- "interrupt": false
854
- }
855
- }
856
- }
857
- ```
858
-
859
- #### TodoCreated
860
-
861
- **Purpose**: Executed when a new todo item is created via the `todo_write` tool. Allows validation, logging, or blocking of todo creation.
862
-
863
- Todo hooks run in two phases:
864
-
865
- - `validation`: runs before persistence. Use this phase for validation only; returning `block` or `deny` prevents the write.
866
- - `postWrite`: runs after persistence. Use this phase for side effects such as logging or syncing; `block` or `deny` is ignored in this phase.
867
-
868
- **Event-specific fields**:
869
-
870
- ```json
871
- {
872
- "todo_id": "unique identifier for the todo item",
873
- "todo_content": "content/description of the todo item",
874
- "todo_status": "pending | in_progress | completed",
875
- "all_todos": "array of all todo items in the current list",
876
- "phase": "validation | postWrite"
877
- }
878
- ```
879
-
880
- **Output Options**:
881
-
882
- - `decision`: "allow", "block", or "deny"
883
- - `reason`: human-readable explanation for the decision (required when blocking)
884
-
885
- **Blocking Behavior**:
886
-
887
- During the `validation` phase, when `decision` is `block` or `deny` (exit code 2), todo creation is prevented. The todo list remains unchanged, and the reason is provided as feedback to the model.
888
-
889
- During the `postWrite` phase, the todo has already been persisted. Hooks may still return output, but `block` / `deny` does not undo the write and should not be used for validation.
890
-
891
- **Example Output (Allow)**:
892
-
893
- ```json
894
- {
895
- "decision": "allow",
896
- "reason": "Todo content validated successfully"
897
- }
898
- ```
899
-
900
- **Example Output (Block)**:
901
-
902
- ```json
903
- {
904
- "decision": "block",
905
- "reason": "Todo content too short. Minimum 5 characters required."
906
- }
907
- ```
908
-
909
- **Example Hook Script**:
910
-
911
- ```bash
912
- #!/bin/bash
913
- # ~/.matilda/hooks/todo-validator.sh
914
- # Validates todo content before creation
915
-
916
- INPUT=$(cat)
917
- CONTENT=$(echo "$INPUT" | jq -r '.todo_content')
918
-
919
- # Check minimum length
920
- if [ ${#CONTENT} -lt 5 ]; then
921
- echo '{"decision": "block", "reason": "Todo content must be at least 5 characters"}'
922
- exit 2
923
- fi
924
-
925
- # Block test-related todos
926
- if [[ "$CONTENT" =~ "test" ]]; then
927
- echo '{"decision": "block", "reason": "Test todos are not allowed in production"}'
928
- exit 2
929
- fi
930
-
931
- echo '{"decision": "allow"}'
932
- exit 0
933
- ```
934
-
935
- **Example Configuration**:
936
-
937
- ```json
938
- {
939
- "hooks": {
940
- "TodoCreated": [
941
- {
942
- "hooks": [
943
- {
944
- "type": "command",
945
- "command": "$HOME/.matilda/hooks/todo-validator.sh",
946
- "name": "todo-validator",
947
- "timeout": 5
948
- }
949
- ]
950
- }
951
- ]
952
- }
953
- }
954
- ```
955
-
956
- #### TodoCompleted
957
-
958
- **Purpose**: Executed when a todo item is marked as completed. Allows validation, logging, or blocking of todo completion.
959
-
960
- Todo hooks run in two phases:
961
-
962
- - `validation`: runs before persistence. Use this phase for validation only; returning `block` or `deny` prevents the write.
963
- - `postWrite`: runs after persistence. Use this phase for side effects such as logging or syncing; `block` or `deny` is ignored in this phase.
964
-
965
- **Event-specific fields**:
966
-
967
- ```json
968
- {
969
- "todo_id": "unique identifier for the todo item",
970
- "todo_content": "content/description of the todo item",
971
- "previous_status": "pending | in_progress (status before completion)",
972
- "all_todos": "array of all todo items in the current list",
973
- "phase": "validation | postWrite"
974
- }
975
- ```
976
-
977
- **Output Options**:
978
-
979
- - `decision`: "allow", "block", or "deny"
980
- - `reason`: human-readable explanation for the decision (required when blocking)
981
-
982
- **Blocking Behavior**:
983
-
984
- During the `validation` phase, when `decision` is `block` or `deny` (exit code 2), todo completion is prevented. The todo item remains in its previous status, and the reason is provided as feedback to the model.
985
-
986
- During the `postWrite` phase, the todo has already been persisted. Hooks may still return output, but `block` / `deny` does not undo the write and should not be used for validation.
987
-
988
- **Example Output (Allow)**:
989
-
990
- ```json
991
- {
992
- "decision": "allow",
993
- "reason": "Todo completion approved"
994
- }
995
- ```
996
-
997
- **Example Output (Block)**:
998
-
999
- ```json
1000
- {
1001
- "decision": "block",
1002
- "reason": "Cannot complete this todo until dependent tasks are finished."
1003
- }
1004
- ```
1005
-
1006
- **Example Hook Script**:
1007
-
1008
- ```bash
1009
- #!/bin/bash
1010
- # ~/.matilda/hooks/todo-completion-validator.sh
1011
- # Validates todo completion conditions
1012
-
1013
- INPUT=$(cat)
1014
- TODO_ID=$(echo "$INPUT" | jq -r '.todo_id')
1015
- ALL_TODOS=$(echo "$INPUT" | jq -r '.all_todos')
1016
-
1017
- # Check if there are incomplete dependent todos (example logic)
1018
- INCOMPLETE_COUNT=$(echo "$ALL_TODOS" | jq '[.[] | select(.status != "completed")] | length')
1019
-
1020
- if [ "$INCOMPLETE_COUNT" -gt 5 ]; then
1021
- echo '{"decision": "block", "reason": "Too many incomplete todos. Complete other tasks first."}'
1022
- exit 2
1023
- fi
1024
-
1025
- echo '{"decision": "allow"}'
1026
- exit 0
1027
- ```
1028
-
1029
- **Example Configuration**:
1030
-
1031
- ```json
1032
- {
1033
- "hooks": {
1034
- "TodoCompleted": [
1035
- {
1036
- "hooks": [
1037
- {
1038
- "type": "command",
1039
- "command": "$HOME/.matilda/hooks/todo-completion-validator.sh",
1040
- "name": "completion-validator",
1041
- "timeout": 5
1042
- }
1043
- ]
1044
- }
1045
- ]
1046
- }
1047
- }
1048
- ```
1049
-
1050
- **Use Cases**:
1051
-
1052
- - **Logging**: Track todo creation and completion for audit or analytics
1053
- - **Validation**: Enforce content quality standards (minimum length, required keywords)
1054
- - **Workflow Control**: Block completion until prerequisites are met
1055
- - **Integration**: Sync todos with external task management systems (Jira, Trello, etc.)
1056
-
1057
- ## Hook Configuration
1058
-
1059
- Hooks are configured in Matilda Code settings, typically in `.matilda/settings.json` or user configuration files:
1060
-
1061
- ```json
1062
- {
1063
- "hooks": {
1064
- "PreToolUse": [
1065
- {
1066
- "matcher": "^Bash$",
1067
- "sequential": false,
1068
- "hooks": [
1069
- {
1070
- "type": "command",
1071
- "command": "/path/to/security-check.sh",
1072
- "name": "security-check",
1073
- "description": "Run security checks before tool execution",
1074
- "timeout": 30
1075
- }
1076
- ]
1077
- }
1078
- ],
1079
- "SessionStart": [
1080
- {
1081
- "hooks": [
1082
- {
1083
- "type": "command",
1084
- "command": "echo 'Session started'",
1085
- "name": "session-init"
1086
- }
1087
- ]
1088
- }
1089
- ]
1090
- }
1091
- }
1092
- ```
1093
-
1094
- ## Hook Execution
1095
-
1096
- ### Parallel vs Sequential Execution
1097
-
1098
- - By default, hooks execute in parallel for better performance
1099
- - Use `sequential: true` in hook definition to enforce order-dependent execution
1100
- - Sequential hooks can modify input for subsequent hooks in the chain
1101
-
1102
- ### Async Hooks
1103
-
1104
- Only `command` type supports asynchronous execution. Setting `"async": true` runs the hook in the background without blocking the main flow.
1105
-
1106
- **Features:**
1107
-
1108
- - Cannot return decision control (operation has already occurred)
1109
- - Results are injected in the next conversation turn via `systemMessage` or `additionalContext`
1110
- - Suitable for auditing, logging, background testing, etc.
1111
-
1112
- **Example:**
1113
-
1114
- ```json
1115
- {
1116
- "hooks": {
1117
- "PostToolUse": [
1118
- {
1119
- "matcher": "WriteFile|Edit",
1120
- "hooks": [
1121
- {
1122
- "type": "command",
1123
- "command": "$MATILDA_PROJECT_DIR/.matilda/hooks/run-tests-async.sh",
1124
- "async": true,
1125
- "timeout": 300
1126
- }
1127
- ]
1128
- }
1129
- ]
1130
- }
1131
- }
1132
- ```
1133
-
1134
- ```bash
1135
- #!/bin/bash
1136
- INPUT=$(cat)
1137
- FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
1138
- if [[ "$FILE_PATH" != *.ts && "$FILE_PATH" != *.js ]]; then exit 0; fi
1139
- RESULT=$(npm test 2>&1)
1140
- if [ $? -eq 0 ]; then
1141
- echo "{\"systemMessage\": \"Tests passed after editing $FILE_PATH\"}"
1142
- else
1143
- echo "{\"systemMessage\": \"Tests failed: $RESULT\"}"
1144
- fi
1145
- ```
1146
-
1147
- ### Security Model
1148
-
1149
- - Hooks run in the user's environment with user privileges
1150
- - Project-level hooks require trusted folder status
1151
- - Timeouts prevent hanging hooks (default: 60 seconds)
1152
-
1153
- ## Best Practices
1154
-
1155
- ### Example 1: Security Validation Hook
1156
-
1157
- A PreToolUse hook that logs and potentially blocks dangerous commands:
1158
-
1159
- **security_check.sh**
1160
-
1161
- ```bash
1162
- #!/bin/bash
1163
-
1164
- # Read input from stdin
1165
- INPUT=$(cat)
1166
-
1167
- # Parse the input to extract tool info
1168
- TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
1169
- TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input')
1170
-
1171
- # Check for potentially dangerous operations
1172
- if echo "$TOOL_INPUT" | grep -qiE "(rm.*-rf|mv.*\/|chmod.*777)"; then
1173
- echo '{
1174
- "hookSpecificOutput": {
1175
- "hookEventName": "PreToolUse",
1176
- "permissionDecision": "deny",
1177
- "permissionDecisionReason": "Security policy blocks dangerous command"
1178
- }
1179
- }'
1180
- exit 2 # Blocking error
1181
- fi
1182
-
1183
- # Log the operation
1184
- echo "INFO: Tool $TOOL_NAME executed safely at $(date)" >> /var/log/matilda-security.log
1185
-
1186
- # Allow with additional context
1187
- echo '{
1188
- "hookSpecificOutput": {
1189
- "hookEventName": "PreToolUse",
1190
- "permissionDecision": "allow",
1191
- "permissionDecisionReason": "Security check passed",
1192
- "additionalContext": "Command approved by security policy"
1193
- }
1194
- }'
1195
- exit 0
1196
- ```
1197
-
1198
- Configure in `.matilda/settings.json`:
1199
-
1200
- ```json
1201
- {
1202
- "hooks": {
1203
- "PreToolUse": [
1204
- {
1205
- "hooks": [
1206
- {
1207
- "type": "command",
1208
- "command": "${SECURITY_CHECK_SCRIPT}",
1209
- "name": "security-checker",
1210
- "description": "Security validation for bash commands",
1211
- "timeout": 10
1212
- }
1213
- ]
1214
- }
1215
- ]
1216
- }
1217
- }
1218
- ```
1219
-
1220
- ### Example 2: HTTP Audit Hook
1221
-
1222
- A PostToolUse HTTP hook that sends all tool execution records to a remote audit service:
1223
-
1224
- ```json
1225
- {
1226
- "hooks": {
1227
- "PostToolUse": [
1228
- {
1229
- "matcher": "*",
1230
- "hooks": [
1231
- {
1232
- "type": "http",
1233
- "url": "https://audit.example.com/api/tool-execution",
1234
- "headers": {
1235
- "Authorization": "Bearer ${AUDIT_API_TOKEN}",
1236
- "Content-Type": "application/json"
1237
- },
1238
- "allowedEnvVars": ["AUDIT_API_TOKEN"],
1239
- "timeout": 10,
1240
- "name": "audit-logger"
1241
- }
1242
- ]
1243
- }
1244
- ]
1245
- }
1246
- }
1247
- ```
1248
-
1249
- ### Example 3: User Prompt Validation Hook
1250
-
1251
- A UserPromptSubmit hook that validates user prompts for sensitive information and provides context for long prompts:
1252
-
1253
- **prompt_validator.py**
1254
-
1255
- ```python
1256
- import json
1257
- import sys
1258
- import re
1259
-
1260
- # Load input from stdin
1261
- try:
1262
- input_data = json.load(sys.stdin)
1263
- except json.JSONDecodeError as e:
1264
- print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
1265
- exit(1)
1266
-
1267
- user_prompt = input_data.get("prompt", "")
1268
-
1269
- # Sensitive words list
1270
- sensitive_words = ["password", "secret", "token", "api_key"]
1271
-
1272
- # Check for sensitive information
1273
- for word in sensitive_words:
1274
- if re.search(rf"\b{word}\b", user_prompt.lower()):
1275
- # Block prompts containing sensitive information
1276
- output = {
1277
- "decision": "block",
1278
- "reason": f"Prompt contains sensitive information '{word}'. Please remove sensitive content and resubmit.",
1279
- "hookSpecificOutput": {
1280
- "hookEventName": "UserPromptSubmit"
1281
- }
1282
- }
1283
- print(json.dumps(output))
1284
- exit(0)
1285
-
1286
- # Check prompt length and add warning context if too long
1287
- if len(user_prompt) > 1000:
1288
- output = {
1289
- "hookSpecificOutput": {
1290
- "hookEventName": "UserPromptSubmit",
1291
- "additionalContext": "Note: User submitted a long prompt. Please read carefully and ensure all requirements are understood."
1292
- }
1293
- }
1294
- print(json.dumps(output))
1295
- exit(0)
1296
-
1297
- # No processing needed for normal cases
1298
- exit(0)
1299
- ```
1300
-
1301
- ## Troubleshooting
1302
-
1303
- - Check application logs for hook execution details
1304
- - Verify hook script permissions and executability
1305
- - Ensure proper JSON formatting in hook outputs
1306
- - Use specific matcher patterns to avoid unintended hook execution
1307
- - Use `--debug` mode to see detailed hook matching and execution information
1308
- - Temporarily disable all hooks: add `"disableAllHooks": true` in settings