{"id":51846898,"url":"https://github.com/inth3shadows/runecho","last_synced_at":"2026-07-23T14:00:24.096Z","repository":{"id":337109131,"uuid":"1152370741","full_name":"inth3shadows/runecho","owner":"inth3shadows","description":"One cheap layer against AI coding mistakes — not the whole answer. Checks every agent Edit/Write against an index of your repo's real symbols, and asks before a write lands on one that doesn't exist. Catches bare calls, consts, type refs: 4 of 9 in our real-hallucination benchmark. Qualified calls out of scope. Deterministic, ~0 tokens, no LLM.","archived":false,"fork":false,"pushed_at":"2026-07-21T15:01:37.000Z","size":1808,"stargazers_count":0,"open_issues_count":11,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-21T15:16:00.132Z","etag":null,"topics":["ai-tooling","anthropic","claude-code","claude-code-plugin","codebase-analysis","developer-tools","git-hooks","go","golang","hallucination-prevention","hooks","llm","mcp","mcp-server","security","static-analysis"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/inth3shadows.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-07T19:20:52.000Z","updated_at":"2026-07-21T14:55:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/inth3shadows/runecho","commit_stats":null,"previous_names":["inth3shadows/runecho"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/inth3shadows/runecho","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inth3shadows%2Frunecho","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inth3shadows%2Frunecho/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inth3shadows%2Frunecho/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inth3shadows%2Frunecho/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inth3shadows","download_url":"https://codeload.github.com/inth3shadows/runecho/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inth3shadows%2Frunecho/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35804545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-23T02:00:06.683Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-tooling","anthropic","claude-code","claude-code-plugin","codebase-analysis","developer-tools","git-hooks","go","golang","hallucination-prevention","hooks","llm","mcp","mcp-server","security","static-analysis"],"created_at":"2026-07-23T14:00:16.378Z","updated_at":"2026-07-23T14:00:24.084Z","avatar_url":"https://github.com/inth3shadows.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RunEcho\n\n[![CI](https://github.com/inth3shadows/runecho/actions/workflows/ci.yml/badge.svg)](https://github.com/inth3shadows/runecho/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/inth3shadows/runecho)](https://github.com/inth3shadows/runecho/releases/latest)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![MCP-compatible](https://img.shields.io/badge/MCP-compatible-blueviolet.svg)](https://modelcontextprotocol.io)\n[![No LLM](https://img.shields.io/badge/No%20LLM-100%25%20local-brightgreen.svg)](#prerequisites)\n\n[![Windows](https://img.shields.io/badge/Windows-supported-blue.svg)](#quick-start)\n[![macOS](https://img.shields.io/badge/macOS-supported-blue.svg)](#quick-start)\n[![Linux](https://img.shields.io/badge/Linux-supported-blue.svg)](#quick-start)\n\nRunEcho is **one cheap layer against AI coding mistakes — not the whole answer.**\nIt checks every agent edit against an index of the symbols your repo actually\nhas, and asks before a write lands on one that doesn't exist.\n\n**The scope, stated up front.** RunEcho reads *unqualified* references — bare\ncalls, constant references, and type annotations. Measured against its own\ncorpus of real model hallucinations, that catches **4 of 9** (N=15 hand-verified\ncases mined from live session transcripts, each backed by a compiler or runtime\nerror as independent ground truth). The other 5 are qualified positions —\n`df.groupby(…)`, `tree.Root()` — which need receiver-type resolution and are out\nof scope by design. The numbers, including the misses, are in\n[bench/FINDINGS.md](bench/FINDINGS.md).\n\nThat is the honest shape of the thing: a narrow, fast, certain check that runs\nbefore the write, not a system that makes your agent correct. Run it the way you\nrun a type checker — one layer that removes one class of mistake completely,\nalongside the tests and review that catch the rest.\n\nIt is **model-free and vendor-neutral**: no LLM, no API keys, no network, and\n~0 tokens of your context window. The same code produces the same answer.\n\n## Why RunEcho Exists\n\nCoding agents are useful, but they routinely make three kinds of mistakes:\n\n- they refer to functions or types that do not exist\n- they describe structural changes inaccurately\n- they keep reasoning from stale repo state after the code has moved on\n\nRunEcho exists to give those agents a **local source of truth** they can query\nbefore they speak, edit, or commit.\n\nUse it when you want:\n\n- a deterministic answer to \"does this symbol actually exist?\"\n- a structural diff instead of a vague summary of what changed\n- a guard that catches invented helper calls before they land in your repo\n\nIf your main problem is broad semantic search or general codebase exploration,\nRunEcho is not trying to be that. Its job is narrower: **verify repo facts and\nreduce hallucinated code changes**.\n\n## How It Works\n\nRunEcho parses your source into a compact **Intermediate Representation (IR)**:\nper file: its content hash plus the functions, classes, exports, and imports it\ndeclares. The IR has a deterministic root hash, so \"did the structure change?\"\nbecomes a cheap hash comparison, and \"what changed?\" becomes a structural diff.\n\nSnapshots of that IR are stored in a single central history database. Each\nenrolled repo has a stable identity, so the oracle can answer questions about any\nof your repos and compute drift between any two snapshots.\n\nThree binaries make up the surface area:\n\n- **`runecho-ir`** — a CLI to enrol repos, index them, take snapshots, and inspect\n  diffs and churn from the terminal.\n- **`runecho-mcp`** — a stdio MCP server that exposes read-only oracle tools\n  (`structure`, `diff`, `hash`, `status`, `health`, `locate`) to an AI agent.\n  `locate` answers \"where is symbol X\" deterministically (name → file:line), so\n  an agent finds definitions without grepping or guessing.\n- **`runecho-guard`** — a guard that checks new code against the indexed IR and\n  flags references to symbols that don't exist (likely hallucinations). Runs as a\n  git pre-commit hook, or as a Claude Code `PreToolUse` hook that vets every\n  `Edit`/`Write`/`MultiEdit` before it lands.\n\n```\nsource ──▶ parser ──▶ IR (hashed) ──▶ snapshot ──▶ ~/.runecho/history.db\n                                          │\n                  AI agent ──(MCP)──▶ runecho-mcp ──▶ structure / diff / hash / ...\n                                          │\n        git commit / agent edit ──▶ runecho-guard ──▶ \"symbol X doesn't exist — block/ask\"\n```\n\n## Prerequisites\n\n- **Nothing** to run a tagged release — the [prebuilt binaries](#quick-start) are\n  self-contained (no runtime, no API keys).\n- **Go 1.24+** only if you build from source (`bash install.sh`).\n- A POSIX or Windows shell. Storage lives under `~/.runecho/` by default.\n- No external services, no API keys.\n\nLanguages parsed today: **Go, JavaScript, TypeScript, JSX, TSX, Google Apps\nScript (`.gs`), Python, and shell (`.sh`/`.bash`)**.\nExtraction is intentionally shallow and deterministic: top-level structure, not\nfull semantic analysis.\n\n## Quick Start\n\n1. Get the binaries. Either **download a prebuilt release** (no Go needed) — pick\n   your OS/arch from the [latest release](https://github.com/inth3shadows/runecho/releases/latest):\n   ```bash\n   # example: macOS arm64 — adjust the asset name for your platform.\n   # NOTE: the tag in the URL path is v-prefixed; the asset filename is not.\n   TAG=v0.6.0; NUM=0.6.0\n   curl -sSL \"https://github.com/inth3shadows/runecho/releases/download/${TAG}/runecho_${NUM}_darwin_arm64.tar.gz\" | tar -xz\n   install -m755 runecho-ir runecho-mcp runecho-guard ~/.local/bin/\n   ```\n   …or **build from source** (needs Go 1.24+), which also installs the guard hooks:\n   ```bash\n   bash install.sh\n   ```\n2. Enrol a repo and capture its current structure:\n   ```bash\n   runecho-ir repo add /path/to/your/repo\n   runecho-ir repo reindex \u003cname\u003e     # name is shown by `repo add`\n   ```\n   If the directory you want to enrol is not the directory you want parsed, set\n   a separate source root:\n   ```bash\n   runecho-ir repo add /path/to/worktree --source-root=/path/to/source\n   ```\n3. See what's enrolled and ask for drift since the last snapshot:\n   ```bash\n   runecho-ir repo list\n   runecho-ir diff --since=reindex /path/to/your/repo\n   ```\n4. Register the oracle with your AI agent so it can query directly:\n   ```bash\n   claude mcp add runecho -- ~/.local/bin/runecho-mcp\n   ```\n   For Codex, add this to `~/.codex/config.toml`:\n   ```toml\n   [mcp_servers.runecho]\n   command = \"/home/YOUR_USER/.local/bin/runecho-mcp\"  # absolute path; TOML does not expand ~\n   ```\n5. Install the edit-time guard in Claude Code — the primary integration if you\n   want RunEcho to vet assistant edits before they are written:\n   ```\n   /plugin marketplace add inth3shadows/runecho\n   /plugin install runecho-guard@runecho\n   ```\n   The plugin wires the `PreToolUse` hook; it does **not** ship the binary, so\n   step 1 still has to have happened. If the binary is missing the hook defers\n   silently rather than erroring on every edit. Uninstall with\n   `/plugin uninstall runecho-guard@runecho`.\n\n   Without plugin support, print the equivalent `~/.claude/settings.json`\n   snippet and merge it by hand:\n   ```bash\n   bash install.sh --print-hook-config\n   ```\n6. (Optional) Install the commit-time guard in a repo you've enrolled:\n   ```bash\n   bash install.sh --hook        # run from the target repo's root\n   ```\n   It blocks commits that call functions which exist nowhere in the indexed code\n   (with a \"did you mean …?\" suggestion when there's a close match). Bypass any\n   single commit with `RUNECHO_GUARD_SKIP=1 git commit …`.\n7. (Maintainers/forks only) If you cut release tags from this repo, install the\n   tag-monotonicity safety net:\n   ```bash\n   bash install.sh --hook-pre-push\n   ```\n   Rejects a `vX.Y.Z` tag push that isn't semver-greater than the highest\n   existing tag — see [issue #51](https://github.com/inth3shadows/runecho/issues/51).\n\n## Current Boundaries\n\nRunEcho is strongest when you want **deterministic structure and guardrails**,\nnot general-purpose code intelligence.\n\n- It tracks top-level symbols and imports/exports, not full type information.\n- All parsers are intentionally shallow (line-regex, not AST). Each language has\n  known gaps — see the [Parser Capability Matrix](TECHNICAL.md#parser-capability-matrix)\n  for the per-language honest accounting.\n- The guard validates **unqualified** references: bare **calls** (`foo(...)`),\n  bare **type annotations** (`x: SomeType`), and SCREAMING_SNAKE **constant**\n  references. It does **not** flag **qualified** references (`obj.method(...)`,\n  `pkg.Thing`, `x.attr`) — those would need receiver-type resolution, semantic\n  analysis RunEcho deliberately avoids. This boundary is measured, not asserted:\n  see [`bench/FINDINGS.md`](bench/FINDINGS.md), where a corpus of real\n  transcript-observed hallucinations places the guard's catch-rate by reference\n  position (the qualified positions are the deliberate gap).\n- Snapshots, diffs, and hash queries are local and deterministic. There is no\n  semantic search, embedding index, or hosted control plane here.\n- The guard runs unattended on every commit/edit with no sandboxing — see\n  [SECURITY.md](SECURITY.md) for the threat model, what's stored, and how to\n  report a vulnerability.\n\n## Project Structure\n\n| Path | Purpose |\n|---|---|\n| `cmd/runecho-ir/` | The CLI: index, snapshot, diff, log, churn, verify, truth-trail, validate-claims, repo, backup |\n| `cmd/runecho-mcp/` | The stdio MCP oracle server |\n| `cmd/runecho-guard/` | The guard: pre-commit mode + Claude Code hook mode |\n| `internal/parser/` | Per-language structure extraction (Go/JS/TS/JSX/TSX/.gs/Python/shell) |\n| `internal/ir/` | IR build, deterministic hashing, JSON storage |\n| `internal/snapshot/` | Central store: migrations, registry, diff, churn, backup |\n| `internal/mcp/` | Minimal MCP plumbing + the oracle tools |\n| `internal/guard/` | Diff parsing, symbol extraction, validation, did-you-mean |\n| `internal/claims/` | Symbol-reference extraction from prose (`validate-claims`, `truth-trail --text`) |\n| `internal/gitutil/` | Canonical git-common-dir resolution (worktree identity) |\n| `install.sh` | Builds all three binaries; `--hook` installs the pre-commit guard |\n\n## Related Documentation\n\n- [Technical Reference](TECHNICAL.md) — architecture, storage schema, the IR, the MCP tools, maintenance\n- [Usage Guide](USAGE.md) — day-to-day operations: enrolling repos, integrations, reading drift, troubleshooting\n- [Changelog](CHANGELOG.md) — notable changes per release; versioning policy\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finth3shadows%2Frunecho","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finth3shadows%2Frunecho","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finth3shadows%2Frunecho/lists"}