hail-hydra-cc 2.0.3 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,18 +56,21 @@ npx hail-hydra-cc --help # Show help
56
56
  │ ├── hydra-coder.md
57
57
  │ ├── hydra-analyst.md
58
58
  │ └── hydra-sentinel.md
59
- ├── commands/hydra/ # 7 slash commands
59
+ ├── commands/hydra/ # 8 slash commands
60
60
  │ ├── help.md # /hydra:help
61
61
  │ ├── status.md # /hydra:status
62
62
  │ ├── update.md # /hydra:update
63
63
  │ ├── config.md # /hydra:config
64
64
  │ ├── guard.md # /hydra:guard
65
65
  │ ├── quiet.md # /hydra:quiet
66
- └── verbose.md # /hydra:verbose
67
- ├── hooks/ # 3 lifecycle hooks
66
+ ├── verbose.md # /hydra:verbose
67
+ │ └── report.md # /hydra:report
68
+ ├── hooks/ # 4 lifecycle hooks
68
69
  │ ├── hydra-check-update.js # SessionStart — version check
69
70
  │ ├── hydra-statusline.js # StatusLine — status bar
70
- └── hydra-auto-guard.js # PostToolUse — file tracker
71
+ ├── hydra-auto-guard.js # PostToolUse — file tracker
72
+ │ ├── hydra-notify.js # Notification — task completion sound
73
+ │ └── hydra-task-complete.wav # Notification sound file
71
74
  └── skills/hydra/ # Skill (Claude Code discoverable via /skills)
72
75
  ├── SKILL.md # Orchestrator instructions
73
76
  ├── VERSION # Installed version
package/files/SKILL.md CHANGED
@@ -14,6 +14,49 @@ description: >
14
14
  > *"Cut off one head, two more shall take its place."*
15
15
  > Except here — every head is doing your work faster and cheaper.
16
16
 
17
+ ## ⛔ MANDATORY PROTOCOLS — NEVER SKIP
18
+
19
+ These protocols are NON-NEGOTIABLE. Skipping them is a framework violation.
20
+
21
+ ### Protocol 1: Sentinel Scan After Code Changes
22
+
23
+ When ANY agent returns output containing `⚠️ HYDRA_SENTINEL_REQUIRED`, you
24
+ MUST — before doing ANYTHING else, before presenting results to the user,
25
+ before running any other agents — dispatch hydra-sentinel-scan with the
26
+ files and changes listed in the trigger block.
27
+
28
+ **This is blocking.** The user does NOT see the code changes until sentinel
29
+ completes. If you present code changes to the user without running sentinel
30
+ first, you have violated the framework's core safety guarantee.
31
+
32
+ Sequence:
33
+ 1. Receive agent output containing ⚠️ HYDRA_SENTINEL_REQUIRED
34
+ 2. IMMEDIATELY dispatch hydra-sentinel-scan AND hydra-guard in parallel
35
+ 3. WAIT for both to complete
36
+ 4. If sentinel-scan finds issues → dispatch hydra-sentinel (deep analysis)
37
+ 5. WAIT for deep analysis
38
+ 6. THEN — and ONLY then — present results to the user
39
+
40
+ If the agent output contains `✅ HYDRA_NO_CODE_CHANGES`, skip sentinel. Present
41
+ results immediately.
42
+
43
+ ### Protocol 2: Sentinel Fix Decision Tree
44
+
45
+ When hydra-sentinel confirms real issues:
46
+
47
+ **TRIVIAL** (auto-fix without asking):
48
+ Import renames, file path updates, barrel file re-exports.
49
+ → Dispatch hydra-coder to fix. Re-run sentinel-scan to verify.
50
+ → Tell user: "Sentinel caught [issue]. Auto-fixed."
51
+
52
+ **MEDIUM** (present to user, offer to fix):
53
+ API contract mismatches, missing env vars, signature mismatches.
54
+ → Show the sentinel report. Ask: "Want me to fix these?"
55
+
56
+ **COMPLEX** (report only):
57
+ Architectural changes, migration needed, business logic decisions.
58
+ → Show the report. Let user decide.
59
+
17
60
  ## Why Hydra Exists
18
61
 
19
62
  Autoregressive LLM inference is memory-bandwidth bound — the time per token scales with model
@@ -505,6 +548,10 @@ When manual verification is required, match depth to risk:
505
548
 
506
549
  ## Sentinel Protocol — Integration Integrity
507
550
 
551
+ > **REMINDER:** If you see `⚠️ HYDRA_SENTINEL_REQUIRED` in any agent's output
552
+ > and you skip sentinel, you are violating the framework's core protocol.
553
+ > See "⛔ MANDATORY PROTOCOLS" at the top of this document.
554
+
508
555
  After EVERY code change made by hydra-coder or hydra-analyst (or yourself),
509
556
  you MUST run the sentinel pipeline BEFORE presenting results to the user.
510
557
 
@@ -703,6 +750,19 @@ Note: Savings calculated against Opus 4.6 pricing ($5/$25 per MTok) as of Februa
703
750
  "Re-executing [task] directly — [agent]'s output was insufficient because [reason]"
704
751
  - **If accepted as-is**, no inline comment needed — the dispatch log covers it
705
752
 
753
+ ### Sentinel Status in Dispatch Log
754
+
755
+ The dispatch log MUST show sentinel status for every task involving code changes:
756
+
757
+ | Step | Agent | Task | Verdict |
758
+ |------|-------|------|---------|
759
+ | 1 | hydra-coder (Sonnet 4.6) | Fixed auth bug | ✅ Accepted |
760
+ | 2 | hydra-sentinel-scan (Haiku) | Integration sweep | ✅ Clean |
761
+ | 3 | hydra-guard (Haiku 4.5) | Security scan | ✅ Clean |
762
+
763
+ If sentinel-scan is missing from the dispatch log after a code change,
764
+ something went wrong. This is your self-check.
765
+
706
766
  ### Controlling the Dispatch Log
707
767
 
708
768
  - **Default**: ON — always shown when 2+ agents were used
@@ -887,6 +947,21 @@ Track these mentally to calibrate:
887
947
  If rejection rate > 20%, you're too aggressive — shift borderline tasks up one tier.
888
948
  If rejection rate < 5%, you're too conservative — delegate more.
889
949
 
950
+ ## Task Completion Notification
951
+
952
+ After completing a user's task (the final response you present to the user),
953
+ run this command as the LAST action:
954
+ ```bash
955
+ node ~/.claude/hooks/hydra-notify.js < /dev/null
956
+ ```
957
+
958
+ This plays a short notification sound so the user knows you're done —
959
+ especially useful when they've tabbed away while waiting.
960
+
961
+ Do this for SUBSTANTIAL tasks only (tasks that took more than ~10 seconds).
962
+ Do NOT play it for quick conversational responses, acknowledgments, or
963
+ follow-up questions.
964
+
890
965
  ## Reference Material
891
966
 
892
967
  - `references/routing-guide.md` — Mandatory delegation examples, decision flowchart
@@ -17,6 +17,7 @@ COMMANDS
17
17
  /hydra:guard Run security scan on files (usage: /hydra:guard src/auth.py)
18
18
  /hydra:quiet Suppress dispatch logs for this session
19
19
  /hydra:verbose Enable verbose dispatch logs with timing
20
+ /hydra:report Report a bug, request a feature, or share feedback
20
21
 
21
22
  AGENTS
22
23
  🟢 hydra-scout (Haiku 4.5) — Explore codebase, find files, map structure
@@ -12,3 +12,5 @@ Respond with:
12
12
  "🐉 Quiet mode enabled. Dispatch logs suppressed for this session. Use /hydra:verbose to re-enable."
13
13
 
14
14
  Continue operating Hydra normally (delegation, verification, auto-guard) — just don't show the dispatch log table.
15
+
16
+ Also suppress the task completion notification sound for this session.
@@ -0,0 +1,112 @@
1
+ ---
2
+ description: Report a bug, request a feature, or share feedback about Hydra
3
+ allowed-tools: Bash
4
+ ---
5
+
6
+ # Hydra Report
7
+
8
+ Walk the user through submitting a bug report, feature request, or general feedback for the Hydra framework. Follow these steps interactively:
9
+
10
+ ## Step 1 — Ask report type
11
+
12
+ Ask the user:
13
+
14
+ ```
15
+ 🐉 What would you like to report?
16
+
17
+ 1. 🐛 Bug Report — something is broken or not working as expected
18
+ 2. ✨ Feature Request — an idea for a new feature or improvement
19
+ 3. 💬 General Feedback — anything else you'd like to share
20
+
21
+ Enter 1, 2, or 3:
22
+ ```
23
+
24
+ Wait for their response. Map:
25
+ - 1 → label: `bug`, template: Bug Report
26
+ - 2 → label: `enhancement`, template: Feature Request
27
+ - 3 → label: `feedback`, template: General Feedback
28
+
29
+ ## Step 2 — Collect description
30
+
31
+ Ask the user to describe the issue or idea:
32
+
33
+ ```
34
+ Describe the [bug/feature/feedback] in a few sentences:
35
+ ```
36
+
37
+ For bugs, also ask:
38
+ ```
39
+ Steps to reproduce (if applicable):
40
+ ```
41
+
42
+ ## Step 3 — Collect system info (optional)
43
+
44
+ Ask: "Include system info in the report? (recommended for bugs) [Y/n]"
45
+
46
+ If yes, gather:
47
+ ```bash
48
+ # Hydra version
49
+ cat ~/.claude/skills/hydra/VERSION 2>/dev/null || echo "not found"
50
+ ```
51
+ ```bash
52
+ # OS info
53
+ node -e "console.log(process.platform + ' ' + process.arch + ' ' + require('os').release())"
54
+ ```
55
+ ```bash
56
+ # Agent count
57
+ ls ~/.claude/agents/hydra-*.md 2>/dev/null | wc -l
58
+ ```
59
+
60
+ Format as a "System Info" section in the report.
61
+
62
+ ## Step 4 — Submit via GitHub CLI or fallback
63
+
64
+ Check if `gh` CLI is available:
65
+ ```bash
66
+ gh --version 2>/dev/null
67
+ ```
68
+
69
+ ### If `gh` is installed, check auth:
70
+ ```bash
71
+ gh auth status 2>/dev/null
72
+ ```
73
+
74
+ ### If authenticated → create issue directly:
75
+ ```bash
76
+ gh issue create \
77
+ --repo AR6420/Hail_Hydra \
78
+ --title "<concise title based on description>" \
79
+ --label "<bug|enhancement|feedback>" \
80
+ --body "<formatted report body>"
81
+ ```
82
+
83
+ Show the resulting issue URL to the user.
84
+
85
+ ### If `gh` is installed but NOT authenticated:
86
+
87
+ Tell the user:
88
+ ```
89
+ GitHub CLI is installed but not authenticated.
90
+ Run this in your terminal to authenticate:
91
+
92
+ gh auth login
93
+
94
+ Then try /hydra:report again.
95
+ ```
96
+
97
+ ### If `gh` is NOT installed → browser fallback:
98
+
99
+ Construct a pre-filled GitHub issue URL and show it to the user:
100
+
101
+ ```
102
+ GitHub CLI not found. You can submit your report via browser:
103
+
104
+ https://github.com/AR6420/Hail_Hydra/issues/new?template=<template>&title=<encoded-title>&labels=<label>&body=<encoded-body>
105
+
106
+ Or install GitHub CLI: https://cli.github.com
107
+ ```
108
+
109
+ Map template filenames:
110
+ - bug → `bug_report.md`
111
+ - enhancement → `feature_request.md`
112
+ - feedback → `feedback.md`
@@ -1,35 +1,78 @@
1
- ---
2
- description: Update the Hydra framework to the latest version from npm
3
- allowed-tools: Bash
4
- ---
5
-
6
- # Hydra Update
7
-
8
- Run the following steps to update Hydra to the latest version:
9
-
10
- 1. First, check the current installed version:
11
- ```bash
12
- cat ~/.claude/skills/hydra/VERSION 2>/dev/null || echo "VERSION file not found"
13
- ```
14
-
15
- 2. Check the latest available version on npm:
16
- ```bash
17
- npm view hail-hydra-cc version 2>/dev/null || echo "Package not found on npm"
18
- ```
19
-
20
- 3. If an update is available (versions differ), run the installer:
21
- ```bash
22
- npx hail-hydra-cc@latest --global
23
- ```
24
-
25
- 4. After installation completes, verify the new version:
26
- ```bash
27
- cat ~/.claude/skills/hydra/VERSION
28
- ```
29
-
30
- 5. Report to the user:
31
- - If updated: "🐉 Hydra updated from [old] → [new]. All heads refreshed."
32
- - If already current: "🐉 Hydra is already at the latest version ([version])."
33
- - If error: Show the error and suggest running `npx hail-hydra-cc@latest --global` manually in their terminal.
34
-
35
- **Important**: After updating, the user should restart Claude Code to reload the updated agent files, commands, and hooks.
1
+ ---
2
+ description: Update the Hydra framework to the latest version from npm
3
+ allowed-tools: Bash, Read
4
+ ---
5
+
6
+ # Hydra Update
7
+
8
+ Run the following steps to update Hydra to the latest version:
9
+
10
+ ## Step 1 Check versions
11
+
12
+ ```bash
13
+ cat ~/.claude/skills/hydra/VERSION 2>/dev/null || echo "VERSION file not found"
14
+ ```
15
+ ```bash
16
+ npm view hail-hydra-cc version 2>/dev/null || echo "Package not found on npm"
17
+ ```
18
+
19
+ If the installed version matches the latest npm version, tell the user:
20
+ "🐉 Hydra is already at the latest version ([version])."
21
+ and stop here.
22
+
23
+ ## Step 2 — Show changelog preview
24
+
25
+ Fetch the CHANGELOG from GitHub:
26
+ ```bash
27
+ curl -sL "https://raw.githubusercontent.com/AR6420/Hail_Hydra/main/CHANGELOG.md"
28
+ ```
29
+
30
+ Parse the changelog to extract entries between the installed version and the latest version. Display a formatted "What's New" section:
31
+
32
+ ```
33
+ 🐉 Hydra Update Available: [installed] [latest]
34
+ ═══════════════════════════════════════════════════
35
+
36
+ 📋 What's New:
37
+ [changelog entries for versions between installed and latest]
38
+ ```
39
+
40
+ If the changelog fetch fails, skip the preview and continue with the update.
41
+
42
+ ## Step 3 — Show safety note
43
+
44
+ Display:
45
+ ```
46
+ ⚠️ What gets replaced:
47
+ • Agent definitions (agents/*.md)
48
+ • SKILL.md, references, commands, hooks
49
+ • VERSION file
50
+
51
+ ✅ What's preserved:
52
+ • Your hydra.config.md settings
53
+ • Agent memory directories (memory/)
54
+ • CLAUDE.md orchestrator notes
55
+ • settings.json hook registrations (re-registered automatically)
56
+ ```
57
+
58
+ ## Step 4 — Ask for confirmation
59
+
60
+ Ask the user: "Proceed with update? [Y/n]"
61
+
62
+ If they decline, respond: "🐉 Update cancelled." and stop.
63
+
64
+ ## Step 5 — Run the update
65
+
66
+ ```bash
67
+ npx hail-hydra-cc@latest --global
68
+ ```
69
+
70
+ ## Step 6 — Verify
71
+
72
+ ```bash
73
+ cat ~/.claude/skills/hydra/VERSION
74
+ ```
75
+
76
+ Report to the user:
77
+ - If updated: "🐉 Hydra updated from [old] → [new]. All heads refreshed. Restart Claude Code to load the new files."
78
+ - If error: Show the error and suggest running `npx hail-hydra-cc@latest --global` manually in their terminal.
@@ -25,3 +25,5 @@ Total delegation time: 17.4s | Waves: 2
25
25
 
26
26
  Respond with:
27
27
  "🐉 Verbose mode enabled. Dispatch logs will include timing details. Use /hydra:quiet to suppress."
28
+
29
+ Re-enable the task completion notification sound.
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Hydra Task Completion Notification
6
+ *
7
+ * Plays a short notification sound when Claude Code finishes a task.
8
+ * Cross-platform: macOS (afplay), Windows (PowerShell), Linux (paplay/aplay).
9
+ *
10
+ * Called by Claude Code's Notification hook — stdin receives JSON from
11
+ * the hook system, which we drain and discard to prevent EPIPE errors.
12
+ */
13
+
14
+ const { spawn } = require('child_process');
15
+ const path = require('path');
16
+ const fs = require('fs');
17
+ const os = require('os');
18
+
19
+ // Drain stdin to prevent EPIPE when Claude Code pipes hook data
20
+ process.stdin.resume();
21
+ process.stdin.on('data', () => {});
22
+ process.stdin.on('end', () => {});
23
+
24
+ const wavFile = path.join(os.homedir(), '.claude', 'hooks', 'hydra-task-complete.wav');
25
+
26
+ // Bail silently if the sound file is missing
27
+ if (!fs.existsSync(wavFile)) {
28
+ process.exit(0);
29
+ }
30
+
31
+ const platform = process.platform;
32
+
33
+ try {
34
+ let child;
35
+
36
+ if (platform === 'darwin') {
37
+ // macOS
38
+ child = spawn('afplay', [wavFile], {
39
+ detached: true,
40
+ stdio: 'ignore',
41
+ });
42
+ } else if (platform === 'win32') {
43
+ // Windows — use PowerShell to play the .wav
44
+ child = spawn('powershell', [
45
+ '-NoProfile', '-NonInteractive', '-Command',
46
+ `(New-Object Media.SoundPlayer '${wavFile.replace(/'/g, "''")}').PlaySync()`,
47
+ ], {
48
+ detached: true,
49
+ stdio: 'ignore',
50
+ windowsHide: true,
51
+ });
52
+ } else {
53
+ // Linux — try paplay (PulseAudio) first, fall back to aplay (ALSA)
54
+ const paplay = spawn('paplay', [wavFile], {
55
+ detached: true,
56
+ stdio: 'ignore',
57
+ });
58
+
59
+ paplay.on('error', () => {
60
+ // paplay not available, try aplay
61
+ const aplay = spawn('aplay', [wavFile], {
62
+ detached: true,
63
+ stdio: 'ignore',
64
+ });
65
+ aplay.unref();
66
+ aplay.on('error', () => {}); // silently ignore if neither works
67
+ });
68
+
69
+ paplay.unref();
70
+ process.exit(0);
71
+ }
72
+
73
+ if (child) {
74
+ child.unref();
75
+ }
76
+ } catch {
77
+ // Silently ignore errors — notification sound is non-critical
78
+ }
79
+
80
+ process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hail-hydra-cc",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "Multi-headed speculative execution framework for Claude Code",
5
5
  "bin": {
6
6
  "hail-hydra-cc": "bin/cli.js"
package/src/display.js CHANGED
@@ -42,8 +42,8 @@ function showInstallComplete(statusLineConfigured = true) {
42
42
  console.log(chalk.cyan.bold(' \uD83D\uDC09 Hail Hydra! Framework deployed and ready.'));
43
43
  console.log(chalk.gray(' ' + '\u2500'.repeat(45)));
44
44
  console.log(chalk.green(` \u2714 9 agents installed`));
45
- console.log(chalk.green(` \u2714 7 slash commands installed`));
46
- console.log(chalk.green(` \u2714 3 hooks registered`));
45
+ console.log(chalk.green(` \u2714 8 slash commands installed`));
46
+ console.log(chalk.green(` \u2714 4 hooks registered`));
47
47
  if (statusLineConfigured) {
48
48
  console.log(chalk.green(` \u2714 StatusLine configured`));
49
49
  } else {
@@ -141,7 +141,7 @@ function showStatusTable(globalStatus, localStatus) {
141
141
  // Global hooks (always ~/.claude/hooks/)
142
142
  console.log();
143
143
  console.log(chalk.bold(' Global Hooks (~/.claude/hooks/)'));
144
- const hookKeys = ['hydra-check-update', 'hydra-statusline', 'hydra-auto-guard'];
144
+ const hookKeys = ['hydra-check-update', 'hydra-statusline', 'hydra-auto-guard', 'hydra-notify'];
145
145
  for (const key of hookKeys) {
146
146
  const dest = path.join(os.homedir(), '.claude', 'hooks', `${key}.js`);
147
147
  if (fileExists(dest)) {
package/src/files.js CHANGED
@@ -80,12 +80,18 @@ const commands = {
80
80
  'guard': readBundled('commands/hydra/guard.md'),
81
81
  'quiet': readBundled('commands/hydra/quiet.md'),
82
82
  'verbose': readBundled('commands/hydra/verbose.md'),
83
+ 'report': readBundled('commands/hydra/report.md'),
83
84
  };
84
85
 
85
86
  const hooks = {
86
87
  'hydra-check-update': readBundled('hooks/hydra-check-update.js'),
87
88
  'hydra-statusline': readBundled('hooks/hydra-statusline.js'),
88
89
  'hydra-auto-guard': readBundled('hooks/hydra-auto-guard.js'),
90
+ 'hydra-notify': readBundled('hooks/hydra-notify.js'),
89
91
  };
90
92
 
91
- module.exports = { agents, skill, references, commands, hooks };
93
+ const binaryHooks = {
94
+ 'hydra-task-complete.wav': path.join(FILES_DIR, 'hooks', 'hydra-task-complete.wav'),
95
+ };
96
+
97
+ module.exports = { agents, skill, references, commands, hooks, binaryHooks };
package/src/installer.js CHANGED
@@ -5,7 +5,7 @@ const path = require('path');
5
5
  const os = require('os');
6
6
  const chalk = require('chalk');
7
7
 
8
- const { agents, skill, references, commands, hooks } = require('./files');
8
+ const { agents, skill, references, commands, hooks, binaryHooks } = require('./files');
9
9
  const { showInstallHeader, showFileInstalled, showInstallComplete, showStatusTable, VERSION } = require('./display');
10
10
 
11
11
  // ── Install locations ────────────────────────────────────────────────────────
@@ -100,6 +100,17 @@ function installHooks() {
100
100
  showFileInstalled(`hooks/${key}.js`, false, err.message);
101
101
  }
102
102
  }
103
+
104
+ // Copy binary hook files (e.g., .wav) that can't be read as UTF-8 text
105
+ for (const [filename, srcPath] of Object.entries(binaryHooks)) {
106
+ const dest = path.join(hooksDir, filename);
107
+ try {
108
+ fs.copyFileSync(srcPath, dest);
109
+ showFileInstalled(`hooks/${filename}`, true);
110
+ } catch (err) {
111
+ showFileInstalled(`hooks/${filename}`, false, err.message);
112
+ }
113
+ }
103
114
  }
104
115
 
105
116
  function registerHooksInSettings() {
@@ -130,6 +141,12 @@ function registerHooksInSettings() {
130
141
  hooks: [{ type: 'command', command: 'node ~/.claude/hooks/hydra-auto-guard.js' }]
131
142
  });
132
143
 
144
+ if (!settings.hooks.Notification) settings.hooks.Notification = [];
145
+ settings.hooks.Notification = settings.hooks.Notification.filter(x => !isHydraHook(x));
146
+ settings.hooks.Notification.push({
147
+ hooks: [{ type: 'command', command: 'node ~/.claude/hooks/hydra-notify.js' }]
148
+ });
149
+
133
150
  let statusLineConfigured = false;
134
151
  if (!settings.statusLine || (settings.statusLine.command && settings.statusLine.command.includes('hydra-'))) {
135
152
  settings.statusLine = {
@@ -161,6 +178,10 @@ function deregisterHooks() {
161
178
  settings.hooks.PostToolUse = settings.hooks.PostToolUse.filter(x => !isHydraHook(x));
162
179
  if (!settings.hooks.PostToolUse.length) delete settings.hooks.PostToolUse;
163
180
  }
181
+ if (settings.hooks?.Notification) {
182
+ settings.hooks.Notification = settings.hooks.Notification.filter(x => !isHydraHook(x));
183
+ if (!settings.hooks.Notification.length) delete settings.hooks.Notification;
184
+ }
164
185
  if (settings.hooks && !Object.keys(settings.hooks).length) delete settings.hooks;
165
186
 
166
187
  if (settings.statusLine?.command?.includes('hydra-')) delete settings.statusLine;
@@ -305,6 +326,15 @@ async function runUninstall({ interactive = true } = {}) {
305
326
  }
306
327
  }
307
328
 
329
+ // Remove binary hook files (e.g., .wav)
330
+ for (const filename of Object.keys(binaryHooks)) {
331
+ const dest = path.join(GLOBAL_BASE, 'hooks', filename);
332
+ if (fileExists(dest)) {
333
+ try { fs.unlinkSync(dest); console.log(chalk.green(` \u2714 Removed hooks/${filename}`)); }
334
+ catch (err) { console.log(chalk.red(` \u2716 Failed: hooks/${filename} \u2014 ${err.message}`)); }
335
+ }
336
+ }
337
+
308
338
  // Remove cache file
309
339
  const cacheFile = path.join(GLOBAL_BASE, 'cache', 'hydra-update-check.json');
310
340
  if (fileExists(cacheFile)) {