MRI reads what's actually in your codebase — and who actually wrote it. Local-first codebase intelligence: git history, AI-session provenance, explainable risk, decision-to-consequence tracking. MIT licensed.
MRI turns a repository into an explainable model of its history, structure,
and risk — and then goes where other tools stop: it reads the AI-session logs
already on your machine (~/.claude, ~/.cursor) to map prompt → file →
commit, decomposes each file's risk into AI-authored vs human-authored
shares, and correlates the decision behind a change to the consequence
that followed. All on your machine. Zero cloud, zero telemetry, zero accounts.
Site: mri.shypot.com · Docs: docs/ · How it works: mri.shypot.com/how-it-works
pip install project-mri
mri scan . # analyze a repo (path or git URL)
mri fusion # AI-provenance view: authorship, decisions, consequences
mri serve # dashboard at http://localhost:7331/dashboard/Individually, most of MRI's capabilities have a rival. Collectively — as one complete, trustworthy, free, self-hostable loop — it stands alone:
- History + structure — full git history × tree-sitter AST. Hotspots, churn, ownership, coupling, complexity: measured, not guessed.
- Session-log provenance — reads local
~/.claude/~/.cursorlogs (and consumes Agent Trace / git-ai git-notes) to map prompts to files to commits. - Authorship-decomposed risk — every 0–100 score carries a ledger, then
splits into AI vs human shares via
git blame× session-commit correlation. Unattributed lines stay unattributed — never silently counted as human. - Decision provenance — the "why" behind a change, mined from ADRs (confidence 0.95) and commit rationale (0.6), recorded as a first-class artifact.
- Consequence loop — did the metric move afterward? 30-day window, confidence capped at 0.6, confounder guardrails. Correlation, never causation.
Surfaced to humans — dashboard, self-contained HTML report, CLI, SARIF CI-gate —
and to agents, via a read-only MCP server (mri mcp).
- Local-first, forever —
pip install project-mri; nothing leaves your machine - Session-log AI provenance — prompt-level attribution, not git-metadata guessing
- Explainable scores — every number traces to a commit, line, or AST node
- Six analyzers — git history, architecture, dependencies, complexity, tech debt, coupling
- Decision → consequence — guardrailed correlation, drawn as a dashed line by design
- Agent-native — read-only MCP server over stdio for Claude Code, Cursor, any MCP client
- Self-hosted dashboard — terminal-aesthetic UI at
/dashboard/, shipped in the wheel - CI integration — GitHub Action, GitLab CI template, SARIF with authorship properties
- Zero telemetry, proven — an egress-tripwire test fails the build if any code path opens a non-loopback connection
- Privacy by default — session content is off (
store_content=False), enforced at the DB layer - Watch mode, webhooks (HMAC-signed), scan diff, backups
pipx install project-mri # or: pip install --user project-mriOr with Docker (build from source):
git clone https://github.com/veter391/project-mri.git
cd project-mri
docker build -t project-mri .
docker run -d --name project-mri -p 7331:7331 \
-v mri-data:/home/mri/.cache/project-mri \
project-mrimri init # create admin user (interactive)
mri serve # start API + dashboardOpen http://localhost:7331/dashboard/. Loopback needs no auth; binding to a
public interface fails closed without configured auth (ADR-013).
mri scan /path/to/your/repo # local path
mri scan https://github.com/owner/repo.git # shallow clone, auto-cleanup
mri scan . --sessions ~/.claude # include AI-session provenance
mri fusion # authorship / decisions / consequences
mri watch /path/to/your/repo # re-scan on change
mri demo # synthetic demo scanReports land in ~/.cache/project-mri/reports/<uuid>.html — self-contained,
archivable, readable in five years.
The repo is a hybrid monorepo: a Python package (src-layout) plus a pnpm
workspace of Next.js apps.
project-mri/
├── pyproject.toml # Python package (src-layout), pinned deps
├── pnpm-workspace.yaml # pnpm workspace → apps/*
├── src/mri/ # Python package (import name: mri)
│ ├── analyzers/ # six analyzers
│ ├── api/ # FastAPI app, routes, middleware
│ ├── auth/ # JWT + bcrypt
│ ├── services/ # scanner, repo_cloner, webhook, watcher
│ ├── db/ # schema.sql + repository (content-retention triggers)
│ ├── _frontend/dashboard/ # built dashboard, embedded at build time (gitignored)
│ ├── security.py # path/branch validation, safe-bind guard
│ ├── config.py # .mri.yml loader
│ └── cli.py # CLI commands
├── apps/
│ ├── web/ # Next.js 16 marketing site → Cloudflare Workers (mri.shypot.com)
│ └── dashboard/ # Next.js dashboard → static export, embedded in the wheel
├── tests/ # pytest suite (unit + API + E2E + egress tripwire)
├── docs/ # METHODOLOGY, TRUST, AUDIT, API, CONFIG, INSTALL, INTEGRATIONS + adr/
├── .github/
│ ├── workflows/ci.yml # lint, tests, Next builds, Docker, Bandit, pip-audit
│ └── action/action.yml # official GitHub Action
├── ci/gitlab-ci.yml # GitLab CI template
└── LICENSE, CHANGELOG.md, CONTRIBUTING.md, SECURITY.md
The dashboard ships inside the Python wheel: apps/dashboard builds a static
export that is served by FastAPI at /dashboard/ — pip install project-mri
needs no Node runtime.
| Analyzer | What it measures |
|---|---|
| git_history | Commit hotspots, bus factor, knowledge islands, change frequency |
| architecture | Module map, god modules, deep nesting, layer violations |
| dependencies | Import graph, SCC cycle detection, fan-in/fan-out, unstable modules |
| complexity | LOC, function length, cyclomatic complexity (lizard), comment ratio |
| tech_debt | Weighted TODO/FIXME/HACK markers, dead code, density per file |
| coupling | Robert Martin's I/A/D metrics, afferent/efferent coupling |
Each contributes a 0–100 score with a contributor ledger. The composite is a weighted mean; unmeasured analyzers are excluded, never zeroed. Every score decomposes in the dashboard — METHODOLOGY.md explains every number.
| Endpoint | Purpose |
|---|---|
GET /api/health · /api/health/deep |
Liveness / readiness |
POST /api/scans |
Start a scan (path or URL) |
GET /api/scans · /api/scans/{uuid} |
List / status + report |
GET /api/scans/{uuid}/report.{html,json,sarif} |
Three formats |
GET /api/scans/{a}/diff/{b} |
Compare two scans |
GET /api/projects/{id}/fusion |
AI-provenance fusion view |
WS /api/ws/scans/{uuid} |
Live progress |
POST /api/auth/login · GET /api/auth/whoami |
Auth (JWT, 24h) |
GET /metrics |
Prometheus format |
GET /dashboard/ |
Self-hosted dashboard |
Full reference: API.md
- Backend: Python 3.10+, FastAPI, aiosqlite, GitPython, tree-sitter, Pydantic v2, bcrypt, PyJWT, watchdog, prometheus-client
- Frontend: Next.js + TypeScript + Tailwind v4 —
apps/web(marketing, Cloudflare Workers) andapps/dashboard(embedded in the wheel) - Tests: pytest, pytest-asyncio, httpx, Playwright (E2E), an egress tripwire
- CI: GitHub Actions (lint + tests + Next builds + Docker + Bandit + pip-audit)
Measured on MRI's own repository (AUDIT.md): 270 files, 98 findings, ~2.5s. Scaling study: 200 files ≈ 2.4s · 800 ≈ 9.7s · 1600 ≈ 13.2s — roughly linear.
Self-hosted means you own your data — MRI ships hardened defaults:
- Fail-closed exposure — non-loopback bind without auth refuses to start (ADR-013)
- bcrypt(12) password hashing · JWT HS256 (24h) with DB-stored secrets
- Path validation (rejects
..), branch validation (rejects shell metacharacters), clone-SSRF guard - Per-IP rate limiting — 60 req/min, 5 scans/min
- CSP, HSTS, X-Frame-Options on every response · CORS allowlist, no wildcards
- HMAC-SHA256 webhook signing · 1 MiB body cap · tarfile traversal guard in
mri restore - Zero telemetry, enforced by test —
tests/test_no_network.pyseals the network and fails the build on any egress
Every guarantee maps to the code or test that proves it: TRUST.md. Disclosure policy: SECURITY.md.
git clone https://github.com/veter391/project-mri.git
cd project-mri
# Backend (src-layout, editable install)
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
mri init && pytest
# Frontend (pnpm workspace)
pnpm install
pnpm dev:web # marketing site
pnpm dev:dashboard # dashboard
pnpm build:dashboard # static export → embedded into src/mri/_frontend
# Quality gate
ruff check src/mri && bandit -r src/mri && pip-audit --strictQuality bars are enforced in CI: ruff zero-findings, 75% coverage floor (QUALITY-BARS.md). Contribution flow: CONTRIBUTING.md.
v0.3.0 — Beta. The fusion loop (session provenance → authorship-decomposed risk → decisions → consequences) is complete end-to-end; API, CLI and dashboard are stable. Toward 1.0:
- Cursor / aider session-log ingestion (deferred until real samples — ADR-009)
- Session-reasoning "why" mining (ADR-012)
- Plugin system for custom analyzers
- Incremental scans · configurable scoring weights
- Multi-language structural expansion (Rust, Go, Java)
Decision records: docs/adr/. History: CHANGELOG.md.
MIT — forever. The whole system is open source: all analyzers, the fusion engine, the API, the dashboard, the MCP server, the CI integrations. No paid tier, no feature gating, no telemetry, no account. A tool that reads your prompts and your source has to be inspectable and un-revocable — so it is.
Built on excellent open source, named and credited: tree-sitter, PyDriller, lizard, grimp + import-linter, NetworkX, GitPython, FastAPI + Pydantic.
