@dgxo/mashadevcli 1.1.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.
Files changed (140) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +393 -0
  3. package/bundle/builtin/skill-creator/SKILL.md +382 -0
  4. package/bundle/builtin/skill-creator/scripts/init_skill.cjs +239 -0
  5. package/bundle/builtin/skill-creator/scripts/package_skill.cjs +131 -0
  6. package/bundle/builtin/skill-creator/scripts/validate_skill.cjs +131 -0
  7. package/bundle/docs/CONTRIBUTING.md +1 -0
  8. package/bundle/docs/admin/enterprise-controls.md +115 -0
  9. package/bundle/docs/assets/connected_devtools.png +0 -0
  10. package/bundle/docs/assets/gemini-screenshot.png +0 -0
  11. package/bundle/docs/assets/monitoring-dashboard-logs.png +0 -0
  12. package/bundle/docs/assets/monitoring-dashboard-metrics.png +0 -0
  13. package/bundle/docs/assets/monitoring-dashboard-overview.png +0 -0
  14. package/bundle/docs/assets/release_patch.png +0 -0
  15. package/bundle/docs/assets/theme-ansi-light.png +0 -0
  16. package/bundle/docs/assets/theme-ansi.png +0 -0
  17. package/bundle/docs/assets/theme-atom-one.png +0 -0
  18. package/bundle/docs/assets/theme-ayu-light.png +0 -0
  19. package/bundle/docs/assets/theme-ayu.png +0 -0
  20. package/bundle/docs/assets/theme-custom.png +0 -0
  21. package/bundle/docs/assets/theme-default-light.png +0 -0
  22. package/bundle/docs/assets/theme-default.png +0 -0
  23. package/bundle/docs/assets/theme-dracula.png +0 -0
  24. package/bundle/docs/assets/theme-github-light.png +0 -0
  25. package/bundle/docs/assets/theme-github.png +0 -0
  26. package/bundle/docs/assets/theme-google-light.png +0 -0
  27. package/bundle/docs/assets/theme-xcode-light.png +0 -0
  28. package/bundle/docs/changelogs/index.md +867 -0
  29. package/bundle/docs/changelogs/latest.md +208 -0
  30. package/bundle/docs/changelogs/preview.md +187 -0
  31. package/bundle/docs/cli/checkpointing.md +93 -0
  32. package/bundle/docs/cli/cli-reference.md +115 -0
  33. package/bundle/docs/cli/creating-skills.md +80 -0
  34. package/bundle/docs/cli/custom-commands.md +327 -0
  35. package/bundle/docs/cli/enterprise.md +604 -0
  36. package/bundle/docs/cli/gemini-ignore.md +71 -0
  37. package/bundle/docs/cli/gemini-md.md +116 -0
  38. package/bundle/docs/cli/generation-settings.md +210 -0
  39. package/bundle/docs/cli/headless.md +50 -0
  40. package/bundle/docs/cli/model-routing.md +42 -0
  41. package/bundle/docs/cli/model.md +53 -0
  42. package/bundle/docs/cli/plan-mode.md +375 -0
  43. package/bundle/docs/cli/rewind.md +51 -0
  44. package/bundle/docs/cli/sandbox.md +257 -0
  45. package/bundle/docs/cli/session-management.md +184 -0
  46. package/bundle/docs/cli/settings.md +165 -0
  47. package/bundle/docs/cli/skills.md +134 -0
  48. package/bundle/docs/cli/system-prompt.md +125 -0
  49. package/bundle/docs/cli/telemetry.md +922 -0
  50. package/bundle/docs/cli/themes.md +269 -0
  51. package/bundle/docs/cli/token-caching.md +20 -0
  52. package/bundle/docs/cli/trusted-folders.md +126 -0
  53. package/bundle/docs/cli/tutorials/automation.md +283 -0
  54. package/bundle/docs/cli/tutorials/file-management.md +142 -0
  55. package/bundle/docs/cli/tutorials/mcp-setup.md +113 -0
  56. package/bundle/docs/cli/tutorials/memory-management.md +126 -0
  57. package/bundle/docs/cli/tutorials/session-management.md +105 -0
  58. package/bundle/docs/cli/tutorials/shell-commands.md +107 -0
  59. package/bundle/docs/cli/tutorials/skills-getting-started.md +110 -0
  60. package/bundle/docs/cli/tutorials/task-planning.md +93 -0
  61. package/bundle/docs/cli/tutorials/web-tools.md +78 -0
  62. package/bundle/docs/core/index.md +107 -0
  63. package/bundle/docs/core/remote-agents.md +84 -0
  64. package/bundle/docs/core/subagents.md +307 -0
  65. package/bundle/docs/examples/proxy-script.md +83 -0
  66. package/bundle/docs/extensions/best-practices.md +188 -0
  67. package/bundle/docs/extensions/index.md +61 -0
  68. package/bundle/docs/extensions/reference.md +333 -0
  69. package/bundle/docs/extensions/releasing.md +154 -0
  70. package/bundle/docs/extensions/writing-extensions.md +308 -0
  71. package/bundle/docs/get-started/authentication.md +402 -0
  72. package/bundle/docs/get-started/examples.md +139 -0
  73. package/bundle/docs/get-started/gemini-3.md +115 -0
  74. package/bundle/docs/get-started/index.md +82 -0
  75. package/bundle/docs/get-started/installation.md +174 -0
  76. package/bundle/docs/hooks/best-practices.md +709 -0
  77. package/bundle/docs/hooks/index.md +164 -0
  78. package/bundle/docs/hooks/reference.md +330 -0
  79. package/bundle/docs/hooks/writing-hooks.md +474 -0
  80. package/bundle/docs/ide-integration/ide-companion-spec.md +267 -0
  81. package/bundle/docs/ide-integration/index.md +224 -0
  82. package/bundle/docs/index.md +141 -0
  83. package/bundle/docs/integration-tests.md +211 -0
  84. package/bundle/docs/issue-and-pr-automation.md +172 -0
  85. package/bundle/docs/local-development.md +134 -0
  86. package/bundle/docs/mermaid/context.mmd +103 -0
  87. package/bundle/docs/mermaid/render-path.mmd +64 -0
  88. package/bundle/docs/npm.md +62 -0
  89. package/bundle/docs/redirects.json +20 -0
  90. package/bundle/docs/reference/commands.md +526 -0
  91. package/bundle/docs/reference/configuration.md +1786 -0
  92. package/bundle/docs/reference/keyboard-shortcuts.md +164 -0
  93. package/bundle/docs/reference/memport.md +246 -0
  94. package/bundle/docs/reference/policy-engine.md +364 -0
  95. package/bundle/docs/reference/tools.md +106 -0
  96. package/bundle/docs/release-confidence.md +164 -0
  97. package/bundle/docs/releases.md +540 -0
  98. package/bundle/docs/resources/faq.md +175 -0
  99. package/bundle/docs/resources/quota-and-pricing.md +165 -0
  100. package/bundle/docs/resources/tos-privacy.md +102 -0
  101. package/bundle/docs/resources/troubleshooting.md +176 -0
  102. package/bundle/docs/resources/uninstall.md +56 -0
  103. package/bundle/docs/sidebar.json +233 -0
  104. package/bundle/docs/tools/activate-skill.md +43 -0
  105. package/bundle/docs/tools/ask-user.md +95 -0
  106. package/bundle/docs/tools/file-system.md +129 -0
  107. package/bundle/docs/tools/internal-docs.md +46 -0
  108. package/bundle/docs/tools/mcp-server.md +1150 -0
  109. package/bundle/docs/tools/memory.md +35 -0
  110. package/bundle/docs/tools/planning.md +58 -0
  111. package/bundle/docs/tools/shell.md +216 -0
  112. package/bundle/docs/tools/todos.md +35 -0
  113. package/bundle/docs/tools/web-fetch.md +35 -0
  114. package/bundle/docs/tools/web-search.md +32 -0
  115. package/bundle/docs/update/update-guide.md +111 -0
  116. package/bundle/masha.js +563471 -0
  117. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/client/main.js +89 -0
  118. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/_client-assets.d.ts +7 -0
  119. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/_client-assets.js +9 -0
  120. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/_client-assets.js.map +1 -0
  121. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/index.d.ts +48 -0
  122. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/index.js +299 -0
  123. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/index.js.map +1 -0
  124. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/types.d.ts +36 -0
  125. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/types.js +7 -0
  126. package/bundle/node_modules/@dgxo/mashadevcli-devtools/dist/src/types.js.map +1 -0
  127. package/bundle/node_modules/@dgxo/mashadevcli-devtools/package.json +32 -0
  128. package/bundle/policies/conseca.toml +6 -0
  129. package/bundle/policies/discovered.toml +8 -0
  130. package/bundle/policies/plan.toml +109 -0
  131. package/bundle/policies/read-only.toml +53 -0
  132. package/bundle/policies/write.toml +80 -0
  133. package/bundle/policies/yolo.toml +54 -0
  134. package/bundle/sandbox-macos-permissive-open.sb +27 -0
  135. package/bundle/sandbox-macos-permissive-proxied.sb +37 -0
  136. package/bundle/sandbox-macos-restrictive-open.sb +96 -0
  137. package/bundle/sandbox-macos-restrictive-proxied.sb +98 -0
  138. package/bundle/sandbox-macos-strict-open.sb +131 -0
  139. package/bundle/sandbox-macos-strict-proxied.sb +133 -0
  140. package/package.json +169 -0
@@ -0,0 +1,709 @@
1
+ # Hooks Best Practices
2
+
3
+ This guide covers security considerations, performance optimization, debugging
4
+ techniques, and privacy considerations for developing and deploying hooks in
5
+ Gemini CLI.
6
+
7
+ ## Performance
8
+
9
+ ### Keep hooks fast
10
+
11
+ Hooks run synchronously—slow hooks delay the agent loop. Optimize for speed by
12
+ using parallel operations:
13
+
14
+ ```javascript
15
+ // Sequential operations are slower
16
+ const data1 = await fetch(url1).then((r) => r.json());
17
+ const data2 = await fetch(url2).then((r) => r.json());
18
+
19
+ // Prefer parallel operations for better performance
20
+ // Start requests concurrently
21
+ const p1 = fetch(url1).then((r) => r.json());
22
+ const p2 = fetch(url2).then((r) => r.json());
23
+
24
+ // Wait for all results
25
+ const [data1, data2] = await Promise.all([p1, p2]);
26
+ ```
27
+
28
+ ### Cache expensive operations
29
+
30
+ Store results between invocations to avoid repeated computation, especially for
31
+ hooks that run frequently (like `BeforeTool` or `AfterModel`).
32
+
33
+ ```javascript
34
+ const fs = require('fs');
35
+ const path = require('path');
36
+
37
+ const CACHE_FILE = '.gemini/hook-cache.json';
38
+
39
+ function readCache() {
40
+ try {
41
+ return JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
42
+ } catch {
43
+ return {};
44
+ }
45
+ }
46
+
47
+ function writeCache(data) {
48
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2));
49
+ }
50
+
51
+ async function main() {
52
+ const cache = readCache();
53
+ const cacheKey = `tool-list-${(Date.now() / 3600000) | 0}`; // Hourly cache
54
+
55
+ if (cache[cacheKey]) {
56
+ // Write JSON to stdout
57
+ console.log(JSON.stringify(cache[cacheKey]));
58
+ return;
59
+ }
60
+
61
+ // Expensive operation
62
+ const result = await computeExpensiveResult();
63
+ cache[cacheKey] = result;
64
+ writeCache(cache);
65
+
66
+ console.log(JSON.stringify(result));
67
+ }
68
+ ```
69
+
70
+ ### Use appropriate events
71
+
72
+ Choose hook events that match your use case to avoid unnecessary execution.
73
+
74
+ - **`AfterAgent`**: Fires **once** per turn after the model finishes its final
75
+ response. Use this for quality validation (Retries) or final logging.
76
+ - **`AfterModel`**: Fires after **every chunk** of LLM output. Use this for
77
+ real-time redaction, PII filtering, or monitoring output as it streams.
78
+
79
+ If you only need to check the final completion, use `AfterAgent` to save
80
+ performance.
81
+
82
+ ### Filter with matchers
83
+
84
+ Use specific matchers to avoid unnecessary hook execution. Instead of matching
85
+ all tools with `*`, specify only the tools you need. This saves the overhead of
86
+ spawning a process for irrelevant events.
87
+
88
+ ```json
89
+ {
90
+ "matcher": "write_file|replace",
91
+ "hooks": [
92
+ {
93
+ "name": "validate-writes",
94
+ "type": "command",
95
+ "command": "./validate.sh"
96
+ }
97
+ ]
98
+ }
99
+ ```
100
+
101
+ ### Optimize JSON parsing
102
+
103
+ For large inputs (like `AfterModel` receiving a large context), standard JSON
104
+ parsing can be slow. If you only need one field, consider streaming parsers or
105
+ lightweight extraction logic, though for most shell scripts `jq` is sufficient.
106
+
107
+ ## Debugging
108
+
109
+ ### The "Strict JSON" rule
110
+
111
+ The most common cause of hook failure is "polluting" the standard output.
112
+
113
+ - **stdout** is for **JSON only**.
114
+ - **stderr** is for **logs and text**.
115
+
116
+ **Good:**
117
+
118
+ ```bash
119
+ #!/bin/bash
120
+ echo "Starting check..." >&2 # <--- Redirect to stderr
121
+ echo '{"decision": "allow"}'
122
+
123
+ ```
124
+
125
+ ### Log to files
126
+
127
+ Since hooks run in the background, writing to a dedicated log file is often the
128
+ easiest way to debug complex logic.
129
+
130
+ ```bash
131
+ #!/usr/bin/env bash
132
+ LOG_FILE=".gemini/hooks/debug.log"
133
+
134
+ # Log with timestamp
135
+ log() {
136
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
137
+ }
138
+
139
+ input=$(cat)
140
+ log "Received input: ${input:0:100}..."
141
+
142
+ # Hook logic here
143
+
144
+ log "Hook completed successfully"
145
+ # Always output valid JSON to stdout at the end, even if just empty
146
+ echo "{}"
147
+
148
+ ```
149
+
150
+ ### Use stderr for errors
151
+
152
+ Error messages on stderr are surfaced appropriately based on exit codes:
153
+
154
+ ```javascript
155
+ try {
156
+ const result = dangerousOperation();
157
+ console.log(JSON.stringify({ result }));
158
+ } catch (error) {
159
+ // Write the error description to stderr so the user/agent sees it
160
+ console.error(`Hook error: ${error.message}`);
161
+ process.exit(2); // Blocking error
162
+ }
163
+ ```
164
+
165
+ ### Test hooks independently
166
+
167
+ Run hook scripts manually with sample JSON input to verify they behave as
168
+ expected before hooking them up to the CLI.
169
+
170
+ **macOS/Linux**
171
+
172
+ ```bash
173
+ # Create test input
174
+ cat > test-input.json << 'EOF'
175
+ {
176
+ "session_id": "test-123",
177
+ "cwd": "/tmp/test",
178
+ "hook_event_name": "BeforeTool",
179
+ "tool_name": "write_file",
180
+ "tool_input": {
181
+ "file_path": "test.txt",
182
+ "content": "Test content"
183
+ }
184
+ }
185
+ EOF
186
+
187
+ # Test the hook
188
+ cat test-input.json | .gemini/hooks/my-hook.sh
189
+
190
+ # Check exit code
191
+ echo "Exit code: $?"
192
+ ```
193
+
194
+ **Windows (PowerShell)**
195
+
196
+ ```powershell
197
+ # Create test input
198
+ @"
199
+ {
200
+ "session_id": "test-123",
201
+ "cwd": "C:\\temp\\test",
202
+ "hook_event_name": "BeforeTool",
203
+ "tool_name": "write_file",
204
+ "tool_input": {
205
+ "file_path": "test.txt",
206
+ "content": "Test content"
207
+ }
208
+ }
209
+ "@ | Out-File -FilePath test-input.json -Encoding utf8
210
+
211
+ # Test the hook
212
+ Get-Content test-input.json | .\.gemini\hooks\my-hook.ps1
213
+
214
+ # Check exit code
215
+ Write-Host "Exit code: $LASTEXITCODE"
216
+ ```
217
+
218
+ ### Check exit codes
219
+
220
+ Gemini CLI uses exit codes for high-level flow control:
221
+
222
+ - **Exit 0 (Success)**: The hook ran successfully. The CLI parses `stdout` for
223
+ JSON decisions.
224
+ - **Exit 2 (System Block)**: A critical block occurred. `stderr` is used as the
225
+ reason.
226
+ - For **Agent/Model** events, this aborts the turn.
227
+ - For **Tool** events, this blocks the tool but allows the agent to continue.
228
+ - For **AfterAgent**, this triggers an automatic retry turn.
229
+
230
+ > **TIP**
231
+ >
232
+ > **Blocking vs. Stopping**: Use `decision: "deny"` (or Exit Code 2) to block a
233
+ > **specific action**. Use `{"continue": false}` in your JSON output to **kill
234
+ > the entire agent loop** immediately.
235
+
236
+ ```bash
237
+ #!/usr/bin/env bash
238
+ set -e
239
+
240
+ # Hook logic
241
+ if process_input; then
242
+ echo '{"decision": "allow"}'
243
+ exit 0
244
+ else
245
+ echo "Critical validation failure" >&2
246
+ exit 2
247
+ fi
248
+
249
+ ```
250
+
251
+ ### Enable telemetry
252
+
253
+ Hook execution is logged when `telemetry.logPrompts` is enabled. You can view
254
+ these logs to debug execution flow.
255
+
256
+ ```json
257
+ {
258
+ "telemetry": {
259
+ "logPrompts": true
260
+ }
261
+ }
262
+ ```
263
+
264
+ ### Use hook panel
265
+
266
+ The `/hooks panel` command inside the CLI shows execution status and recent
267
+ output:
268
+
269
+ ```bash
270
+ /hooks panel
271
+ ```
272
+
273
+ Check for:
274
+
275
+ - Hook execution counts
276
+ - Recent successes/failures
277
+ - Error messages
278
+ - Execution timing
279
+
280
+ ## Development
281
+
282
+ ### Start simple
283
+
284
+ Begin with basic logging hooks before implementing complex logic:
285
+
286
+ ```bash
287
+ #!/usr/bin/env bash
288
+ # Simple logging hook to understand input structure
289
+ input=$(cat)
290
+ echo "$input" >> .gemini/hook-inputs.log
291
+ # Always return valid JSON
292
+ echo "{}"
293
+
294
+ ```
295
+
296
+ ### Documenting your hooks
297
+
298
+ Maintainability is critical for complex hook systems. Use descriptions and
299
+ comments to help yourself and others understand why a hook exists.
300
+
301
+ **Use the `description` field**: This text is displayed in the `/hooks panel` UI
302
+ and helps diagnose issues.
303
+
304
+ ```json
305
+ {
306
+ "hooks": {
307
+ "BeforeTool": [
308
+ {
309
+ "matcher": "write_file|replace",
310
+ "hooks": [
311
+ {
312
+ "name": "secret-scanner",
313
+ "type": "command",
314
+ "command": "$GEMINI_PROJECT_DIR/.gemini/hooks/block-secrets.sh",
315
+ "description": "Scans code changes for API keys and secrets before writing"
316
+ }
317
+ ]
318
+ }
319
+ ]
320
+ }
321
+ }
322
+ ```
323
+
324
+ **Add comments in hook scripts**: Explain performance expectations and
325
+ dependencies.
326
+
327
+ ```javascript
328
+ #!/usr/bin/env node
329
+ /**
330
+ * RAG Tool Filter Hook
331
+ *
332
+ * Reduces the tool space by extracting keywords from the user's request.
333
+ *
334
+ * Performance: ~500ms average
335
+ * Dependencies: @google/generative-ai
336
+ */
337
+ ```
338
+
339
+ ### Use JSON libraries
340
+
341
+ Parse JSON with proper libraries instead of text processing.
342
+
343
+ **Bad:**
344
+
345
+ ```bash
346
+ # Fragile text parsing
347
+ tool_name=$(echo "$input" | grep -oP '"tool_name":\s*"\K[^"]+')
348
+
349
+ ```
350
+
351
+ **Good:**
352
+
353
+ ```bash
354
+ # Robust JSON parsing
355
+ tool_name=$(echo "$input" | jq -r '.tool_name')
356
+
357
+ ```
358
+
359
+ ### Make scripts executable
360
+
361
+ Always make hook scripts executable on macOS/Linux:
362
+
363
+ ```bash
364
+ chmod +x .gemini/hooks/*.sh
365
+ chmod +x .gemini/hooks/*.js
366
+
367
+ ```
368
+
369
+ **Windows Note**: On Windows, PowerShell scripts (`.ps1`) don't use `chmod`, but
370
+ you may need to ensure your execution policy allows them to run (e.g.,
371
+ `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser`).
372
+
373
+ ### Version control
374
+
375
+ Commit hooks to share with your team:
376
+
377
+ ```bash
378
+ git add .gemini/hooks/
379
+ git add .gemini/settings.json
380
+
381
+ ```
382
+
383
+ **`.gitignore` considerations:**
384
+
385
+ ```gitignore
386
+ # Ignore hook cache and logs
387
+ .gemini/hook-cache.json
388
+ .gemini/hook-debug.log
389
+ .gemini/memory/session-*.jsonl
390
+
391
+ # Keep hook scripts
392
+ !.gemini/hooks/*.sh
393
+ !.gemini/hooks/*.js
394
+
395
+ ```
396
+
397
+ ## Hook security
398
+
399
+ ### Threat Model
400
+
401
+ Understanding where hooks come from and what they can do is critical for secure
402
+ usage.
403
+
404
+ | Hook Source | Description |
405
+ | :---------------------------- | :------------------------------------------------------------------------------------------------------------------------- |
406
+ | **System** | Configured by system administrators (e.g., `/etc/gemini-cli/settings.json`, `/Library/...`). Assumed to be the **safest**. |
407
+ | **User** (`~/.gemini/...`) | Configured by you. You are responsible for ensuring they are safe. |
408
+ | **Extensions** | You explicitly approve and install these. Security depends on the extension source (integrity). |
409
+ | **Project** (`./.gemini/...`) | **Untrusted by default.** Safest in trusted internal repos; higher risk in third-party/public repos. |
410
+
411
+ #### Project Hook Security
412
+
413
+ When you open a project with hooks defined in `.gemini/settings.json`:
414
+
415
+ 1. **Detection**: Gemini CLI detects the hooks.
416
+ 2. **Identification**: A unique identity is generated for each hook based on its
417
+ `name` and `command`.
418
+ 3. **Warning**: If this specific hook identity has not been seen before, a
419
+ **warning** is displayed.
420
+ 4. **Execution**: The hook is executed (unless specific security settings block
421
+ it).
422
+ 5. **Trust**: The hook is marked as "trusted" for this project.
423
+
424
+ > **Modification detection**: If the `command` string of a project hook is
425
+ > changed (e.g., by a `git pull`), its identity changes. Gemini CLI will treat
426
+ > it as a **new, untrusted hook** and warn you again. This prevents malicious
427
+ > actors from silently swapping a verified command for a malicious one.
428
+
429
+ ### Risks
430
+
431
+ | Risk | Description |
432
+ | :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- |
433
+ | **Arbitrary Code Execution** | Hooks run as your user. They can do anything you can do (delete files, install software). |
434
+ | **Data Exfiltration** | A hook could read your input (prompts), output (code), or environment variables (`GEMINI_API_KEY`) and send them to a remote server. |
435
+ | **Prompt Injection** | Malicious content in a file or web page could trick an LLM into running a tool that triggers a hook in an unexpected way. |
436
+
437
+ ### Mitigation Strategies
438
+
439
+ #### Verify the source
440
+
441
+ **Verify the source** of any project hooks or extensions before enabling them.
442
+
443
+ - For open-source projects, a quick review of the hook scripts is recommended.
444
+ - For extensions, ensure you trust the author or publisher (e.g., verified
445
+ publishers, well-known community members).
446
+ - Be cautious with obfuscated scripts or compiled binaries from unknown sources.
447
+
448
+ #### Sanitize environment
449
+
450
+ Hooks inherit the environment of the Gemini CLI process, which may include
451
+ sensitive API keys. Gemini CLI provides a
452
+ [redaction system](/docs/reference/configuration.md#environment-variable-redaction)
453
+ that automatically filters variables matching sensitive patterns (e.g., `KEY`,
454
+ `TOKEN`).
455
+
456
+ > **Disabled by Default**: Environment redaction is currently **OFF by
457
+ > default**. We strongly recommend enabling it if you are running third-party
458
+ > hooks or working in sensitive environments.
459
+
460
+ **Impact on hooks:**
461
+
462
+ - **Security**: Prevents your hook scripts from accidentally leaking secrets.
463
+ - **Troubleshooting**: If your hook depends on a specific environment variable
464
+ that is being blocked, you must explicitly allow it in `settings.json`.
465
+
466
+ ```json
467
+ {
468
+ "security": {
469
+ "environmentVariableRedaction": {
470
+ "enabled": true,
471
+ "allowed": ["MY_REQUIRED_TOOL_KEY"]
472
+ }
473
+ }
474
+ }
475
+ ```
476
+
477
+ **System administrators:** You can enforce redaction for all users in the system
478
+ configuration.
479
+
480
+ ## Troubleshooting
481
+
482
+ ### Hook not executing
483
+
484
+ **Check hook name in `/hooks panel`:** Verify the hook appears in the list and
485
+ is enabled.
486
+
487
+ **Verify matcher pattern:**
488
+
489
+ ```bash
490
+ # Test regex pattern
491
+ echo "write_file|replace" | grep -E "write_.*|replace"
492
+
493
+ ```
494
+
495
+ **Check disabled list:** Verify the hook is not listed in your `settings.json`:
496
+
497
+ ```json
498
+ {
499
+ "hooks": {
500
+ "disabled": ["my-hook-name"]
501
+ }
502
+ }
503
+ ```
504
+
505
+ **Ensure script is executable**: For macOS and Linux users, verify the script
506
+ has execution permissions:
507
+
508
+ ```bash
509
+ ls -la .gemini/hooks/my-hook.sh
510
+ chmod +x .gemini/hooks/my-hook.sh
511
+ ```
512
+
513
+ **Windows Note**: On Windows, ensure your execution policy allows running
514
+ scripts (e.g., `Get-ExecutionPolicy`).
515
+
516
+ **Verify script path:** Ensure the path in `settings.json` resolves correctly.
517
+
518
+ ```bash
519
+ # Check path expansion
520
+ echo "$GEMINI_PROJECT_DIR/.gemini/hooks/my-hook.sh"
521
+
522
+ # Verify file exists
523
+ test -f "$GEMINI_PROJECT_DIR/.gemini/hooks/my-hook.sh" && echo "File exists"
524
+ ```
525
+
526
+ ### Hook timing out
527
+
528
+ **Check configured timeout:** The default is 60000ms (1 minute). You can
529
+ increase this in `settings.json`:
530
+
531
+ ```json
532
+ {
533
+ "name": "slow-hook",
534
+ "timeout": 120000
535
+ }
536
+ ```
537
+
538
+ **Optimize slow operations:** Move heavy processing to background tasks or use
539
+ caching.
540
+
541
+ ### Invalid JSON output
542
+
543
+ **Validate JSON before outputting:**
544
+
545
+ ```bash
546
+ #!/usr/bin/env bash
547
+ output='{"decision": "allow"}'
548
+
549
+ # Validate JSON
550
+ if echo "$output" | jq empty 2>/dev/null; then
551
+ echo "$output"
552
+ else
553
+ echo "Invalid JSON generated" >&2
554
+ exit 1
555
+ fi
556
+
557
+ ```
558
+
559
+ ### Environment variables not available
560
+
561
+ **Check if variable is set:**
562
+
563
+ ```bash
564
+ #!/usr/bin/env bash
565
+ if [ -z "$GEMINI_PROJECT_DIR" ]; then
566
+ echo "GEMINI_PROJECT_DIR not set" >&2
567
+ exit 1
568
+ fi
569
+
570
+ ```
571
+
572
+ **Debug available variables:**
573
+
574
+ ```bash
575
+ env > .gemini/hook-env.log
576
+ ```
577
+
578
+ ## Authoring secure hooks
579
+
580
+ When writing your own hooks, follow these practices to ensure they are robust
581
+ and secure.
582
+
583
+ ### Validate all inputs
584
+
585
+ Never trust data from hooks without validation. Hook inputs often come from the
586
+ LLM or user prompts, which can be manipulated.
587
+
588
+ ```bash
589
+ #!/usr/bin/env bash
590
+ input=$(cat)
591
+
592
+ # Validate JSON structure
593
+ if ! echo "$input" | jq empty 2>/dev/null; then
594
+ echo "Invalid JSON input" >&2
595
+ exit 1
596
+ fi
597
+
598
+ # Validate tool_name explicitly
599
+ tool_name=$(echo "$input" | jq -r '.tool_name // empty')
600
+ if [[ "$tool_name" != "write_file" && "$tool_name" != "read_file" ]]; then
601
+ echo "Unexpected tool: $tool_name" >&2
602
+ exit 1
603
+ fi
604
+ ```
605
+
606
+ ### Use timeouts
607
+
608
+ Prevent denial-of-service (hanging agents) by enforcing timeouts. Gemini CLI
609
+ defaults to 60 seconds, but you should set stricter limits for fast hooks.
610
+
611
+ ```json
612
+ {
613
+ "hooks": {
614
+ "BeforeTool": [
615
+ {
616
+ "matcher": "*",
617
+ "hooks": [
618
+ {
619
+ "name": "fast-validator",
620
+ "type": "command",
621
+ "command": "./hooks/validate.sh",
622
+ "timeout": 5000 // 5 seconds
623
+ }
624
+ ]
625
+ }
626
+ ]
627
+ }
628
+ }
629
+ ```
630
+
631
+ ### Limit permissions
632
+
633
+ Run hooks with minimal required permissions:
634
+
635
+ ```bash
636
+ #!/usr/bin/env bash
637
+ # Don't run as root
638
+ if [ "$EUID" -eq 0 ]; then
639
+ echo "Hook should not run as root" >&2
640
+ exit 1
641
+ fi
642
+
643
+ # Check file permissions before writing
644
+ if [ -w "$file_path" ]; then
645
+ # Safe to write
646
+ else
647
+ echo "Insufficient permissions" >&2
648
+ exit 1
649
+ fi
650
+ ```
651
+
652
+ ### Example: Secret Scanner
653
+
654
+ Use `BeforeTool` hooks to prevent committing sensitive data. This is a powerful
655
+ pattern for enhancing security in your workflow.
656
+
657
+ ```javascript
658
+ const SECRET_PATTERNS = [
659
+ /api[_-]?key\s*[:=]\s*['"]?[a-zA-Z0-9_-]{20,}['"]?/i,
660
+ /password\s*[:=]\s*['"]?[^\s'"]{8,}['"]?/i,
661
+ /secret\s*[:=]\s*['"]?[a-zA-Z0-9_-]{20,}['"]?/i,
662
+ /AKIA[0-9A-Z]{16}/, // AWS access key
663
+ /ghp_[a-zA-Z0-9]{36}/, // GitHub personal access token
664
+ /sk-[a-zA-Z0-9]{48}/, // OpenAI API key
665
+ ];
666
+
667
+ function containsSecret(content) {
668
+ return SECRET_PATTERNS.some((pattern) => pattern.test(content));
669
+ }
670
+ ```
671
+
672
+ ## Privacy considerations
673
+
674
+ Hook inputs and outputs may contain sensitive information.
675
+
676
+ ### What data is collected
677
+
678
+ Hook telemetry may include inputs (prompts, code) and outputs (decisions,
679
+ reasons) unless disabled.
680
+
681
+ ### Privacy settings
682
+
683
+ **Disable PII logging:** If you are working with sensitive data, disable prompt
684
+ logging in your settings:
685
+
686
+ ```json
687
+ {
688
+ "telemetry": {
689
+ "logPrompts": false
690
+ }
691
+ }
692
+ ```
693
+
694
+ **Suppress Output:** Individual hooks can request their metadata be hidden from
695
+ logs and telemetry by returning `"suppressOutput": true` in their JSON response.
696
+
697
+ > **Note**
698
+
699
+ > `suppressOutput` only affects background logging. Any `systemMessage` or
700
+ > `reason` included in the JSON will still be displayed to the user in the
701
+ > terminal.
702
+
703
+ ### Sensitive data in hooks
704
+
705
+ If your hooks process sensitive data:
706
+
707
+ 1. **Minimize logging:** Don't write sensitive data to log files.
708
+ 2. **Sanitize outputs:** Remove sensitive data before outputting JSON or writing
709
+ to stderr.