hydra-nano 0.1.0 → 0.3.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.
package/README.md CHANGED
@@ -1,194 +1,137 @@
1
- # Hydra
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/rahul05ranjan/hydra/main/assets/hydra-banner.svg" alt="Hydra: small local models that take the noisy work off your coding agent" width="100%">
3
+ </p>
2
4
 
3
- Small local models that a frontier coding agent (Claude Code, Codex) hands routine repo work to, so the raw output of that work never enters the frontier model's context.
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/hydra-nano"><img src="https://img.shields.io/npm/v/hydra-nano?color=7c5cff&label=npm" alt="npm version"></a>
7
+ <a href="https://huggingface.co/rahul05ranjan/hydra-nano-git"><img src="https://img.shields.io/badge/model-Hydra%20Nano%20v2-22d3ee" alt="Hydra Nano v2 on Hugging Face"></a>
8
+ <img src="https://img.shields.io/badge/runs-100%25%20local-5eead4" alt="Runs 100% local">
9
+ <img src="https://img.shields.io/badge/node-%E2%89%A518-3c873a" alt="Node 18 or later">
10
+ <a href="https://github.com/rahul05ranjan/hydra/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT license"></a>
11
+ </p>
4
12
 
5
- Hydra version 0.1 provides five specialist heads powered by the local **Hydra Nano** model family (`hydra-nano:git`, `hydra-nano:os`, `hydra-nano:test`, `hydra-nano:read`, `hydra-nano:files`), also hosted on Hugging Face at [`rahul05ranjan/hydra-nano-git`](https://huggingface.co/rahul05ranjan/hydra-nano-git):
6
- 1. **git head** (`hydra-nano:git`): inspects repository history, branch sync, diffs, blame, and status.
7
- 2. **files head** (`hydra-nano:files`): fast definition-ranked code search without cluttering context.
8
- 3. **read head** (`hydra-nano:read`): extracts symbol definitions (functions, classes, methods), line ranges, or structural definition outlines across TypeScript, JavaScript, Python, Rust, and Go without dumping whole multi-thousand-line files into context.
9
- 4. **test & logs head** (`hydra-nano:test`): runs test and compiler suites (`npm test`, `pytest`, `cargo test`, `tsc`), strips framework noise and `node_modules` stacks, and returns verbatim failure diffs and source lines with the command's exit code.
10
- 5. **os head** (`hydra-nano:os`): read-only system inspection (ports, processes, disk, system info) with strict secret-blocking guardrails.
13
+ <p align="center">
14
+ <b>Your coding agent reads every line of every test log, git diff and process list it runs.<br>Hydra reads them on your machine and hands back only the lines that matter.</b>
15
+ </p>
11
16
 
12
- ## How a call works
17
+ ---
13
18
 
14
- ```
15
- agent ── hydra ask --head git "<question>" ──────▶ git head model picks probes from a menu, code runs them
16
- agent ── hydra ask --head files "<question>" ────▶ files head model picks search terms, code searches
17
- agent ── hydra read <file> [symbol|--lines] ─────▶ read head pinpoints symbol/lines, extracts outline
18
- agent ── hydra run -- <test/build-command> ──────▶ test head runs locally, digests failures & diffs
19
- agent ◀── verbatim evidence lines ──────────────── model picks lines; the agent interprets them
20
- ```
21
-
22
- - **Read-only and safe**: The model never writes an arbitrary command. It picks from fixed menus or digests command output.
23
- - **Verbatim evidence**: Results are the command's own text lines, never a paraphrase.
24
- - **Complete lists**: Git status, history, branches, remotes, stashes, tags and worktrees retain every returned record. Explicit commit counts override the model's count (maximum 50).
25
- - **Pass-through**: Output under 800 characters is handed over whole with zero model calls.
26
- - **Preserved exit codes**: `hydra run -- <cmd>` preserves `<cmd>`'s exit code, so agents know immediately if a build or test failed.
27
-
28
- On Windows, OS inspection uses fixed read-only netstat, tasklist and PowerShell CIM commands, plus Node system/memory APIs. Process output is capped at 30 records and is not sorted by CPU usage. Failed probes are marked in the returned evidence. Code search ranks current source ahead of archived evaluation results while keeping those results searchable.
29
-
30
- ## Try it
19
+ ## Why Hydra
31
20
 
32
- Needs Node 18 or later and [llama.cpp](https://github.com/ggml-org/llama.cpp) (the default backend). [Ollama](https://ollama.com/download) is optional; select it with `HYDRA_BACKEND=ollama`.
21
+ Frontier coding agents pay for every token of tool output: a failing test suite, a long `git log`, a `ps` dump. Most of it is noise, and all of it fills the context window.
33
22
 
34
- ### Run without Ollama
23
+ Hydra puts small specialist models on your own machine between the agent and that output:
35
24
 
36
- **Hydra Nano v2 (2026-10-14):** the installer pins the Q8_0 GGUF of a full-parameter Git fine-tune at Hub revision `8129125f` (SHA-256 `6d6542c8…`). With the current code it solves **963/1,000 sealed Git tasks (96.3%; 96.17% usage-weighted)** (927/1,000 with the code validated on Kaggle) and, on 1,000-task held-out sets, Files 98.0%, Read 96.1%, Test 94.4% and OS 100% (synthetic probe outputs). See the [model card](https://huggingface.co/rahul05ranjan/hydra-nano-git) and the receipts in [`evals/results/suite/v2-6d6542c8`](evals/results/suite/v2-6d6542c8) and [`final-git-validation`](evals/results/suite/final-git-validation/SUMMARY.json). The previous v1 artifact (87.4% sealed) stays at Hub revision `ff1c723f`.
37
-
38
- `train/publish_release.py` publishes a validated release: it checks the checkpoint and GGUF against the frozen validation receipt, uploads them with the model cards in [`hub/`](hub), and pins `runtime-manifest.json` to the new revision. The GGUF is reproducible with llama.cpp `convert_hf_to_gguf.py` at commit `a05e58c` (`--outtype q8_0`). Safetensors files cannot be passed directly to `llama-server`.
39
-
40
- Start the server in one terminal:
41
-
42
- ```powershell
43
- llama-server -m C:\models\hydra-nano-git.gguf --alias hydra-nano:git --host 127.0.0.1 --port 8080 -c 8192
44
- ```
25
+ - **Less context, same answer.** A `pnpm test` run that printed ~13,807 tokens reached the agent as ~57: the failing test, the assertion diff and the source line.
26
+ - **Nothing leaves your machine.** The model runs locally on llama.cpp. Hydra's telemetry stays in `~/.hydra/ledger.jsonl`.
27
+ - **Read-only by design.** The model never writes a shell command. It picks from fixed, read-only menus; code builds and runs the command.
28
+ - **Verbatim, not paraphrased.** Hydra returns the command's own lines, so the agent sees evidence, not a summary.
45
29
 
46
- In another PowerShell terminal:
47
-
48
- ```powershell
49
- $env:HYDRA_BACKEND = 'llamacpp'
50
- $env:HYDRA_LLAMA_URL = 'http://127.0.0.1:8080'
51
- $env:HYDRA_MODEL = 'hydra-nano:git'
52
- node skills/hydra/scripts/hydra.mjs doctor
53
- node skills/hydra/scripts/hydra.mjs ask --head git "which branch am I on?"
54
- ```
55
-
56
- On macOS/Linux, set the same variables with `export HYDRA_BACKEND=llamacpp`, `export HYDRA_LLAMA_URL=http://127.0.0.1:8080` and `export HYDRA_MODEL=hydra-nano:git`.
57
-
58
- The URL is the server root, without `/v1`. `HYDRA_MODEL` must match the server alias; setting it sends all model-backed heads to that one model and does not create specialist weights. Without this override, Hydra requests its existing per-head model names; your server must serve those aliases. `hydra doctor` verifies the effective configured names. `hydra setup` with this backend prints instructions without installing or starting anything.
59
-
60
- Hydra uses llama.cpp's [schema-constrained chat API](https://github.com/ggml-org/llama.cpp/tree/master/tools/server#post-v1chatcompletions-openai-compatible-chat-completions-api), disables thinking, and limits replies to 512 tokens. The model still chooses fixed read-only probes. HTTP fixture tests and native Windows Q8 inference/bootstrap checks pass; sealed accuracy on the converted runtime is tracked separately.
61
-
62
- ### Run with Ollama
63
-
64
- Set `HYDRA_BACKEND=ollama` first (`$env:HYDRA_BACKEND = 'ollama'` in PowerShell; `export HYDRA_BACKEND=ollama` in Bash).
30
+ ## Quick start
65
31
 
66
32
  ```bash
67
- # 1. Download the small local model (1.2 GB)
68
- node skills/hydra/scripts/hydra.mjs setup
69
-
70
- # 2. Ask questions about any repo
71
- cd <any git repository>
72
- node <path>/skills/hydra/scripts/hydra.mjs ask "who changed package.json most recently and why?"
73
-
74
- # 3. Slice files, symbols, or show structural outlines
75
- node <path>/skills/hydra/scripts/hydra.mjs read src/index.ts handleRequest
76
- node <path>/skills/hydra/scripts/hydra.mjs read src/server.ts --lines 20-50
77
- node <path>/skills/hydra/scripts/hydra.mjs read src/config.py --outline
78
-
79
- # 4. Run test and build commands through hydra
80
- node <path>/skills/hydra/scripts/hydra.mjs run -- npm test
81
- node <path>/skills/hydra/scripts/hydra.mjs run -- pytest
82
-
83
- # 5. View token savings
84
- node <path>/skills/hydra/scripts/hydra.mjs stats
85
- ```
86
-
87
- ## Install as a skill
88
-
89
- Everything an agent needs is inside `skills/hydra`:
90
-
91
- ```bash
92
- npx skills add rahul05ranjan/hydra --skill hydra
33
+ npx hydra-nano
93
34
  ```
94
35
 
95
- This installs the skill instructions and bundled Node CLI. It does **not** install `llama-server`, download weights or start inference: the [skills installer](https://github.com/vercel-labs/skills) copies/links skill files, and [install lifecycle hooks](https://github.com/vercel-labs/skills/issues/1155) remain a feature request. The bundled CLI can run `read` and `search` immediately; model-backed calls need the runtime described above.
36
+ One command installs everything: a pinned llama.cpp runtime, the ~812 MB Hydra Nano model (SHA-256 checked), the Hydra skill, and the integration for each coding tool it finds.
96
37
 
97
- A complete bootstrap is provided separately:
38
+ Want the `hydra` command in your own terminal too?
98
39
 
99
40
  ```bash
100
- npx github:rahul05ranjan/hydra
41
+ npm install -g hydra-nano
42
+ hydra doctor
101
43
  ```
102
44
 
103
- It installs the skill globally for every agent it finds (Claude Code if `~/.claude` exists, Codex if `~/.codex` exists; name others with `--agent <id>`), downloads a pinned llama.cpp runtime and the approximately 812 MB Hydra Nano Git Q8 GGUF, verifies SHA-256 hashes, and writes configuration under `~/.hydra`. Node 18+ with npm is required. Windows x64/arm64 CPU, macOS x64/arm64, and Ubuntu-compatible Linux x64/arm64 runtime artifacts are supported. Windows has live verification; other platform packages have not been exercised here.
45
+ Requires Node 18+. Runtime packages for macOS, Linux and Windows on x64 and arm64; verified live on macOS and Windows. Prefer GitHub? `npx github:rahul05ranjan/hydra` installs the same thing.
104
46
 
105
- For Claude Code the bootstrap also registers two Claude Code hooks in `~/.claude/settings.json`, because an agent that merely has the skill rarely uses it. A `PreToolUse` hook turns a direct test or build run (npm/pnpm/yarn test or build, jest, vitest, pytest, unittest, `node --test`, cargo, go, gradle, mvn, dotnet, make test) back with the `hydra run --` command to use instead; prefixing a command with `HYDRA_RAW=1` lets the raw log through. A `SessionStart` hook tells each new session to ask Hydra about git history and to keep Read and Grep for source files, where Hydra does not save tokens. Other settings are kept, the original file is saved as `settings.json.before-hydra`, and an invalid settings file is left untouched. Skip the hooks with `--no-hooks`; manage them later with `hydra hooks install|remove|status`.
47
+ ## Works with your coding tools
106
48
 
107
- The first bootstrap shares the Git model across all model-backed heads; it does not download five specialist weights. Runtime downloads and configuration stay outside agent skill folders, so skill updates retain them. Hydra starts its managed server on `127.0.0.1:11435` when needed; it stays running until `hydra stop` or a reboot. Run the installed `scripts/hydra.mjs doctor` to check readiness. `HYDRA_HOME` changes the data/config directory; explicit backend, URL and model environment variables override managed defaults.
49
+ | Tool | How Hydra joins | Status |
50
+ |---|---|---|
51
+ | **Claude Code** | Skill + hooks that route test/build runs and git questions | Tested |
52
+ | **Codex** | Skill + MCP server + `PreToolUse` hook | MCP listed by Codex; trust the hook with `/hooks` |
53
+ | **OpenCode** | MCP server + plugin | MCP connects |
54
+ | **Cursor** | MCP server + `beforeShellExecution` hook | Preview |
55
+ | **Gemini CLI** | MCP server + `BeforeTool` hook | Preview |
56
+ | **Antigravity** | Skill + MCP server | Preview |
108
57
 
109
- From a local checkout, run `node skills/hydra/scripts/install.mjs`. After skill-only installation, run the installed `scripts/install.mjs --runtime-only`. The code and immutable GGUF are published. The remote bootstrap was verified on Windows on 2026-10-12, including installed-skill readiness and model hash verification; see [the receipt](evals/results/remote-bootstrap-windows.json).
58
+ Any other tool that speaks MCP can use Hydra too: point it at `hydra mcp` (stdio).
110
59
 
111
- For Kaggle evaluation, put `KAGGLE_USERNAME` and `KAGGLE_API_TOKEN` in root `.env` using [`.env.example`](.env.example). `train/kaggle/control.py` loads that file, prepares private frozen inputs, and separates upload from GPU execution. `run --approved` is only for an explicitly approved 30-minute evaluation; the kernel trains nothing, verifies source/model hashes, and rejects CPU fallback. Tokens are never embedded in the uploaded source bundle.
60
+ Hydra never overwrites your settings. Every file it edits is backed up once as `<file>.before-hydra`, only Hydra's own entries change, and `hydra agents remove` takes them out again.
112
61
 
113
- Or copy `skills/hydra` directly to your agent's skills directory:
114
- - Claude Code: `~/.claude/skills/hydra`
115
- - Antigravity: `~/.gemini/config/skills/hydra`
62
+ ## What it does
116
63
 
117
- ## Evaluations & Benchmarks
64
+ | Head | Ask it | It returns |
65
+ |---|---|---|
66
+ | **git** | "what changed in the last commit?", "who last touched `billing.js`?" | The matching commits, diff hunks or blame lines |
67
+ | **test** | `hydra run -- npm test` (pytest, cargo, go, tsc, gradle, ...) | Failing test names, assertion diffs and source locations, with the original exit code |
68
+ | **os** | "what is listening on port 3000?" | The matching ports, processes or disk lines, with secrets blocked |
69
+ | **read** | `hydra read src/server.ts handleRequest` | One symbol, a line range or an outline |
70
+ | **files** | `hydra search parseConfig` | Definition-ranked matches |
118
71
 
119
- ### Strict comparison against targeted commands
72
+ Through MCP, Hydra offers the three where it pays most: `hydra_git`, `hydra_run` and `hydra_os`.
120
73
 
121
- `npm run eval:strict` creates an isolated development repository, executes 12 tasks through concise direct commands and Hydra, and checks complete source slices, file sets, ordered commit records, failure/pass facts and exit codes. It uses no sealed `git1` inputs. The latest run passed **12/12 on both routes**, but Hydra returned **866 estimated tokens versus 460** for targeted commands (**88.3% more output**). These are character-count estimates and do not measure actual frontier-agent usage.
74
+ ## Benchmarks
122
75
 
123
- The older whole-file trial is retained as a historical result; its weak substring score is not answer accuracy. See `TRACKER.md` for the audit.
76
+ **Hydra Nano v2**: a full-parameter fine-tune of a 0.8B model, one set of weights for every head, run as a Q8_0 GGUF.
124
77
 
125
- The first actual Claude Code A/B run used `claude-opus-5-5`, with **6/6 correct in each arm**. Direct tools consumed **118,215** reported input-plus-output tokens and Hydra **112,431** (**4.89% fewer**). Trace review found that the harness denied a legitimate direct `git diff-tree` attempt; permission-denial-free pairs instead consumed **2.63% more tokens with Hydra**. This six-task single-run fixture does not establish general savings. The whitelist and workspace isolation have been corrected for future runs. The [frontier report](evals/results/frontier/2026-10-10T11-08-52-051Z/SUMMARY.md) includes the limitations and links to full traces.
78
+ | Set | Tasks | Solved |
79
+ |---|---|---|
80
+ | Git (sealed test set, never used for training) | 1,000 | **96.3%** |
81
+ | Files (held out) | 1,000 | **98.0%** |
82
+ | Read (held out) | 1,000 | **96.1%** |
83
+ | Test logs (second held-out set) | 1,000 | **97.5%** |
84
+ | OS (held out, synthetic probe outputs) | 1,000 | **100%** |
85
+ | Test-log benchmark across 8 frameworks | 20 | **19/20**, 47% fewer tokens |
126
86
 
127
- `npm run eval:frontier:prepare` prepares a six-task Claude Code A/B trial without model calls. `npm run eval:frontier` launches 12 fresh sessions after user approval, with direct tools versus explicit Hydra delegation. It records exact structured-answer checks, actual reported input/output tokens including cached input, cost, tool errors, tool calls, turns and elapsed time. Sessions use isolated copies of the fixture, the same configured frontier model, a frozen Hydra runtime, a $0.50 budget setting per session and a 10-minute overall time limit. This measures repository-inspection tasks in a controlled fixture; spontaneous skill adoption and full software-development workloads require further trials.
87
+ Receipts: [model card](https://huggingface.co/rahul05ranjan/hydra-nano-git) and [`evals/results`](https://github.com/rahul05ranjan/hydra/tree/main/evals/results).
128
88
 
129
- `node evals/trial/analyze_frontier.mjs <run-directory>` independently checks saved answers against gold and reports overall and permission-denial-free pairs without new model calls. Fixture workspaces live under `~/.hydra/trials/frontier`, outside this project.
89
+ <!-- usage-stats:begin (written by evals/usage/readme_stats.mjs) -->
90
+ **In real use.** Since 2026-10-17, Hydra has handled **118 calls** in **9 coding sessions** across **3 projects** on the maintainer's machine. Of **~375,638 tokens** of command output, **~18,781** reached the agent: **95% kept out of context**.
130
91
 
131
- ### Repeated real-source and natural-adoption trial
92
+ | Work | Calls | Output read locally | Reached the agent | Kept out |
93
+ |---|---|---|---|---|
94
+ | Test and build runs | 112 | ~374,873 | ~18,199 | **95%** |
95
+ | File slices | 1 | ~508 | ~283 | **44%** |
96
+ | Git questions | 5 | ~257 | ~299 | **-16%** |
132
97
 
133
- `npm run eval:real:prepare` freezes four function-extraction tasks from Vasuki and Dhruv CLI, independent parser gold, source hashes and the production skill. The 69-file source corpus has 9,375 lines. Three fresh sessions per task compare native tools, Hydra available without a usage instruction, and explicit Hydra delegation: **36 sessions** with a **20-minute** deadline and **$18** total configured API-cost-equivalent budget. This tests source inspection and complete function extraction.
98
+ <sub>From Hydra's local ledger; tokens are estimates (characters / 4). Updated 2026-10-20.</sub>
99
+ <!-- usage-stats:end -->
134
100
 
135
- After explicit run approval, use `npm run eval:real -- --prepared <directory>`. The runner checks startup skill discovery, unchanged sources and models, and permission errors; it preserves every factual failure. `node evals/trial/analyze_real_repo.mjs <directory>` audits saved traces without model calls. See the [predeclared protocol](evals/trial/REAL_REPO_PROTOCOL.md) for arm ordering, exact correctness and exploratory task-cluster intervals.
101
+ **Where Hydra does not help, measured.** In a controlled trial of 36 Claude Code sessions extracting functions from real source code, forcing that work through Hydra used **72% more tokens** than the agent's own tools. So Hydra leaves source reading and search to the agent, and routes only the noisy work: test and build logs, git history, system inspection. Full method and numbers in [evaluations](https://github.com/rahul05ranjan/hydra/blob/main/docs/evaluations.md).
136
102
 
137
- The approved run completed **36/36 sessions**, with **12/12 correct in every arm** and no protocol violations. Native tools used **387,115** total reported tokens, skill availability **391,296 (+1.08%)**, and explicit Hydra delegation **667,303 (+72.38%)**. Claude chose Hydra in **0/12** available sessions and **12/12** forced sessions. Runtime was **513.9 seconds** and reported API-cost equivalent **$2.7095**. Token savings were absent on these four tasks. Trace audit found Python symbol slices that included unrelated code or omitted part of the function; native fallback restored complete answers. See the [full report](evals/results/real-repo/2026-10-10T11-57-49-798Z/SUMMARY.md) and [evidence audit](evals/results/real-repo/2026-10-10T11-57-49-798Z/AUDIT.md).
103
+ ## Commands
138
104
 
139
- ### 1. `evals/git1` (1000 tasks, sealed git test set)
140
-
141
- 50 generated repositories, 20 kinds of question, 10 phrasings each. Verified by git gold facts and usage weighting.
142
-
143
- - **Baseline (`qwen3.5:0.8b`)**: 70% solved (69% weighted by real usage), plan accuracy 74%, 10 errors.
144
- - **Improved with JSON prompt grounding**: **77% solved (76% weighted)**, plan accuracy **80%**, **0 errors**, runtime dropped from 21.2 min to **3.5 min**.
145
- - `staged_files`: 0% ➔ 100% (+100 points)
146
- - `message_search`: 4% ➔ 72% (+68 points)
147
- - `commit_files`: 46% ➔ 72% (+26 points)
148
-
149
- Full results in `evals/results/git1.qwen3.5-0.8b.json`.
150
-
151
- ### 2. `evals/test_logs` (20 cross-language tasks)
152
-
153
- Benchmarks failure extraction and noise reduction across Vitest, Jest, Pytest, Cargo, TSC, Go, node:test, and Mocha.
154
-
155
- - **Solved**: **100% (20/20)**
156
- - **Test Name Recall**: **100%**
157
- - **File / Line Location Recall**: **100%**
158
- - **Assertion Diff Recall**: **100%**
159
- - **Cleanliness**: **100%** (zero framework or `node_modules` stack frame pollution)
160
- - **Token Savings**: **49.6% net token reduction** overall, and **96.4% to 96.7%** on verbose test suites.
161
- - **Runtime**: **3.2s** across all 20 tasks.
105
+ ```bash
106
+ hydra ask "which branch am I on and what changed?" # git, files or os, routed by the question
107
+ hydra run -- pytest -q # a test or build run, digested
108
+ hydra os "what is using port 8080?" # read-only system inspection
109
+ hydra read src/app.py create_app # one symbol, a line range or an outline
110
+ hydra smell src/ # detect Refactoring.Guru code smells (or --diff / --staged)
111
+ hydra refactor src/app.py process_order # actionable step-by-step refactoring recipe
112
+ hydra design "need flexible algorithms at runtime" # GoF design pattern advisor & architecture guide
113
+ hydra stats # tokens kept out of context
114
+ hydra improve --since 2026-10-17 # what the local telemetry says to improve
115
+ hydra agents status # Hydra in each coding tool
116
+ hydra doctor # is the local model ready?
117
+ ```
162
118
 
163
- Full results in `evals/results/test_logs.qwen3.5-0.8b.json`.
119
+ Need the raw log for one run? Prefix it with `HYDRA_RAW=1` and the hook lets it through.
164
120
 
165
- ### 3. `evals/read` (20 cross-language tasks)
121
+ ## Privacy and control
166
122
 
167
- Benchmarks targeted symbol extraction, line range slicing, and file outlines across TypeScript, JavaScript, Python, Rust, and Go to address the #1 token sink (75.5% of tool tokens).
123
+ - **Local only.** The model, the runtime and the telemetry live in `~/.hydra`. Nothing is sent anywhere.
124
+ - **Turn telemetry off** with `HYDRA_TELEMETRY=0`.
125
+ - **Skip parts of the install** with `--no-agents` (no other tools), `--no-hooks` (no hooks) or `--runtime-only` (no skill).
126
+ - **Uninstall cleanly.** `hydra agents remove` and `hydra hooks remove` undo every integration and restore your settings; `hydra stop` stops the local server; deleting `~/.hydra` removes the runtime, the model and the telemetry.
168
127
 
169
- - **Solved**: **100% (20/20)**
170
- - **Target Line Recall**: **100%**
171
- - **Cleanliness**: **100%** (zero unrelated function/code leak)
172
- - **Token Savings**: **48.1% net token reduction** overall, and **77% to 92%** on targeted line and symbol slices.
173
- - **Runtime**: **0.01s** (instantaneous local extraction).
128
+ ## Learn more
174
129
 
175
- Full results in `evals/results/read.json`.
130
+ - [How Hydra works](https://github.com/rahul05ranjan/hydra/blob/main/docs/how-it-works.md): heads, backends (llama.cpp or Ollama), telemetry, every install path and the code layout.
131
+ - [Evaluations and trials](https://github.com/rahul05ranjan/hydra/blob/main/docs/evaluations.md): how each number above was measured.
132
+ - [What real use teaches](https://github.com/rahul05ranjan/hydra/blob/main/IMPROVEMENTS.md): the open and fixed findings from Hydra's own telemetry.
133
+ - [Hydra Nano on Hugging Face](https://huggingface.co/rahul05ranjan/hydra-nano-git).
176
134
 
177
- ## Layout
135
+ ## License
178
136
 
179
- - `skills/hydra/SKILL.md`: tells an agent when to delegate and how to read the result.
180
- - `skills/hydra/scripts/hydra.mjs`: the CLI.
181
- - `skills/hydra/scripts/lib/`:
182
- - `runtime.mjs`: selectable Ollama/llama.cpp API client and per-head model configuration.
183
- - `route.mjs`: route questions between heads.
184
- - `git.mjs`: git head probes and plan step.
185
- - `files.mjs`: search and walk head.
186
- - `read.mjs`: file slice and symbol reader head.
187
- - `test_logs.mjs`: test runner and build log reader head.
188
- - `answer.mjs`: verbatim line selection and lead generation.
189
- - `ollama.mjs`: compatibility exports for existing evaluation callers.
190
- - `ledger.mjs`: local token accounting ledger.
191
- - `test/`: unit test suite (`npm test`).
192
- - `evals/git1/`: 1000-task sealed test set for git head.
193
- - `evals/test_logs/`: 20-task cross-language benchmark for test and build logs.
194
- - `evals/read/`: 20-task cross-language benchmark for file slice reading.
137
+ MIT. See [LICENSE](https://github.com/rahul05ranjan/hydra/blob/main/LICENSE).
package/package.json CHANGED
@@ -1,16 +1,26 @@
1
1
  {
2
2
  "name": "hydra-nano",
3
- "version": "0.1.0",
4
- "description": "Small local models that Claude Code and Codex hand routine read-only repo work to: git questions, test and build digests, file slicing, code search and OS inspection",
3
+ "version": "0.3.0",
4
+ "description": "Small local models that take the noisy work off your coding agent: git history, test and build digests and OS inspection run on your machine, and only the lines that matter reach Claude Code, Codex, Cursor, OpenCode, Gemini CLI or Antigravity. Skill, MCP server and hooks.",
5
5
  "keywords": [
6
6
  "claude-code",
7
7
  "codex",
8
+ "cursor",
9
+ "opencode",
10
+ "gemini-cli",
11
+ "antigravity",
12
+ "mcp",
13
+ "mcp-server",
8
14
  "agent-skill",
15
+ "ai-agents",
16
+ "coding-agent",
9
17
  "local-llm",
10
18
  "llama.cpp",
19
+ "token-saving",
20
+ "context-window",
11
21
  "git",
12
22
  "test-runner",
13
- "token-saving"
23
+ "developer-tools"
14
24
  ],
15
25
  "license": "MIT",
16
26
  "author": "rahul05ranjan",
@@ -42,7 +52,8 @@
42
52
  "eval:frontier": "node evals/trial/frontier_trial.mjs --run",
43
53
  "eval:real:prepare": "node evals/trial/real_repo_trial.mjs",
44
54
  "eval:real": "node evals/trial/real_repo_trial.mjs --run",
45
- "dashboard": "node dashboard/server.mjs"
55
+ "dashboard": "node dashboard/server.mjs",
56
+ "stats:readme": "node evals/usage/readme_stats.mjs"
46
57
  },
47
58
  "engines": {
48
59
  "node": ">=18"
@@ -1,41 +1,35 @@
1
1
  ---
2
2
  name: hydra
3
- description: Hand a read-only git question (repo state, history, blame), a where-is-it code search, targeted file slicing instead of whole-file reads, test/build failure digests, or system/OS inspections (ports, processes, disk) to hydra locally. Use before running git status, log, diff, show, blame, broad searches, whole file reads, ps/lsof dumps, or test/build commands where noisy output would flood your context.
3
+ description: Run test and build commands, git history/diff/blame questions, and machine inspections (ports, processes, disk) through hydra, a local model that returns only the lines that matter. Use before running npm test, pytest, cargo test, tsc or a build, before reading git log, diff, show or blame output, and before ps, lsof or df dumps.
4
4
  ---
5
5
 
6
6
  # Hydra
7
7
 
8
- `hydra` runs read-only commands for repo questions, file slicing, test/build runs, and system inspections on a small local model and prints the lines that answer it. The raw output stays on this machine instead of entering your context.
8
+ `hydra` runs a noisy read-only command on this machine and prints only the lines that answer the question; the raw output stays out of your context. It pays off where output is long and mostly noise: test and build logs, git history and diffs, process and port listings.
9
9
 
10
10
  ## Call it
11
11
 
12
- From the repository the question is about, naming the head that fits:
12
+ From the repository the question is about:
13
13
 
14
14
  ```
15
+ node scripts/hydra.mjs run -- <test or build command...>
15
16
  node scripts/hydra.mjs ask --head git "<question>"
16
- node scripts/hydra.mjs ask --head files "<question>"
17
- node scripts/hydra.mjs ask --head read "<question>"
18
- node scripts/hydra.mjs ask --head test "<question>"
19
- node scripts/hydra.mjs ask --head os "<question>"
20
- node scripts/hydra.mjs search <term...>
21
- node scripts/hydra.mjs read <file> [symbol|--lines <start-end>|--outline]
22
- node scripts/hydra.mjs run -- <command...>
23
17
  node scripts/hydra.mjs os [question...]
24
18
  ```
25
19
 
26
- `scripts/` is in this skill's directory. Ask one full question per call and name the file, branch, commit or author when you know it: the model may only use a path, revision or name that appears in your question.
27
- - For finding definitions & files: use `hydra search <term>` to get definition-ranked matches without noise or raw grep dumps.
28
- - For reading code: use `hydra read <file> [symbol|--lines]` instead of reading multi-thousand-line files. It returns the exact symbol or slice, or a structural outline of symbols.
29
- - For tests and builds: run `hydra run -- <command...>` to execute the command locally and get the failure evidence with its exit code.
30
- - For system and environment: use `hydra os` or `--head os` to inspect listening ports, top processes, disk space, and system info without dumping 500 lines of terminal output into context.
20
+ `scripts/` is in this skill's directory.
21
+
22
+ - **Tests and builds:** `run --` executes the command and returns the failing tests, assertion diffs and source locations with the exit code, or a short pass summary. A run you already cut to a few lines yourself (`| tail -n 20`) gains nothing from Hydra.
23
+ - **Git:** ask one full question per call and name the file, branch, commit or author when you know it; the model may only use a path, revision or name that appears in your question. A short check such as `git status --short` is cheaper to run yourself.
24
+ - **Machine:** ports, processes, disk, memory, system info and environment variable names, with secrets withheld.
25
+
26
+ Read and search source files with your own tools: a measured trial found routing that work through Hydra cost 72% more tokens. Hydra also has `search`, `read`, `smell`, `refactor` and `design` commands (`node scripts/hydra.mjs` with no arguments lists them) for when the user asks for them.
31
27
 
32
28
  ## What it answers
33
29
 
30
+ - **test**: test and build output (`npm test`, `pytest`, `cargo test`, `go test`, `tsc` and others). On failure, the failing test name, assertion diff and the user's own file:line, with node_modules and framework frames dropped.
34
31
  - **git**: current branch and sync state, uncommitted and staged changes, commit history, what this branch adds over a base branch, one commit's patch, blame, branches, worktrees, remotes, stashes, tags.
35
- - **files**: where a name is defined or used, and which files are named like it.
36
- - **read**: extracts symbol definitions (functions, classes, methods), line ranges (`--lines 10-50`), or structural definition outlines across TypeScript, JavaScript, Python, Rust, and Go without dumping whole files into context.
37
- - **test**: runs and parses test and build outputs (`npm test`, `pytest`, `cargo test`, `tsc`). If tests fail, extracts the failing test name, assertion diff, and exact user file:line location, stripping node_modules and framework traces.
38
- - **os**: inspects listening ports (`lsof`), running processes / CPU consumers (`ps`), disk space (`df -h`), and system info (`uptime`, `uname`) while strictly guarding against printing secrets.
32
+ - **os**: listening ports, running processes and CPU consumers, disk space, memory, system info, environment variable names, never their values.
39
33
 
40
34
  Changes to the repository, and questions that need reasoning about what code does, stay with you.
41
35
 
@@ -1,22 +1,54 @@
1
1
  #!/usr/bin/env node
2
- // Claude Code PreToolUse hook (Bash): a test or build run goes through `hydra run --`, whose digest
3
- // keeps failing test names, assertion diffs and source locations and drops the rest of the log.
4
- // Prefix a command with HYDRA_RAW=1 when the raw log is really needed.
2
+ // Shell-command hook: a test or build run goes through `hydra run --` (or the hydra_run MCP tool),
3
+ // whose digest keeps failing test names, assertion diffs and source locations and drops the rest.
4
+ // A run already cut to a few lines by its own pipeline (| tail -n 15, | grep -c) passes: Hydra would
5
+ // save little and a retry costs more. Prefix a command with HYDRA_RAW=1 when the raw log is really needed.
6
+ // --format picks the tool's hook protocol:
7
+ // claude, codex PreToolUse; command at tool_input.command; deny via hookSpecificOutput.
8
+ // gemini BeforeTool on run_shell_command; deny via {"decision": "deny", "reason"}.
9
+ // cursor beforeShellExecution; command at command; must always answer with a permission.
10
+ // Each decision goes to the local ledger with the hook's own time, for `hydra improve`; a command
11
+ // that simply passes is recorded without its text.
5
12
  import path from 'node:path';
6
13
  import { fileURLToPath } from 'node:url';
7
- import { testRun } from '../lib/claude_hooks.mjs';
14
+ import { rawBypass, testRun, trimmedRun } from '../lib/claude_hooks.mjs';
15
+ import { record } from '../lib/ledger.mjs';
8
16
 
9
17
  const hydra = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'hydra.mjs');
18
+ const flag = process.argv.indexOf('--format');
19
+ const format = flag >= 0 ? process.argv[flag + 1] : 'claude';
20
+
21
+ const answers = {
22
+ claude: { pass: null, deny: reason => ({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: reason } }) },
23
+ gemini: { pass: { decision: 'allow' }, deny: reason => ({ decision: 'deny', reason }) },
24
+ cursor: { pass: { permission: 'allow' }, deny: reason => ({ permission: 'deny', agent_message: reason,
25
+ user_message: 'Hydra sent this test/build run through hydra run to keep the full log out of context.' }) },
26
+ };
27
+ answers.codex = answers.claude;
28
+ const answer = answers[format] ?? answers.claude;
29
+
10
30
  let input = '';
11
31
  process.stdin.on('data', chunk => { input += chunk; }).on('end', () => {
12
- let command = '';
13
- try { command = JSON.parse(input).tool_input?.command ?? ''; } catch { return; }
32
+ let parsed;
33
+ try { parsed = JSON.parse(input) ?? {}; } catch {
34
+ if (answer.pass) process.stdout.write(JSON.stringify(answer.pass));
35
+ return;
36
+ }
37
+ const command = String((format === 'cursor' ? parsed.command : parsed.tool_input?.command) ?? '');
38
+ const session = parsed.session_id ?? parsed.conversation_id;
39
+ const event = (decision, withCommand = true) => ({ ts: new Date().toISOString(), kind: 'hook', hook: 'route-tests',
40
+ ...(format === 'claude' ? {} : { agent: format }), decision, ...(withCommand ? { command: command.slice(0, 300) } : {}),
41
+ ...(session ? { session } : {}), hookMs: Math.round(process.uptime() * 1000) });
14
42
  const run = testRun(command);
15
- if (!run) return;
16
- process.stdout.write(JSON.stringify({ hookSpecificOutput: {
17
- hookEventName: 'PreToolUse', permissionDecision: 'deny',
18
- permissionDecisionReason: `Test/build runs go through Hydra so the full log stays out of context. Run it as:\n` +
19
- ` node "${hydra}" run -- ${run}\n(keep any cd or env prefix before it). Hydra returns the failing tests, ` +
20
- `assertion diffs and source locations verbatim, or a short pass summary. If you truly need the raw log, ` +
21
- `prefix the original command with HYDRA_RAW=1.` } }));
43
+ if (!run) {
44
+ record(rawBypass(command) ? event('raw') : trimmedRun(command) ? event('trimmed') : event('pass', false));
45
+ if (answer.pass) process.stdout.write(JSON.stringify(answer.pass));
46
+ return;
47
+ }
48
+ record({ ...event('deny'), run });
49
+ process.stdout.write(JSON.stringify(answer.deny(`Test/build runs go through Hydra so the full log stays out of context. Run it as:\n` +
50
+ ` node "${hydra}" run -- ${run}\n${format === 'claude' ? '' : 'or call the hydra_run tool with that command. '}` +
51
+ `(Keep any cd or env prefix before it.) Hydra returns the failing tests, assertion diffs and source locations ` +
52
+ `verbatim, or a short pass summary. A run you cut to a few lines yourself (| tail -n 40 or less, or | grep ... | head -40) also passes. ` +
53
+ `If you truly need the raw log, prefix the original command with HYDRA_RAW=1.`)));
22
54
  });
@@ -1,13 +1,29 @@
1
1
  #!/usr/bin/env node
2
- // Claude Code SessionStart hook: tells the agent where Hydra pays off, so it uses it without being asked.
2
+ // Session-start hook: tells the agent where Hydra pays off, so it uses it without being asked.
3
+ // --format claude or codex answers with hookSpecificOutput; cursor with additional_context.
4
+ // The session start goes to the local ledger, so `hydra improve` can tell how many sessions used Hydra.
3
5
  import path from 'node:path';
4
6
  import { fileURLToPath } from 'node:url';
7
+ import { record } from '../lib/ledger.mjs';
5
8
 
6
9
  const hydra = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'hydra.mjs');
7
- process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: 'SessionStart', additionalContext:
8
- `Hydra is installed: it runs noisy read-only commands on a small local model and returns only the lines that matter.\n` +
9
- `- For git history, diff, blame or "what changed" questions, first run: node "${hydra}" ask --head git "<question>" ` +
10
+ const flag = process.argv.indexOf('--format');
11
+ const format = flag >= 0 ? process.argv[flag + 1] : 'claude';
12
+ const mcp = format === 'claude' ? '' : ' (or the hydra_git / hydra_run MCP tools)';
13
+ const guide = `Hydra is installed: it runs noisy read-only commands on a small local model and returns only the lines that matter.\n` +
14
+ `- For git history, diff, blame or "what changed" questions, first run: node "${hydra}" ask --head git "<question>"${mcp} ` +
10
15
  `from the repository, instead of reading git log, git diff or git show output yourself. Use plain git for writes ` +
11
16
  `and for short checks such as git status --short.\n` +
12
17
  `- A hook sends test and build runs through: node "${hydra}" run -- <command>\n` +
13
- `- Keep using Read and Grep for source files; Hydra does not save tokens there.` } }));
18
+ `- Keep using your own file reading and search for source files; Hydra does not save tokens there.`;
19
+
20
+ let input = '';
21
+ process.stdin.on('data', chunk => { input += chunk; }).on('end', () => {
22
+ let start = {};
23
+ try { start = JSON.parse(input) ?? {}; } catch { /* The tool always sends JSON; record what there is. */ }
24
+ const session = start.session_id ?? start.conversation_id;
25
+ record({ ts: new Date().toISOString(), kind: 'session', ...(format === 'claude' ? {} : { agent: format }),
26
+ ...(session ? { session } : {}), ...(start.source ? { source: start.source } : {}) });
27
+ process.stdout.write(JSON.stringify(format === 'cursor' ? { additional_context: guide }
28
+ : { hookSpecificOutput: { hookEventName: 'SessionStart', additionalContext: guide } }));
29
+ });