AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Runar Forge

mcp-crlome-runar-forge · by crlome

Persistent, semantically-searchable memory and a symbol-level code graph for AI coding agents. One static Rust binary — SQLite or PostgreSQL, MCP-compatible.

No reviews yet
0 installs
20 views
0.0% view→install

Install

$ agentstack add mcp-crlome-runar-forge

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-crlome-runar-forge)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Runar Forge? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

RunarForge — Huginn & Muninn

[](https://github.com/crlome/runar-forge/releases/latest) [](https://www.npmjs.com/package/@runar-forge/cli) [](https://github.com/crlome/runar-forge/actions/workflows/ci.yml) [](LICENSE)

> Persistent, semantically-searchable memory for AI coding tools. > One static Rust binary. SQLite or PostgreSQL. MCP-compatible.

runar-forge.com

runar is a single-binary CLI that gives Claude Code, VS Code, OpenCode, Codex, Cursor, Windsurf, Trae, Gemini CLI, Continue.dev, Zed, Goose, Kimi — any MCP-aware AI tool — a memory that survives session closes, travels across tools, and understands codebase structure.

Named after Odin's two ravens from Norse mythology:

  • Huginn ("thought") — the scout: crawls codebases, builds

dependency graphs, scores file importance, extracts patterns and tech debt.

  • Muninn ("memory") — the librarian: stores, retrieves,

ranks, and graduates entries through tiered memory layers (working → episodic → semantic → archival).

A third subsystem, the Curator, answers natural-language questions by assembling context from memory.


Features

  • One static binary. No Node, no Python, no runtime deps.

~16 MB on macOS arm64; ~70 MB with bundled local embeddings.

  • Two storage backends.
  • SQLite (bundled via rusqlite bundled-full + FTS5) — zero

setup, single-machine, default for solo use.

  • PostgreSQL 16+ with pgvector — multi-user, full semantic

search, shared team memory.

  • Hybrid local + remote sync. Outbox + reconcile pattern with

LWW + verified tiebreaker. Run sqlite or local-pg as a fast primary and a remote PG as the team store; runar sync push|pull drains the outbox and pulls deltas.

  • MCP server. runar mcp-muninn speaks the Model Context

Protocol over stdio. 28 tools exposed under muninn_* (13), huginn_* (10), curator_* (5).

  • Symbol-level code graph. runar crawl extracts definitions, call

sites and per-function complexity into a dedicated codegraph.db (Rust, TypeScript/JS, Python, Go), then resolves calls into edges through a confidence-ranked tier chain. Query it with runar graph search|symbol|trace|status or the huginn_search_graph / huginn_symbol / huginn_trace MCP tools. An edge is evidence or it is absent: unmatched calls are counted, never attached to a plausible-looking definition.

  • A code view for humans. runar graph serve opens a browser on

localhost; runar graph export writes the same interface to a single HTML file that works offline. No bundler, no CDN, no vendored JavaScript, and no new dependency — see [Code view](#code-view).

  • A graph that says when it is stale, and can fix itself. Every index

records the commit and working-tree state it read, so runar doctor and the session code map report when the graph has fallen behind instead of answering confidently from an old picture. runar graph refresh re-indexes the graph alone in well under a second — only changed files are re-parsed — and the opt-in hooks keep it current on their own. See [Keeping the graph current](#keeping-the-graph-current).

  • Tiered memory. Entries graduate through 4 layers based on age,

citation count, verification, and confidence; runar gc enforces retention.

  • Auto-capture. Optional Claude Code hooks queue PostToolUse

payloads, then summarize them at session end (Claude Haiku if ANTHROPIC_API_KEY is set, otherwise heuristic fallback).

  • Health checks. runar doctor runs 21 read-only probes — storage,

schema, migrations, FTS parity, sync state, hook log, code-graph coverage and freshness, and the auto-refresh record. A degraded subsystem is reported as skipped with the reason and the fix, never as a silent pass.

  • Self-update. runar update --check|--rollback fetches signed

release manifests; previous binary preserved at runar.previous.


Install

A. Build from source

git clone https://github.com/crlome/runar-forge.git
cd runar-forge
cargo build --release -p runar-muninn
# Binary lands at target/release/runar
sudo mv target/release/runar /usr/local/bin/runar

With bundled local embeddings (no external embedding API required):

cargo build --release -p runar-muninn --features local-embeddings

B. Pre-built binary

Pick the matching tarball from GitHub Releases:

| Target | Asset | |---------------------------------|------------------------------------------------| | Linux x8664 | runar-x86_64-unknown-linux-gnu.tar.gz | | Linux aarch64 | runar-aarch64-unknown-linux-gnu.tar.gz | | macOS arm64 (Apple Silicon) | runar-aarch64-apple-darwin.tar.gz | | macOS x8664 (Intel) | runar-x86_64-apple-darwin.tar.gz | | Windows x86_64 | runar-x86_64-pc-windows-msvc.zip |

Each tarball/zip is paired with a .sha256 checksum.

C. npm

npm install -g @runar-forge/cli

@runar-forge/cli is a tiny launcher; npm pulls the binary as the matching per-platform optional dependency (@runar-forge/cli--). No install scripts, no install-time network — so it installs cleanly even with ignore-scripts=true.


Quick start

runar init                          # creates ~/.runar-forge/.env
runar config wizard                 # interactive storage + DB setup
runar doctor                        # 21 read-only health checks
runar setup claude-code -p my-proj  # wire MCP tools into Claude Code

Optional auto-capture (PostToolUse queue + SessionEnd summarizer):

runar setup claude-code -p my-proj --with-auto-capture

Other editors — same mcp-muninn server, different config file. vscode, opencode, and codex auto-write their config; cursor and windsurf print it for manual paste. Hooks (context injection, auto-capture) are Claude Code only — the rest are MCP tools only.

runar setup vscode      # writes .vscode/mcp.json   (servers.muninn)
runar setup opencode    # writes opencode.json      (mcp.muninn, type=local)
runar setup codex       # writes ~/.codex/config.toml ([mcp_servers.muninn])
runar setup cursor      # prints MCP config for manual paste
runar setup windsurf    # prints MCP config for manual paste

Code view

Every other surface on the graph targets an agent. This one targets you.

runar graph serve                 # opens a browser on 127.0.0.1
runar graph export -p myproject   # one self-contained HTML file

Two altitudes of one tool, with a toggle between them. Selecting a symbol never changes altitude — clicking a tower shows you its card where it stands.

City

Directories are blocks, symbols are buildings, height is cyclomatic complexity, so the thing most likely to hurt you is the tallest thing on screen. Selecting one arcs its calls across the city; the dash pattern is the resolver's own confidence tier, so a weak guess looks like one.

Only symbols that have complexity get a building — on a large codebase most symbols are fields and type declarations, and drawing them buries the towers that matter. The header always states what was drawn against what exists.

Symbol

Search on the left, the neighbourhood in the middle, the definition on the right. Never the whole graph: one symbol's callers and callees, and a click moves you to any of them.

Note the card shows call sites and distinct callers separately. They are different questions, and on real code they differ by a factor of three or more — a function called ten times from one test is not a hub.

Projects

One codegraph.db holds every project you have crawled. Served, the switcher reads it live.

> Screenshots are taken against generated fixtures, not real code — > see tools/fixtures/demo_graph.py.

On serve and safety. It binds 127.0.0.1 only, puts a 128-bit random token in the URL path so a page you visit cannot reach it by guessing the port, validates the Host header against DNS rebinding, answers GET only, and opens the store read-only. No CORS headers are sent.


Keeping the graph current

The graph is built by runar crawl, so between crawls it describes the code as it was, not as it is. That matters more than ordinary staleness: graph search|symbol|trace and the search-hint hook answer confidently from the old picture, and a stale symbol looks exactly like a current one.

Every index now records two things about the tree it read — the commit at HEAD, and a signature over git status --porcelain with each listed path's size and mtime. Any reader can compare them without opening the graph writable.

runar graph refresh --project myproject --check   # 0 current, 2 stale, 3 cannot tell
runar graph refresh --project myproject           # re-index; ~0.3s on a 160-file project

runar doctor reports the same verdict, and the session code map adds one STALE: line when the graph is genuinely behind. Nothing is claimed when it cannot be known: a project without git, or a graph built before this feature existed, reports "cannot judge" rather than a false all-clear.

Automatic refresh (opt-in)

runar setup claude-code --project myproject --with-graph-autorefresh

Installs two triggers — after a file write, and at session start. Neither does any work in the hook itself: it reads one timestamp file and, if a refresh is due, starts a detached child, so the tool call that triggered it never waits.

The child refuses more often than it runs, and deliberately so. It will not build a graph that does not exist, will not touch a project without git, and skips entirely when the recorded signals have not changed — it fires on change, never on "the working tree is dirty", because a repository that stays dirty all afternoon is not getting staler. After each pass the next one is held off for twenty times what that one cost, floored at 30s and capped at 10 minutes.

Every decision — including every refusal — is recorded, because a background task that quietly does nothing is indistinguishable from one that is broken:

$ runar doctor
✔ graph auto-refresh  myproject: done (4s ago, 379ms)
     3 fire(s): 1 started a refresh, 2 debounced; 100% of runs had work;
     1 refresh(es), 373ms median / 373ms p95

Raw rows land in ~/.runar-forge/graph-refresh-stats.tsv. Remove the hooks again with --no-graph-autorefresh.

> Enable it per project as you return to work on each one. It only helps where > you are actively editing, and it requires that project to have been crawled > at least once — runar graph refresh is maintenance, never construction.


CLI reference

| Command | Purpose | |------------------------------|---------------------------------------------------------------------------------| | runar mcp-muninn | Start MCP server over stdio (called by AI tools, not humans). | | runar init | Create ~/.runar-forge/.env. --interactive runs the wizard. | | runar config | Manage ~/.runar-forge/.env: path, show, get, set, unset, wizard. | | runar doctor | 21 read-only health checks. --db, --json, --quiet, --timeout-ms. | | runar setup | Wire MCP into claude-code/vscode/opencode/codex/cursor/windsurf. --with-auto-capture, --with-search-hints, --with-graph-autorefresh, --all-projects, --configure. | | runar update | Self-update binary via release manifest. --check, --channel, --rollback. | | runar search | CLI-side semantic search; --limit. | | runar save | Save a memory entry from the shell. --project, --type, --tags, --topic-key. | | runar stats | Memory system statistics (entries by type, sessions, layers). | | runar crawl [] | Crawl a project. --project, --mode auto|full|incremental. Builds the symbol graph by default; --no-deep skips it. | | runar graph search | Full-text search over symbol names. --project, --label, --limit. | | runar graph symbol | Definition site, signature, metrics and one-hop callers/callees. --project. | | runar graph trace | Walk the call graph. --direction callers|callees, --depth (max 5), --limit. | | runar graph status | Symbol-graph coverage: files indexed, skipped by language, symbols, edges, unresolved calls. | | runar graph serve | Open the code view on localhost. --project, --port (0 = pick one), --no-open. | | runar graph export | Write the code view to one self-contained HTML file. --project, --output. | | runar graph refresh | Re-index an already-built graph so it matches the working tree. --project, --path, --full, --check (report only; exits 0 current / 2 stale / 3 cannot tell). | | runar graph autorefresh | Hook entry point: start a background refresh if one is due. --silent for hook use; opt in via setup claude-code --with-graph-autorefresh. | | runar hint | PreToolUse Grep|Glob search hints from the symbol graph. --silent for hook use; opt in via setup claude-code --with-search-hints. | | runar architecture | Latest architecture summary for a project. | | runar techdebt | List TODO/FIXME/HACK/XXX markers. --type. | | runar ask | Curator Q&A from the CLI. --project. | | runar onboard | Multi-section onboarding report. --json. | | runar benchmark | Memory-quality benchmark (deterministic). --mode quick|full. | | runar gc | Tier graduation + stale eviction. --project, --dry-run. | | runar export | Export entries as JSONL. --project, --type, --output, --limit. | | runar import | Import entries from JSONL. | | runar sync init | Validate local + remote pair. --force overrides schema mismatch. | | runar sync push | Drain local outbox to remote. --limit, --dry-run. | | runar sync pull | Incremental pull (remote → local). --limit, --dry-run, --since. | | runar sync bootstrap | First-time / full-table pull. --project, --page-size, --yes-i-know. | | runar sync status | Read-only sync health summary. --json. | | runar sync enable\|disable | Toggle background auto-sync. | | runar sync gc | Outbox retention sweep (default 7 days). --dry-run. | | runar session ping\|list | Session heartbeat / recent-session listing. | | runar context | Print recent context (PreToolUse hook target). | | runar nudge | UserPromptSubmit hook (idle-save reminder). | | runar save-ack | PostToolUse acknowledgement hook. | | runar extract | Passive PostToolUse extraction (gated by RUNAR_PASSIVE_LEARNING=true). | | runar enqueue | Enqueue raw PostToolUse payload onto observation queue.

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.