MRI scan for your codebase — local-first codebase intelligence tool
Project description
MRI
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/
The loop
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).
Highlights
- 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
Quick start
Install
pipx install project-mri # or: pip install --user project-mri
Or 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-mri
First run
mri init # create admin user (interactive)
mri serve # start API + dashboard
Open http://localhost:7331/dashboard/. Loopback needs no auth; binding to a
public interface fails closed without configured auth (ADR-013).
Scan something
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 scan
Reports land in ~/.cache/project-mri/reports/<uuid>.html — self-contained,
archivable, readable in five years.
Repository layout
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.
The six analyzers
| 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.
HTTP API
| 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
Tech stack
- 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)
Performance
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.
Security
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.
Development
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 --strict
Quality bars are enforced in CI: ruff zero-findings, 75% coverage floor (QUALITY-BARS.md). Contribution flow: CONTRIBUTING.md.
Project status
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.
License
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.
Credits
Built on excellent open source, named and credited: tree-sitter, PyDriller, lizard, grimp + import-linter, NetworkX, GitPython, FastAPI + Pydantic.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file project_mri-0.3.0.tar.gz.
File metadata
- Download URL: project_mri-0.3.0.tar.gz
- Upload date:
- Size: 598.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be425373bf26991bdebd8cbed841f09860c6e0b15ef4c0400ed9033313fc7251
|
|
| MD5 |
e8332b62e165d47bb811c67b04dedc3d
|
|
| BLAKE2b-256 |
4308bfefbd0ed172503f844e4fa0433255ae9881b3bbddef9e86d8213c19ac17
|
File details
Details for the file project_mri-0.3.0-py3-none-any.whl.
File metadata
- Download URL: project_mri-0.3.0-py3-none-any.whl
- Upload date:
- Size: 552.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc997a5bc85a8b565d9be2b7b84e6e854ad8807622a8e18c4dfc1b66e1f9eb74
|
|
| MD5 |
b411d7c35df91fecf463452824e9b8ac
|
|
| BLAKE2b-256 |
271a064b86b35255b19642ce37baa2405c4760f545520e72491080aaa35b972b
|