hail-hydra-cc 1.2.0 → 1.2.2

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
@@ -44,7 +44,7 @@ npx hail-hydra-cc --help # Show help
44
44
 
45
45
  ```
46
46
  ~/.claude/ (or ./.claude/ for local)
47
- ├── agents/
47
+ ├── agents/ # 7 agent definitions
48
48
  │ ├── hydra-scout.md
49
49
  │ ├── hydra-runner.md
50
50
  │ ├── hydra-scribe.md
@@ -52,8 +52,21 @@ npx hail-hydra-cc --help # Show help
52
52
  │ ├── hydra-git.md
53
53
  │ ├── hydra-coder.md
54
54
  │ └── hydra-analyst.md
55
- └── hydra/
56
- ├── SKILL.md
55
+ ├── commands/hydra/ # 7 slash commands
56
+ ├── help.md # /hydra:help
57
+ │ ├── status.md # /hydra:status
58
+ │ ├── update.md # /hydra:update
59
+ │ ├── config.md # /hydra:config
60
+ │ ├── guard.md # /hydra:guard
61
+ │ ├── quiet.md # /hydra:quiet
62
+ │ └── verbose.md # /hydra:verbose
63
+ ├── hooks/ # 3 lifecycle hooks
64
+ │ ├── hydra-check-update.js # SessionStart — version check
65
+ │ ├── hydra-statusline.js # StatusLine — status bar
66
+ │ └── hydra-auto-guard.js # PostToolUse — file tracker
67
+ └── skills/hydra/ # Skill (Claude Code discoverable via /skills)
68
+ ├── SKILL.md # Orchestrator instructions
69
+ ├── VERSION # Installed version
57
70
  └── references/
58
71
  ├── routing-guide.md
59
72
  └── model-capabilities.md
package/bin/cli.js CHANGED
@@ -39,8 +39,8 @@ Examples:
39
39
 
40
40
  What gets installed:
41
41
  ~/.claude/agents/ 7 Hydra agent .md files
42
- ~/.claude/hydra/SKILL.md Core framework instructions
43
- ~/.claude/hydra/references/ Model capabilities & routing guides
42
+ ~/.claude/skills/hydra/SKILL.md Core framework instructions
43
+ ~/.claude/skills/hydra/references/ Model capabilities & routing guides
44
44
  `);
45
45
 
46
46
  // ── Main action ───────────────────────────────────────────────────────────────
package/files/SKILL.md CHANGED
@@ -1,15 +1,12 @@
1
1
  ---
2
2
  name: hydra
3
3
  description: >
4
- Hydra — multi-headed task execution framework for Claude Code that dramatically reduces
5
- latency and API costs. Inspired by speculative decoding in LLM inference, Hydra makes
6
- the main Opus agent an intelligent orchestrator that delegates work to Haiku 4.5 and Sonnet 4.6
7
- "heads," reserving Opus-level reasoning only for tasks that truly require it. ALWAYS
8
- activate this skill during any Claude Code session. This skill should be triggered for
9
- EVERY task — it is the default operating mode, not an optional optimization. Think of it
10
- as "always on" infrastructure, like an OS scheduler. If you are running as Opus and about
11
- to do work that a faster model could handle, delegate it. "Cut off one head, two more
12
- shall take its place" — except here, every head is working FOR you.
4
+ Multi-agent orchestration framework for Claude Code. Automatically delegates
5
+ tasks to cheaper, faster sub-agents (Haiku 4.5, Sonnet 4.6) while maintaining
6
+ Opus-level quality through verification. Use when working on any coding task
7
+ Hydra activates automatically to route file exploration, test running,
8
+ documentation, code writing, debugging, security scanning, and git operations
9
+ to the optimal agent. Saves ~50% on API costs.
13
10
  ---
14
11
 
15
12
  # 🐉 Hydra — Multi-Headed Speculative Execution
@@ -41,7 +38,7 @@ User Request
41
38
  │ │
42
39
  ▼ ▼
43
40
  ┌─────────────────────────────┐ ┌──────────────────────────────┐
44
- │ 🧠 ORCHESTRATOR (Opus) │ │ 🟢 hydra-scout (Haiku 4.5)
41
+ │ 🧠 ORCHESTRATOR (Opus) │ │ 🟢 hydra-scout
45
42
  │ Classifies task │ │ IMMEDIATE pre-dispatch: │
46
43
  │ Plans waves │ │ "Find files relevant to │
47
44
  │ Decides blocking / not │ │ [user's request]" │
@@ -364,7 +361,7 @@ Wave 4 → launch E (needs D complete)
364
361
  Classify every incoming task before executing. This is fast — just a mental check, not a separate
365
362
  step the user sees.
366
363
 
367
- ### Tier 1 → Haiku 4.5 Heads (hydra-scout (Haiku 4.5), hydra-runner (Haiku 4.5), hydra-scribe (Haiku 4.5), hydra-guard (Haiku 4.5), hydra-git (Haiku 4.5))
364
+ ### Tier 1 → Haiku 4.5 Heads (hydra-scout, hydra-runner, hydra-scribe, hydra-guard, hydra-git)
368
365
 
369
366
  Route to Haiku when the task is **mechanical, read-heavy, or well-defined**:
370
367
 
@@ -382,7 +379,7 @@ Route to Haiku when the task is **mechanical, read-heavy, or well-defined**:
382
379
  **Heuristic**: If you could describe the task as a single imperative sentence with no ambiguity
383
380
  (e.g., "find all files importing X", "run the test suite"), it's Tier 1.
384
381
 
385
- ### Tier 2 → Sonnet 4.6 Heads (hydra-coder (Sonnet 4.6), hydra-analyst (Sonnet 4.6))
382
+ ### Tier 2 → Sonnet 4.6 Heads (hydra-coder, hydra-analyst)
386
383
 
387
384
  Route to Sonnet when the task requires **reasoning about code, but within well-understood patterns**:
388
385
 
@@ -419,7 +416,7 @@ Keep it yourself when the task demands **deep reasoning, novel architecture, or
419
416
  - **When in doubt, go one tier up.** Better to use Sonnet for a Haiku task than Haiku for a
420
417
  Sonnet task. Quality is never sacrificed.
421
418
  - **Compound tasks should be decomposed.** "Read the codebase and redesign the auth system"
422
- becomes: hydra-scout (Haiku 4.5) reads, then you design (Opus).
419
+ becomes: hydra-scout reads, then you design (Opus).
423
420
  - **Iterative tasks escalate naturally.** If a Sonnet draft isn't right, don't retry with Sonnet —
424
421
  do it yourself.
425
422
 
@@ -501,20 +498,20 @@ These output types require no orchestrator judgment — accept and pass through:
501
498
 
502
499
  | Agent | Auto-Accept When |
503
500
  |-------|-----------------|
504
- | hydra-scout (Haiku 4.5) | Returns file paths, directory listings, search results, grep output — factual data with no interpretation |
505
- | hydra-runner (Haiku 4.5) | Reports all tests passing, clean build, clean lint — unambiguous pass/fail |
506
- | hydra-scribe (Haiku 4.5) | Produces docs/comments for NON-CRITICAL content (internal docstrings, changelogs) |
501
+ | hydra-scout | Returns file paths, directory listings, search results, grep output — factual data with no interpretation |
502
+ | hydra-runner | Reports all tests passing, clean build, clean lint — unambiguous pass/fail |
503
+ | hydra-scribe | Produces docs/comments for NON-CRITICAL content (internal docstrings, changelogs) |
507
504
 
508
505
  ### Manual Verify (orchestrator reviews before accepting)
509
506
  These outputs require judgment — scan before passing to user or downstream agents:
510
507
 
511
508
  | Agent | Always Verify When |
512
509
  |-------|-------------------|
513
- | hydra-coder (Sonnet 4.6) | ALWAYS — code changes are never auto-accepted |
514
- | hydra-analyst (Sonnet 4.6) | ALWAYS — diagnoses and recommendations need validation |
515
- | hydra-runner (Haiku 4.5) | Reports test FAILURES — verify the failures are real and not environment issues |
516
- | hydra-scribe (Haiku 4.5) | Writing user-facing docs (README, API docs) — verify accuracy |
517
- | hydra-scout (Haiku 4.5) | Returns analysis or interpretation (not raw data) — verify conclusions |
510
+ | hydra-coder | ALWAYS — code changes are never auto-accepted |
511
+ | hydra-analyst | ALWAYS — diagnoses and recommendations need validation |
512
+ | hydra-runner | Reports test FAILURES — verify the failures are real and not environment issues |
513
+ | hydra-scribe | Writing user-facing docs (README, API docs) — verify accuracy |
514
+ | hydra-scout | Returns analysis or interpretation (not raw data) — verify conclusions |
518
515
 
519
516
  ### Verification Decision Flowchart
520
517
 
@@ -554,8 +551,8 @@ When manual verification is required, match depth to risk:
554
551
 
555
552
  ## Auto-Guard Protocol
556
553
 
557
- After hydra-coder (Sonnet 4.6) produces any code changes, AUTOMATICALLY dispatch
558
- hydra-guard (Haiku 4.5) to scan the changes before presenting to the user. This is
554
+ After hydra-coder produces any code changes, AUTOMATICALLY dispatch
555
+ hydra-guard to scan the changes before presenting to the user. This is
559
556
  a non-blocking, low-cost quality gate that runs in the same wave as any final validation.
560
557
 
561
558
  ### Dispatch Rules
@@ -718,8 +715,8 @@ Hydra's heads live in `agents/`. Install them where Claude Code discovers subage
718
715
  ## Configuration
719
716
 
720
717
  At session start, check for a Hydra configuration file at:
721
- 1. `.claude/hydra/hydra.config.md` (project-level, takes precedence)
722
- 2. `~/.claude/hydra/hydra.config.md` (user-level, fallback)
718
+ 1. `.claude/skills/hydra/config/hydra.config.md` (project-level, takes precedence)
719
+ 2. `~/.claude/skills/hydra/config/hydra.config.md` (user-level, fallback)
723
720
 
724
721
  If found, apply the settings. If not found, use defaults:
725
722
  - **mode**: balanced
@@ -748,13 +745,13 @@ If the user types any of these exact phrases, respond with the corresponding act
748
745
 
749
746
  | Head | Model | Role | Tools |
750
747
  |------|-------|------|-------|
751
- | `hydra-scout (Haiku 4.5)` | 🟢 Haiku 4.5 | Codebase exploration, file search, reading | Read, Grep, Glob |
752
- | `hydra-runner (Haiku 4.5)` | 🟢 Haiku 4.5 | Test execution, builds, linting, validation | Read, Bash, Glob, Grep |
753
- | `hydra-scribe (Haiku 4.5)` | 🟢 Haiku 4.5 | Documentation, READMEs, comments, changelogs | Read, Write, Edit, Glob, Grep |
754
- | `hydra-guard (Haiku 4.5)` | 🟢 Haiku 4.5 | Security/quality gate after code changes | Read, Grep, Glob, Bash |
755
- | `hydra-git (Haiku 4.5)` | 🟢 Haiku 4.5 | Git operations: commit, branch, diff, log | Read, Bash, Glob, Grep |
756
- | `hydra-coder (Sonnet 4.6)` | 🔵 Sonnet 4.6 | Code writing, implementation, refactoring | Read, Write, Edit, Bash, Glob, Grep |
757
- | `hydra-analyst (Sonnet 4.6)` | 🔵 Sonnet 4.6 | Code review, debugging, architecture analysis | Read, Grep, Glob, Bash |
748
+ | `hydra-scout` | 🟢 Haiku 4.5 | Codebase exploration, file search, reading | Read, Grep, Glob |
749
+ | `hydra-runner` | 🟢 Haiku 4.5 | Test execution, builds, linting, validation | Read, Bash, Glob, Grep |
750
+ | `hydra-scribe` | 🟢 Haiku 4.5 | Documentation, READMEs, comments, changelogs | Read, Write, Edit, Glob, Grep |
751
+ | `hydra-guard` | 🟢 Haiku 4.5 | Security/quality gate after code changes | Read, Grep, Glob, Bash |
752
+ | `hydra-git` | 🟢 Haiku 4.5 | Git operations: commit, branch, diff, log | Read, Bash, Glob, Grep |
753
+ | `hydra-coder` | 🔵 Sonnet 4.6 | Code writing, implementation, refactoring | Read, Write, Edit, Bash, Glob, Grep |
754
+ | `hydra-analyst` | 🔵 Sonnet 4.6 | Code review, debugging, architecture analysis | Read, Grep, Glob, Bash |
758
755
 
759
756
  ## Measuring Impact
760
757
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: hydra-analyst (Sonnet 4.6)
2
+ name: hydra-analyst
3
3
  description: >
4
4
  🔵 Hydra's analysis head — thorough code review, debugging, and analysis agent. Use
5
5
  PROACTIVELY whenever Claude needs to review code for quality, analyze a bug with error
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: hydra-coder (Sonnet 4.6)
2
+ name: hydra-coder
3
3
  description: >
4
4
  🔵 Hydra's implementation head — capable code writing and engineering agent. Use PROACTIVELY
5
5
  whenever Claude needs to write new code, implement features, refactor existing code, create
@@ -1,11 +1,11 @@
1
1
  ---
2
- name: hydra-git (Haiku 4.5)
2
+ name: hydra-git
3
3
  description: >
4
4
  🟢 Hydra's git operations specialist. Handles all version control tasks: staging,
5
5
  committing with well-crafted Conventional Commits messages, branching, merging,
6
6
  rebasing, stashing, cherry-picking, log inspection, diff analysis, and conflict
7
7
  detection. Runs on Haiku 4.5 — git operations are mechanical and well-defined.
8
- Use hydra-analyst (Sonnet 4.6) for merge conflict RESOLUTION (requires code
8
+ Use hydra-analyst for merge conflict RESOLUTION (requires code
9
9
  comprehension) but hydra-git for conflict DETECTION and all other git operations.
10
10
  May run in parallel with other Hydra agents — produces self-contained, clearly
11
11
  structured output so the orchestrator can merge results from multiple simultaneous agents.
@@ -42,7 +42,7 @@ You are hydra-git — Hydra's version control specialist. You handle git operati
42
42
  3. **Never force-push without explicit orchestrator instruction.** Ask before any destructive push.
43
43
 
44
44
  4. **Detect conflicts, don't resolve them.** If a merge or rebase hits a conflict, stop, report
45
- which files are conflicted and why, and flag for hydra-analyst (Sonnet 4.6) to resolve.
45
+ which files are conflicted and why, and flag for hydra-analyst to resolve.
46
46
 
47
47
  5. **Auto-stage sensibly.** When committing, stage files related to the described change.
48
48
  Do not stage .env, credentials, or large binaries. Flag these if you encounter them.
@@ -89,7 +89,7 @@ Changes in this diff:
89
89
 
90
90
  - Never force-push to main/master without explicit instruction
91
91
  - Never commit .env files, credential files, or secrets
92
- - Never resolve merge conflicts — detect and escalate to hydra-analyst (Sonnet 4.6)
92
+ - Never resolve merge conflicts — detect and escalate to hydra-analyst
93
93
  - Never amend published commits without explicit instruction
94
94
  - Never skip pre-commit hooks (--no-verify) without explicit instruction
95
95
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: hydra-guard (Haiku 4.5)
2
+ name: hydra-guard
3
3
  description: >
4
4
  🟢 Hydra's security and quality gate agent. Automatically invoked after hydra-coder
5
5
  (Sonnet 4.6) produces code changes. Performs a fast scan for common security issues
@@ -7,7 +7,7 @@ description: >
7
7
  code quality checks (unused imports, dead code, missing error handling on async
8
8
  operations), and leftover debug artifacts (console.log, TODO/FIXME/HACK comments).
9
9
  Runs on Haiku 4.5 for speed — this is a fast gate, not a deep audit. For deep
10
- security review, use hydra-analyst (Sonnet 4.6) instead.
10
+ security review, use hydra-analyst instead.
11
11
  May run in parallel with other Hydra agents — produces self-contained, clearly
12
12
  structured output so the orchestrator can merge results from multiple simultaneous agents.
13
13
  tools: Read, Grep, Glob, Bash
@@ -91,7 +91,7 @@ Note: Savings calculated against Opus 4.6 ($5/$25 per MTok). These are warnings
91
91
  - Never modify source files
92
92
  - Never block or delay delivery of hydra-coder's output
93
93
  - Never flag false positives — verify the pattern before reporting
94
- - Never perform deep architectural security analysis — that's hydra-analyst (Sonnet 4.6)
94
+ - Never perform deep architectural security analysis — that's hydra-analyst
95
95
  - If a scan would take more than 30 seconds, report what you found and stop
96
96
 
97
97
  ## Collaboration Protocol
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: hydra-runner (Haiku 4.5)
2
+ name: hydra-runner
3
3
  description: >
4
4
  🟢 Hydra's execution head — fast test runner, build executor, and validation agent.
5
5
  Use PROACTIVELY whenever Claude needs to run tests, execute builds, check linting, verify
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: hydra-scout (Haiku 4.5)
2
+ name: hydra-scout
3
3
  description: >
4
4
  🟢 Hydra's fastest head — ultra-fast codebase exploration and information retrieval.
5
5
  Use PROACTIVELY whenever Claude needs to search files, read code, find patterns, grep for
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: hydra-scribe (Haiku 4.5)
2
+ name: hydra-scribe
3
3
  description: >
4
4
  🟢 Hydra's documentation head — fast technical writing agent. Use PROACTIVELY whenever
5
5
  Claude needs to write or update README files, add code comments or docstrings, create
@@ -0,0 +1,37 @@
1
+ ---
2
+ description: Show current Hydra configuration and how to customize it
3
+ allowed-tools: Read, Bash
4
+ ---
5
+
6
+ # Hydra Config
7
+
8
+ Show the current Hydra configuration:
9
+
10
+ 1. Check for project-level config first:
11
+ ```bash
12
+ cat .claude/skills/hydra/config/hydra.config.md 2>/dev/null
13
+ ```
14
+
15
+ 2. If not found, check global config:
16
+ ```bash
17
+ cat ~/.claude/skills/hydra/config/hydra.config.md 2>/dev/null
18
+ ```
19
+
20
+ 3. If neither found, show defaults:
21
+
22
+ ```
23
+ 🐉 Hydra Configuration (defaults — no config file found)
24
+ ─────────────────────────────
25
+ Mode: balanced
26
+ Dispatch Log: on
27
+ Auto-Guard: on
28
+ Model Overrides: none
29
+ ─────────────────────────────
30
+ To customize, create a config file:
31
+ Global: ~/.claude/skills/hydra/config/hydra.config.md
32
+ Project: .claude/skills/hydra/config/hydra.config.md
33
+
34
+ Run /hydra:status to see current agent assignments.
35
+ ```
36
+
37
+ 4. If a config file IS found, display its contents and note where it was loaded from.
@@ -0,0 +1,71 @@
1
+ ---
2
+ description: Manually run the Hydra security and quality scan on specified files or directories
3
+ allowed-tools: Read, Grep, Glob, Bash
4
+ model: haiku
5
+ ---
6
+
7
+ # Hydra Guard — Manual Security Scan
8
+
9
+ Run a focused security and quality scan on the specified files.
10
+
11
+ **Target**: $ARGUMENTS
12
+
13
+ If no arguments provided, scan all files changed since the last commit:
14
+ ```bash
15
+ git diff --name-only HEAD 2>/dev/null || echo "Not a git repository or no changes"
16
+ ```
17
+
18
+ ## Scan Checklist
19
+
20
+ For each target file, check for:
21
+
22
+ ### CRITICAL (security)
23
+ - Hardcoded secrets, API keys, tokens, passwords (patterns: `sk-`, `ghp_`, `AKIA`, `password =`, `secret =`, `token =`, `api_key =`)
24
+ - SQL injection vulnerabilities (string concatenation in queries)
25
+ - XSS vulnerabilities (unescaped user input in HTML output)
26
+ - Unsafe deserialization (`eval()`, `pickle.loads()`, `unserialize()`)
27
+ - Path traversal (`../` in file operations without validation)
28
+ - Command injection (user input passed to shell commands)
29
+
30
+ ### WARNING (quality)
31
+ - `console.log` / `print()` debug leftovers
32
+ - TODO/FIXME/HACK comments
33
+ - Unused imports (obvious cases only)
34
+ - Missing error handling on async operations (no try/catch, no .catch())
35
+ - Empty catch blocks
36
+ - Hardcoded URLs or magic numbers without constants
37
+
38
+ ### INFO (style)
39
+ - Functions longer than 100 lines
40
+ - Deeply nested conditionals (3+ levels)
41
+ - Inconsistent naming conventions within the same file
42
+
43
+ ## Output Format
44
+
45
+ ```
46
+ 🐉 Hydra Guard — Security & Quality Report
47
+ ═══════════════════════════════════════════
48
+ Files scanned: 3
49
+
50
+ 🔴 CRITICAL (2 findings)
51
+ src/auth.py:45 Hardcoded API key: OPENAI_KEY = "sk-..."
52
+ src/db.py:78 SQL injection: f-string in query construction
53
+
54
+ ⚠️ WARNING (3 findings)
55
+ src/auth.py:12 console.log left in production code
56
+ src/utils.py:89 Empty catch block — errors silently swallowed
57
+ src/api.py:34 TODO: "fix this later" (line 34)
58
+
59
+ ℹ️ INFO (1 finding)
60
+ src/handler.py:1 Function process_request is 142 lines long
61
+
62
+ Summary: 2 critical · 3 warnings · 1 info
63
+ ```
64
+
65
+ If no issues found:
66
+ ```
67
+ 🐉 Hydra Guard — All Clear ✅
68
+ Files scanned: 3 | No issues found.
69
+ ```
70
+
71
+ **Important**: This is a FAST scan, not a deep audit. For thorough security review, use hydra-analyst instead.
@@ -0,0 +1,41 @@
1
+ ---
2
+ description: Show all available Hydra commands, agents, and a quick reference guide
3
+ ---
4
+
5
+ # Hydra Help
6
+
7
+ Display the following help reference directly — do NOT search files or run commands:
8
+
9
+ ```
10
+ 🐉 Hydra Framework — Quick Reference
11
+ ═══════════════════════════════════════
12
+ COMMANDS
13
+ /hydra:help Show this help screen
14
+ /hydra:status Show installed agents, version, config
15
+ /hydra:update Update Hydra to the latest version
16
+ /hydra:config Show current configuration
17
+ /hydra:guard Run security scan on files (usage: /hydra:guard src/auth.py)
18
+ /hydra:quiet Suppress dispatch logs for this session
19
+ /hydra:verbose Enable verbose dispatch logs with timing
20
+
21
+ AGENTS
22
+ 🟢 hydra-scout (Haiku 4.5) — Explore codebase, find files, map structure
23
+ 🟢 hydra-runner (Haiku 4.5) — Run tests, linters, build commands
24
+ 🟢 hydra-scribe (Haiku 4.5) — Write docs, comments, READMEs
25
+ 🟢 hydra-guard (Haiku 4.5) — Security scan, quality gate
26
+ 🟢 hydra-git (Haiku 4.5) — Git operations, commits, branches
27
+ 🔵 hydra-coder (Sonnet 4.6) — Write and edit code
28
+ 🔵 hydra-analyst (Sonnet 4.6) — Debug, diagnose, review
29
+
30
+ HOW IT WORKS
31
+ The Opus 4.6 orchestrator automatically delegates tasks to cheaper,
32
+ faster agents (Haiku 4.5 and Sonnet 4.6) — saving ~50% on API costs
33
+ while maintaining Opus-level quality through verification.
34
+
35
+ You don't need to do anything. Just work normally.
36
+ Hydra operates invisibly unless you check the dispatch log.
37
+
38
+ LINKS
39
+ GitHub: https://github.com/AR6420/Hail_Hydra
40
+ npm: https://www.npmjs.com/package/hail-hydra-cc
41
+ ```
@@ -0,0 +1,14 @@
1
+ ---
2
+ description: Suppress Hydra dispatch logs for the rest of this session
3
+ ---
4
+
5
+ # Hydra Quiet Mode
6
+
7
+ Acknowledge this command and remember for the rest of this session:
8
+
9
+ **Do NOT display the Hydra Dispatch Log footer after tasks.**
10
+
11
+ Respond with:
12
+ "🐉 Quiet mode enabled. Dispatch logs suppressed for this session. Use /hydra:verbose to re-enable."
13
+
14
+ Continue operating Hydra normally (delegation, verification, auto-guard) — just don't show the dispatch log table.
@@ -0,0 +1,72 @@
1
+ ---
2
+ description: Show Hydra framework status — installed agents, version, config, and update availability
3
+ allowed-tools: Bash, Read, Glob
4
+ ---
5
+
6
+ # Hydra Status
7
+
8
+ Show a comprehensive status report for the Hydra framework.
9
+
10
+ ## 1. Version Info
11
+ ```bash
12
+ INSTALLED=$(cat ~/.claude/skills/hydra/VERSION 2>/dev/null || echo "unknown")
13
+ echo "Installed: $INSTALLED"
14
+ LATEST=$(npm view hail-hydra-cc version 2>/dev/null || echo "unknown")
15
+ echo "Latest: $LATEST"
16
+ ```
17
+
18
+ ## 2. Installed Agents
19
+ ```bash
20
+ echo "=== Global Agents ==="
21
+ ls -1 ~/.claude/agents/hydra-*.md 2>/dev/null || echo "None found"
22
+ echo "=== Local Agents ==="
23
+ ls -1 .claude/agents/hydra-*.md 2>/dev/null || echo "None found"
24
+ ```
25
+
26
+ ## 3. Installed Commands
27
+ ```bash
28
+ echo "=== Global Commands ==="
29
+ ls -1 ~/.claude/commands/hydra/*.md 2>/dev/null || echo "None found"
30
+ echo "=== Local Commands ==="
31
+ ls -1 .claude/commands/hydra/*.md 2>/dev/null || echo "None found"
32
+ ```
33
+
34
+ ## 4. Hooks
35
+ ```bash
36
+ ls -1 ~/.claude/hooks/hydra-*.js 2>/dev/null || echo "None found"
37
+ ```
38
+
39
+ ## 5. Configuration
40
+ ```bash
41
+ cat ~/.claude/skills/hydra/config/hydra.config.md 2>/dev/null || \
42
+ cat .claude/skills/hydra/config/hydra.config.md 2>/dev/null || \
43
+ echo "No config file found (using defaults)"
44
+ ```
45
+
46
+ ## Display Format
47
+
48
+ Present results as a clean status card:
49
+
50
+ ```
51
+ 🐉 Hydra Framework Status
52
+ ──────────────────────────────
53
+ Version: 1.0.0 (latest: 1.0.0 ✅) OR (update available: 1.1.0 ⚡)
54
+ Install: Global (~/.claude/)
55
+ Agents (7):
56
+ 🟢 hydra-scout (Haiku 4.5) ✅
57
+ 🟢 hydra-runner (Haiku 4.5) ✅
58
+ 🟢 hydra-scribe (Haiku 4.5) ✅
59
+ 🟢 hydra-guard (Haiku 4.5) ✅
60
+ 🟢 hydra-git (Haiku 4.5) ✅
61
+ 🔵 hydra-coder (Sonnet 4.6) ✅
62
+ 🔵 hydra-analyst (Sonnet 4.6) ✅
63
+ Commands (7): update, status, help, config, guard, quiet, verbose
64
+ Hooks (3): check-update ✅, statusline ✅, auto-guard ✅
65
+ Config: balanced mode, dispatch log on, auto-guard on
66
+ ──────────────────────────────
67
+ ```
68
+
69
+ If an update is available, add:
70
+ ```
71
+ ⚡ Update available! Run /hydra:update to get the latest version.
72
+ ```
@@ -0,0 +1,35 @@
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.
@@ -0,0 +1,27 @@
1
+ ---
2
+ description: Enable verbose Hydra dispatch logs with timing and token estimates
3
+ ---
4
+
5
+ # Hydra Verbose Mode
6
+
7
+ Acknowledge this command and remember for the rest of this session:
8
+
9
+ **Display DETAILED Hydra Dispatch Logs after every task that involves delegation.**
10
+
11
+ The verbose log includes extra columns for timing:
12
+
13
+ ```
14
+ 🐉 Hydra Dispatch Log (verbose)
15
+ | Step | Agent | Task | Time | Verdict |
16
+ |------|---------------------|-----------------------|-------|-------------|
17
+ | 1 | hydra-scout (Haiku 4.5) | Explored auth module | 3.2s | ✅ Accepted |
18
+ | 2 | hydra-coder (Sonnet 4.6) | Fixed null check | 8.1s | ✅ Accepted |
19
+ | 3 | hydra-guard (Haiku 4.5) | Security scan | 1.4s | ✅ Passed |
20
+ | 4 | hydra-runner (Haiku 4.5) | Ran test suite | 4.7s | ✅ Accepted |
21
+
22
+ Delegation: 4/4 (100%) | Accepted: 4 | Adjusted: 0 | Rejected: 0
23
+ Total delegation time: 17.4s | Waves: 2
24
+ ```
25
+
26
+ Respond with:
27
+ "🐉 Verbose mode enabled. Dispatch logs will include timing details. Use /hydra:quiet to suppress."
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Hydra Auto-Guard Hook — PostToolUse (matcher: Write|Edit|MultiEdit)
4
+ // Records changed file paths to a temp file for hydra-guard to scan later.
5
+ // Does NOT run the scan itself — that would slow down every edit.
6
+ // Overhead: <1ms per edit. Files deduped by path.
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const os = require('os');
11
+
12
+ let input = '';
13
+ process.stdin.on('data', (chunk) => (input += chunk));
14
+ process.stdin.on('end', () => {
15
+ try {
16
+ const data = JSON.parse(input);
17
+
18
+ // Extract the file path from the tool input
19
+ const filePath = data.tool_input?.file_path ||
20
+ data.tool_input?.path ||
21
+ null;
22
+
23
+ if (!filePath) {
24
+ process.exit(0);
25
+ }
26
+
27
+ // Append to session-scoped changed files list
28
+ const sessionId = data.session_id || 'unknown';
29
+ const trackingDir = path.join(os.tmpdir(), 'hydra-guard');
30
+ const trackingFile = path.join(trackingDir, `${sessionId}.txt`);
31
+
32
+ // Ensure directory exists
33
+ if (!fs.existsSync(trackingDir)) {
34
+ fs.mkdirSync(trackingDir, { recursive: true });
35
+ }
36
+
37
+ // Read existing tracked files
38
+ let existing = '';
39
+ try {
40
+ existing = fs.readFileSync(trackingFile, 'utf8');
41
+ } catch (e) {
42
+ // File doesn't exist yet — that's fine
43
+ }
44
+
45
+ // Only append if not already tracked (dedup)
46
+ if (!existing.split('\n').includes(filePath)) {
47
+ fs.appendFileSync(trackingFile, filePath + '\n');
48
+ }
49
+
50
+ } catch (e) {
51
+ // Silently fail — NEVER block Claude Code
52
+ }
53
+ process.exit(0);
54
+ });
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Hydra Update Checker — SessionStart hook
4
+ // Spawns a DETACHED background process to check npm for updates.
5
+ // Writes result to ~/.claude/cache/hydra-update-check.json
6
+ // The statusline hook reads this cache file.
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const os = require('os');
11
+ const { spawn } = require('child_process');
12
+
13
+ const homeDir = os.homedir();
14
+ const cacheDir = path.join(homeDir, '.claude', 'cache');
15
+ const cacheFile = path.join(cacheDir, 'hydra-update-check.json');
16
+
17
+ // VERSION file locations (check project first, then global)
18
+ const projectVersionFile = path.join(process.cwd(), '.claude', 'hydra', 'VERSION');
19
+ const globalVersionFile = path.join(homeDir, '.claude', 'hydra', 'VERSION');
20
+
21
+ // Ensure cache directory exists
22
+ if (!fs.existsSync(cacheDir)) {
23
+ fs.mkdirSync(cacheDir, { recursive: true });
24
+ }
25
+
26
+ // Skip check if we checked within the last hour
27
+ try {
28
+ const existing = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
29
+ const age = Date.now() - (existing.checked_at || 0);
30
+ if (age < 3600000) { // 1 hour
31
+ process.exit(0);
32
+ }
33
+ } catch (e) {
34
+ // No cache or invalid — proceed with check
35
+ }
36
+
37
+ // Read stdin to prevent EPIPE (Claude Code pipes JSON to all hooks)
38
+ let stdinData = '';
39
+ process.stdin.on('data', (chunk) => (stdinData += chunk));
40
+ process.stdin.on('end', () => {
41
+ // Spawn background process (MUST be detached to not block Claude Code)
42
+ const child = spawn(process.execPath, ['-e', `
43
+ const fs = require('fs');
44
+ const { execSync } = require('child_process');
45
+
46
+ const cacheFile = ${JSON.stringify(cacheFile)};
47
+ const projectVersionFile = ${JSON.stringify(projectVersionFile)};
48
+ const globalVersionFile = ${JSON.stringify(globalVersionFile)};
49
+
50
+ try {
51
+ // Read installed version
52
+ let installed = 'unknown';
53
+ try {
54
+ installed = fs.readFileSync(projectVersionFile, 'utf8').trim();
55
+ } catch (e) {
56
+ try {
57
+ installed = fs.readFileSync(globalVersionFile, 'utf8').trim();
58
+ } catch (e2) {}
59
+ }
60
+
61
+ // Fetch latest version from npm (with timeout)
62
+ const latest = execSync('npm view hail-hydra-cc version', {
63
+ encoding: 'utf8',
64
+ timeout: 10000,
65
+ windowsHide: true,
66
+ stdio: ['pipe', 'pipe', 'pipe']
67
+ }).trim();
68
+
69
+ // Compare and write cache
70
+ const updateAvailable = installed !== 'unknown' && latest !== installed;
71
+
72
+ const result = {
73
+ installed: installed,
74
+ latest: latest,
75
+ update_available: updateAvailable,
76
+ checked_at: Date.now()
77
+ };
78
+
79
+ fs.writeFileSync(cacheFile, JSON.stringify(result, null, 2));
80
+ } catch (e) {
81
+ // Network error or npm not available — write a "no check" result
82
+ const result = {
83
+ installed: 'unknown',
84
+ latest: 'unknown',
85
+ update_available: false,
86
+ checked_at: Date.now(),
87
+ error: e.message
88
+ };
89
+ fs.writeFileSync(cacheFile, JSON.stringify(result, null, 2));
90
+ }
91
+ `], {
92
+ stdio: 'ignore',
93
+ windowsHide: true,
94
+ detached: true // CRITICAL: prevents blocking Claude Code input on Windows
95
+ });
96
+
97
+ child.unref();
98
+ process.exit(0);
99
+ });
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Hydra StatusLine — persistent status bar at bottom of Claude Code
4
+ // Receives session JSON via stdin, outputs one formatted line to stdout.
5
+ //
6
+ // Display format:
7
+ // 🐉 │ Opus │ Ctx: 37% ████░░░░░░ │ $0.42 │ my-project │ ⚡ Update available
8
+ //
9
+ // Context bar is color-coded:
10
+ // Green (0-49%) → Yellow (50-79%) → Red (80%+)
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const os = require('os');
15
+
16
+ const cacheFile = path.join(os.homedir(), '.claude', 'cache', 'hydra-update-check.json');
17
+
18
+ let input = '';
19
+ process.stdin.on('data', (chunk) => (input += chunk));
20
+ process.stdin.on('end', () => {
21
+ try {
22
+ const data = JSON.parse(input);
23
+
24
+ // === Model ===
25
+ const model = data.model?.display_name || 'Unknown';
26
+
27
+ // === Context Usage ===
28
+ // Use precomputed used_percentage from Claude Code (most reliable)
29
+ const ctxPct = Math.round(data.context_window?.used_percentage || 0);
30
+
31
+ // Build visual context bar (10 chars wide)
32
+ const filled = Math.round(ctxPct / 10);
33
+ const empty = 10 - filled;
34
+ const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(empty);
35
+
36
+ // Color-code: Green <50%, Yellow 50-79%, Red 80%+
37
+ let ctxColor;
38
+ if (ctxPct < 50) {
39
+ ctxColor = '\x1b[32m'; // Green
40
+ } else if (ctxPct < 80) {
41
+ ctxColor = '\x1b[33m'; // Yellow
42
+ } else {
43
+ ctxColor = '\x1b[31m'; // Red
44
+ }
45
+ const reset = '\x1b[0m';
46
+ const dim = '\x1b[2m';
47
+
48
+ const ctxDisplay = `${ctxColor}Ctx: ${ctxPct}% ${bar}${reset}`;
49
+
50
+ // === Session Cost ===
51
+ const cost = (data.cost?.total_cost_usd || 0).toFixed(2);
52
+
53
+ // === Working Directory ===
54
+ const dirName = path.basename(data.workspace?.current_dir || data.cwd || '');
55
+
56
+ // === Update Check (read from cache) ===
57
+ let updateNotice = '';
58
+ try {
59
+ const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
60
+ if (cache.update_available) {
61
+ updateNotice = ` \x1b[33m\u26A1 v${cache.latest} available${reset}`;
62
+ }
63
+ } catch (e) {
64
+ // No cache — skip update notice
65
+ }
66
+
67
+ // === Compose Status Line ===
68
+ const parts = [
69
+ '\x1b[32m\uD83D\uDC32\x1b[0m', // Green dragon emoji (🐉)
70
+ `${dim}${model}${reset}`, // Dim model name
71
+ ctxDisplay, // Color-coded context bar
72
+ `${dim}$${cost}${reset}`, // Dim cost
73
+ `${dim}${dirName}${reset}`, // Dim directory
74
+ ];
75
+
76
+ // Append update notice if available
77
+ if (updateNotice) {
78
+ parts.push(updateNotice);
79
+ }
80
+
81
+ process.stdout.write(parts.join(' \u2502 '));
82
+
83
+ } catch (e) {
84
+ // Fallback if JSON parse fails
85
+ process.stdout.write('\uD83D\uDC32 Hydra');
86
+ }
87
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hail-hydra-cc",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Multi-headed speculative execution framework for Claude Code",
5
5
  "bin": {
6
6
  "hail-hydra-cc": "bin/cli.js"
@@ -36,5 +36,9 @@
36
36
  "bin/",
37
37
  "src/",
38
38
  "files/"
39
- ]
39
+ ],
40
+ "publishConfig": {
41
+ "registry": "https://registry.npmjs.org/",
42
+ "access": "public"
43
+ }
40
44
  }
package/src/display.js CHANGED
@@ -37,17 +37,36 @@ function showFileInstalled(displayName, success, errorMsg) {
37
37
  }
38
38
  }
39
39
 
40
- function showInstallComplete() {
40
+ function showInstallComplete(statusLineConfigured = true) {
41
41
  console.log();
42
- console.log(chalk.cyan.bold(' 🐉 Hail Hydra! 7 heads deployed and ready.'));
42
+ console.log(chalk.cyan.bold(' \uD83D\uDC09 Hail Hydra! Framework deployed and ready.'));
43
+ console.log(chalk.gray(' ' + '\u2500'.repeat(45)));
44
+ console.log(chalk.green(` \u2714 7 agents installed`));
45
+ console.log(chalk.green(` \u2714 7 slash commands installed`));
46
+ console.log(chalk.green(` \u2714 3 hooks registered`));
47
+ if (statusLineConfigured) {
48
+ console.log(chalk.green(` \u2714 StatusLine configured`));
49
+ } else {
50
+ console.log(chalk.yellow(` \u26a0 StatusLine skipped (existing config preserved)`));
51
+ }
52
+ console.log(chalk.green(` \u2714 Version tracked (${VERSION})`));
43
53
  console.log();
44
- console.log(chalk.gray(' Launch Claude Code to start using the framework.'));
54
+ console.log(chalk.gray(' Quick start: /hydra:help'));
55
+ console.log(chalk.gray(' Check status: /hydra:status'));
45
56
  console.log(chalk.gray(' GitHub: https://github.com/AR6420/Hail_Hydra'));
46
57
  console.log();
47
58
  }
48
59
 
49
60
  function showStatusTable(globalStatus, localStatus) {
50
- const divider = chalk.gray(' ' + '─'.repeat(50));
61
+ const os = require('os');
62
+ const path = require('path');
63
+ const fs = require('fs');
64
+
65
+ function fileExists(p) {
66
+ try { fs.accessSync(p, fs.constants.F_OK); return true; } catch { return false; }
67
+ }
68
+
69
+ const divider = chalk.gray(' ' + '\u2500'.repeat(50));
51
70
 
52
71
  console.log();
53
72
  console.log(chalk.bold(' Installation Status'));
@@ -65,7 +84,9 @@ function showStatusTable(globalStatus, localStatus) {
65
84
  const anyInstalled =
66
85
  status.agents.some((a) => a.installed) ||
67
86
  status.skill ||
68
- status.references.some((r) => r.installed);
87
+ status.references.some((r) => r.installed) ||
88
+ (status.commands && status.commands.some((c) => c.installed)) ||
89
+ status.version;
69
90
 
70
91
  if (!anyInstalled) {
71
92
  console.log(chalk.gray(' (not installed)'));
@@ -73,29 +94,60 @@ function showStatusTable(globalStatus, localStatus) {
73
94
  }
74
95
 
75
96
  for (const agent of status.agents) {
76
- const dot = agent.model === 'Haiku' ? chalk.green('🟢') : chalk.blue('🔵');
77
- const name = chalk.bold(agent.display.split('')[0].trim());
78
- const role = chalk.gray(' ' + agent.display.split('')[1].trim());
97
+ const dot = agent.model === 'Haiku' ? chalk.green('\uD83D\uDFE2') : chalk.blue('\uD83D\uDD35');
98
+ const name = chalk.bold(agent.display.split('\u2014')[0].trim());
99
+ const role = chalk.gray('\u2014 ' + agent.display.split('\u2014')[1].trim());
79
100
  if (agent.installed) {
80
- console.log(` ${dot} ${chalk.green('')} ${name} ${role}`);
101
+ console.log(` ${dot} ${chalk.green('\u2714')} ${name} ${role}`);
81
102
  } else {
82
- console.log(` ${dot} ${chalk.gray('')} ${chalk.gray(name)} ${chalk.gray(role + ' (not installed)')}`);
103
+ console.log(` ${dot} ${chalk.gray('\u2716')} ${chalk.gray(name)} ${chalk.gray(role + ' (not installed)')}`);
83
104
  }
84
105
  }
85
106
 
86
107
  if (status.skill) {
87
- console.log(chalk.green(' SKILL.md'));
108
+ console.log(chalk.green(' \u2714 SKILL.md'));
88
109
  } else {
89
- console.log(chalk.gray(' SKILL.md (not installed)'));
110
+ console.log(chalk.gray(' \u2716 SKILL.md (not installed)'));
90
111
  }
91
112
 
92
113
  for (const ref of status.references) {
93
114
  if (ref.installed) {
94
- console.log(chalk.green(` ${ref.name}`));
115
+ console.log(chalk.green(` \u2714 ${ref.name}`));
95
116
  } else {
96
- console.log(chalk.gray(` ${ref.name} (not installed)`));
117
+ console.log(chalk.gray(` \u2716 ${ref.name} (not installed)`));
118
+ }
119
+ }
120
+
121
+ // Commands
122
+ if (status.commands) {
123
+ for (const cmd of status.commands) {
124
+ if (cmd.installed) {
125
+ console.log(chalk.green(` \u2714 ${cmd.name}`));
126
+ } else {
127
+ console.log(chalk.gray(` \u2716 ${cmd.name} (not installed)`));
128
+ }
97
129
  }
98
130
  }
131
+
132
+ // Version
133
+ if (status.version) {
134
+ console.log(chalk.green(` \u2714 hydra/VERSION (${status.version})`));
135
+ } else {
136
+ console.log(chalk.gray(' \u2716 hydra/VERSION (not installed)'));
137
+ }
138
+ }
139
+
140
+ // Global hooks (always ~/.claude/hooks/)
141
+ console.log();
142
+ console.log(chalk.bold(' Global Hooks (~/.claude/hooks/)'));
143
+ const hookKeys = ['hydra-check-update', 'hydra-statusline', 'hydra-auto-guard'];
144
+ for (const key of hookKeys) {
145
+ const dest = path.join(os.homedir(), '.claude', 'hooks', `${key}.js`);
146
+ if (fileExists(dest)) {
147
+ console.log(chalk.green(` \u2714 ${key}.js`));
148
+ } else {
149
+ console.log(chalk.gray(` \u2716 ${key}.js (not installed)`));
150
+ }
99
151
  }
100
152
 
101
153
  console.log();
package/src/files.js CHANGED
@@ -62,4 +62,20 @@ const references = {
62
62
  'model-capabilities': readBundled('references/model-capabilities.md'),
63
63
  };
64
64
 
65
- module.exports = { agents, skill, references };
65
+ const commands = {
66
+ 'update': readBundled('commands/hydra/update.md'),
67
+ 'status': readBundled('commands/hydra/status.md'),
68
+ 'help': readBundled('commands/hydra/help.md'),
69
+ 'config': readBundled('commands/hydra/config.md'),
70
+ 'guard': readBundled('commands/hydra/guard.md'),
71
+ 'quiet': readBundled('commands/hydra/quiet.md'),
72
+ 'verbose': readBundled('commands/hydra/verbose.md'),
73
+ };
74
+
75
+ const hooks = {
76
+ 'hydra-check-update': readBundled('hooks/hydra-check-update.js'),
77
+ 'hydra-statusline': readBundled('hooks/hydra-statusline.js'),
78
+ 'hydra-auto-guard': readBundled('hooks/hydra-auto-guard.js'),
79
+ };
80
+
81
+ module.exports = { agents, skill, references, commands, hooks };
package/src/installer.js CHANGED
@@ -5,8 +5,8 @@ const path = require('path');
5
5
  const os = require('os');
6
6
  const chalk = require('chalk');
7
7
 
8
- const { agents, skill, references } = require('./files');
9
- const { showInstallHeader, showFileInstalled, showInstallComplete, showStatusTable } = require('./display');
8
+ const { agents, skill, references, commands, hooks } = require('./files');
9
+ const { showInstallHeader, showFileInstalled, showInstallComplete, showStatusTable, VERSION } = require('./display');
10
10
 
11
11
  // ── Install locations ────────────────────────────────────────────────────────
12
12
 
@@ -28,9 +28,9 @@ function buildManifest(base) {
28
28
  const skillEntry = {
29
29
  type: 'skill',
30
30
  key: 'SKILL.md',
31
- display: 'SKILL.md',
31
+ display: 'skills/hydra/SKILL.md',
32
32
  content: skill,
33
- dest: path.join(base, 'hydra', 'SKILL.md'),
33
+ dest: path.join(base, 'skills', 'hydra', 'SKILL.md'),
34
34
  };
35
35
 
36
36
  const refEntries = Object.entries(references).map(([key, content]) => ({
@@ -38,10 +38,26 @@ function buildManifest(base) {
38
38
  key,
39
39
  display: `references/${key}.md`,
40
40
  content,
41
- dest: path.join(base, 'hydra', 'references', `${key}.md`),
41
+ dest: path.join(base, 'skills', 'hydra', 'references', `${key}.md`),
42
42
  }));
43
43
 
44
- return [...agentEntries, skillEntry, ...refEntries];
44
+ const commandEntries = Object.entries(commands).map(([key, content]) => ({
45
+ type: 'command',
46
+ key,
47
+ display: `commands/hydra/${key}.md`,
48
+ content,
49
+ dest: path.join(base, 'commands', 'hydra', `${key}.md`),
50
+ }));
51
+
52
+ const versionEntry = {
53
+ type: 'version',
54
+ key: 'VERSION',
55
+ display: 'skills/hydra/VERSION',
56
+ content: VERSION,
57
+ dest: path.join(base, 'skills', 'hydra', 'VERSION'),
58
+ };
59
+
60
+ return [...agentEntries, skillEntry, ...refEntries, ...commandEntries, versionEntry];
45
61
  }
46
62
 
47
63
  // ── Helpers ──────────────────────────────────────────────────────────────────
@@ -68,6 +84,94 @@ function hasAnyInstalled(base) {
68
84
  return buildManifest(base).some((entry) => fileExists(entry.dest));
69
85
  }
70
86
 
87
+ // ── Hooks & settings ─────────────────────────────────────────────────────────
88
+
89
+ function installHooks() {
90
+ const hooksDir = path.join(GLOBAL_BASE, 'hooks');
91
+ ensureDir(hooksDir);
92
+
93
+ for (const [key, content] of Object.entries(hooks)) {
94
+ const dest = path.join(hooksDir, `${key}.js`);
95
+ try {
96
+ writeFileSafe(dest, content);
97
+ try { fs.chmodSync(dest, 0o755); } catch {}
98
+ showFileInstalled(`hooks/${key}.js`, true);
99
+ } catch (err) {
100
+ showFileInstalled(`hooks/${key}.js`, false, err.message);
101
+ }
102
+ }
103
+ }
104
+
105
+ function registerHooksInSettings() {
106
+ const settingsFile = path.join(GLOBAL_BASE, 'settings.json');
107
+
108
+ let settings = {};
109
+ try {
110
+ settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
111
+ } catch {}
112
+
113
+ if (!settings.hooks) settings.hooks = {};
114
+ if (!settings.hooks.SessionStart) settings.hooks.SessionStart = [];
115
+ if (!settings.hooks.PostToolUse) settings.hooks.PostToolUse = [];
116
+
117
+ const isHydraHook = (entry) =>
118
+ Array.isArray(entry.hooks) && entry.hooks.some(h => h.command && h.command.includes('hydra-'));
119
+
120
+ // Remove stale Hydra entries (clean reinstall)
121
+ settings.hooks.SessionStart = settings.hooks.SessionStart.filter(x => !isHydraHook(x));
122
+ settings.hooks.PostToolUse = settings.hooks.PostToolUse.filter(x => !isHydraHook(x));
123
+
124
+ settings.hooks.SessionStart.push({
125
+ hooks: [{ type: 'command', command: 'node ~/.claude/hooks/hydra-check-update.js' }]
126
+ });
127
+
128
+ settings.hooks.PostToolUse.push({
129
+ matcher: 'Write|Edit|MultiEdit',
130
+ hooks: [{ type: 'command', command: 'node ~/.claude/hooks/hydra-auto-guard.js' }]
131
+ });
132
+
133
+ let statusLineConfigured = false;
134
+ if (!settings.statusLine || (settings.statusLine.command && settings.statusLine.command.includes('hydra-'))) {
135
+ settings.statusLine = {
136
+ type: 'command',
137
+ command: 'node ~/.claude/hooks/hydra-statusline.js',
138
+ padding: 0,
139
+ };
140
+ statusLineConfigured = true;
141
+ }
142
+
143
+ writeFileSafe(settingsFile, JSON.stringify(settings, null, 2));
144
+ return { statusLineConfigured };
145
+ }
146
+
147
+ function deregisterHooks() {
148
+ const settingsFile = path.join(GLOBAL_BASE, 'settings.json');
149
+
150
+ try {
151
+ let settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
152
+
153
+ const isHydraHook = (entry) =>
154
+ Array.isArray(entry.hooks) && entry.hooks.some(h => h.command && h.command.includes('hydra-'));
155
+
156
+ if (settings.hooks?.SessionStart) {
157
+ settings.hooks.SessionStart = settings.hooks.SessionStart.filter(x => !isHydraHook(x));
158
+ if (!settings.hooks.SessionStart.length) delete settings.hooks.SessionStart;
159
+ }
160
+ if (settings.hooks?.PostToolUse) {
161
+ settings.hooks.PostToolUse = settings.hooks.PostToolUse.filter(x => !isHydraHook(x));
162
+ if (!settings.hooks.PostToolUse.length) delete settings.hooks.PostToolUse;
163
+ }
164
+ if (settings.hooks && !Object.keys(settings.hooks).length) delete settings.hooks;
165
+
166
+ if (settings.statusLine?.command?.includes('hydra-')) delete settings.statusLine;
167
+
168
+ writeFileSafe(settingsFile, JSON.stringify(settings, null, 2));
169
+ console.log(chalk.green(' \u2714 Hooks deregistered from settings.json'));
170
+ } catch (err) {
171
+ console.log(chalk.yellow(` \u26a0 Could not update settings.json: ${err.message}`));
172
+ }
173
+ }
174
+
71
175
  // ── Core install ─────────────────────────────────────────────────────────────
72
176
 
73
177
  function installToBase(base, label) {
@@ -125,10 +229,14 @@ async function runInstall(scope) {
125
229
  if (results.some((r) => !r.success)) anyFailed = true;
126
230
  }
127
231
 
232
+ // Hooks and settings are always global (once, not per-base)
233
+ installHooks();
234
+ const { statusLineConfigured } = registerHooksInSettings();
235
+
128
236
  if (!anyFailed) {
129
- showInstallComplete();
237
+ showInstallComplete(statusLineConfigured);
130
238
  } else {
131
- console.log(chalk.yellow(' Some files failed to install. Check errors above.\n'));
239
+ console.log(chalk.yellow(' \u26a0 Some files failed to install. Check errors above.\n'));
132
240
  }
133
241
  }
134
242
 
@@ -189,11 +297,28 @@ async function runUninstall({ interactive = true } = {}) {
189
297
  }
190
298
  }
191
299
 
300
+ // Remove hook .js files from ~/.claude/hooks/
301
+ for (const key of Object.keys(hooks)) {
302
+ const dest = path.join(GLOBAL_BASE, 'hooks', `${key}.js`);
303
+ if (fileExists(dest)) {
304
+ try { fs.unlinkSync(dest); console.log(chalk.green(` \u2714 Removed hooks/${key}.js`)); }
305
+ catch (err) { console.log(chalk.red(` \u2716 Failed: hooks/${key}.js \u2014 ${err.message}`)); }
306
+ }
307
+ }
308
+
309
+ // Remove cache file
310
+ const cacheFile = path.join(GLOBAL_BASE, 'cache', 'hydra-update-check.json');
311
+ if (fileExists(cacheFile)) {
312
+ try { fs.unlinkSync(cacheFile); } catch {}
313
+ }
314
+
315
+ deregisterHooks();
316
+
192
317
  console.log();
193
318
  if (failed === 0) {
194
- console.log(chalk.cyan.bold(' 🐉 All heads severed. Hydra sleeps.\n'));
319
+ console.log(chalk.cyan.bold(' \uD83D\uDC09 All heads severed. Hydra sleeps.\n'));
195
320
  } else {
196
- console.log(chalk.yellow(` ${removed} removed, ${failed} failed.\n`));
321
+ console.log(chalk.yellow(` \u26a0 ${removed} removed, ${failed} failed.\n`));
197
322
  }
198
323
  }
199
324
 
@@ -214,10 +339,19 @@ function getStatus(base) {
214
339
  installed: fileExists(e.dest),
215
340
  }));
216
341
 
342
+ const commandEntries = manifest.filter((e) => e.type === 'command').map((e) => ({
343
+ name: e.display,
344
+ installed: fileExists(e.dest),
345
+ }));
346
+
347
+ const versionEntry = manifest.find((e) => e.type === 'version');
348
+
217
349
  return {
218
350
  agents: agentEntries,
219
351
  skill: skillEntry ? fileExists(skillEntry.dest) : false,
220
352
  references: refEntries,
353
+ commands: commandEntries,
354
+ version: versionEntry ? (fileExists(versionEntry.dest) ? fs.readFileSync(versionEntry.dest, 'utf8').trim() : null) : null,
221
355
  };
222
356
  }
223
357