CodeTruth Server
БесплатноНе проверенA verification layer that lets AI agents safely delete code in large codebases by assessing usage paths and providing risk statuses.
Описание
A verification layer that lets AI agents safely delete code in large codebases by assessing usage paths and providing risk statuses.
README
CI PyPI License: MIT Python 3.10+
A verification layer that lets AI agents safely delete code in large codebases.
Agents hallucinate absence of usage. CodeTruth inverts the question — instead of "is this code used?" it asks "can we prove this code is used?" — and only surfaces a symbol for deletion when it fails to find any usage path: no call, no import, no inheritance, no string reference, no reflection target, no framework registration. Detection is deterministic; the agent only reads the evidence and decides. It is a risk assessor for code deletion, not a dead code detector.
Sixty seconds of proof
Point it at real code — here it is finding genuinely dead code in urllib3:
$ pip install codetruth
$ codetruth scan ./urllib3
[SAFE] 0.95 connectionpool:_url_from_pool (connectionpool.py:1167)
[SAFE] 0.95 contrib.emscripten.connection:_supports_http_protocol ...
[DEAD?] 0.65 ...
928 symbols, 2576 edges | safe_to_delete: 4 likely_dead: 110 uncertain: 197 used: 591
$ codetruth check ./urllib3 connectionpool:_url_from_pool
"status": "safe_to_delete",
"evidence_for_deletion": [
"No strong references (calls/imports/inheritance) found in the repository",
"No string-literal, reflection, or attribute-name references detected",
"Not matched by any framework/entry-point rule",
"Not referenced by the test suite",
"Verified: symbol name occurs nowhere else in the repository's text"
],
"deletion_plan": { "span": {"start_line": 1167, ...}, "orphaned_imports": [...] }
Just as important is what it refuses to flag: route handlers, pydantic validators, enum members constructed by value, stdlib-override methods — symbols with zero direct references that are absolutely load-bearing. More real finds (and refusals) in FINDINGS.md; measured results in validation/VALIDATION.md.
Statuses
| Status | Meaning | Recommended action |
|---|---|---|
safe_to_delete |
zero usage paths found under every analysis rule, and the name verified absent from all repo text outside its own definition | delete |
likely_dead |
no usage found, but external exposure can't be ruled out (public API, module, test-only) | review_required |
uncertain_dynamic_risk |
weak evidence exists (string refs, reflection, dynamic module) | review_required |
definitely_used |
strong reference or framework entry point proven | keep |
Install
Requires Python 3.10+. The core is lightweight (networkx + PyYAML);
the MCP server and the JS plugin are opt-in extras.
pip install codetruth # CLI + Python API (dead-code gate, CI, scripts)
pip install "codetruth[mcp]" # + the agent-facing MCP server
pip install "codetruth[javascript]" # + the JS/TS plugin
pip install "codetruth[mcp,javascript]" # everything (or: codetruth[all])
- Not using an agent? Plain
pip install codetruthis all you need — the CLI (codetruth scan), Python API (from codetruth import scan), HTML report, and--cigate work with no extra dependencies. Themcpextra pulls a web-server stack (pydantic/starlette/uvicorn) and is only for the MCP server, so the core deliberately doesn't require it. - Using it with Claude Code / an MCP agent? Install
"codetruth[mcp]", thenclaude mcp add codetruth -- codetruth mcp. - If the
codetruthcommand isn't found, your Python scripts dir isn't on PATH — usepython -m codetruth.cli(andpython -m codetruth.mcp_server).
MCP (the primary interface — for agents)
pip install "codetruth[mcp]"
claude mcp add codetruth -- codetruth mcp
Tools exposed: check_deletion_safety(repo, symbol) (the one to call
before deleting), scan(repo, ...) (the whole review queue),
plan_deletion(repo, symbol) (advisory removal plan), and
scan_workspace(repos, ...) (cross-service usage across repos). The agent
workflow: identify symbol → call check_deletion_safety → only delete on
safe_to_delete; everything else routes to human review.
CLI
codetruth scan ./repo # review queue, strongest candidates first
codetruth scan ./repo -v --json out.json # full evidence
codetruth scan ./repo --app-mode # application (not library) repos:
# public symbols may be safe_to_delete
codetruth scan ./repo --strict # flag orphaned "useless clumps"
codetruth scan ./repo --min-rank 0.5 --group # trim the tail, group by file
codetruth scan ./repo --html report.html # self-contained HTML report
codetruth scan ./repo --ci # exit 1 if dead code exists (report gate)
codetruth scan ./repo --progress # live progress line (auto on a TTY)
codetruth baseline ./repo # accept current findings (see below)
codetruth check ./repo pkg.module:func # one symbol's evidence record
codetruth plan ./repo pkg.module:func # advisory deletion plan (never applied)
Long scans show a live progress line (files scanned, then graph/rules/verify
phases) on a terminal; it's auto-silenced when output is piped (--progress /
--no-progress to override). Ctrl+C cancels cleanly.
The --ci gate is advisory like everything else: it fails the build so a
human looks at provably-dead code — it never deletes. Mark false alarms with
# codetruth: keep or a .codetruth.toml entrypoint. Disagree with a
verdict? codetruth report-fp ./repo pkg.mod:symbol generates a prefilled
issue — disputed verdicts are the most valuable feedback this project gets.
GitHub PR annotations (Action + SARIF)
# .github/workflows/deadcode.yml
permissions:
security-events: write
jobs:
deadcode:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- uses: AlaikAsif/CodeTruth@main
# inputs: path, language, args (e.g. "--app-mode"), upload-sarif
Findings appear as inline annotations in the PR (via SARIF + GitHub Code
Scanning), and the gate fails only on newly-introduced dead code once a
baseline is committed. Standalone: codetruth scan . --sarif out.sarif.
Adopting on an existing codebase (baseline)
A gate that fails on all pre-existing dead code never gets switched on. Accept the current state once, commit the baseline, and the gate only fails on newly introduced dead code:
codetruth baseline ./repo # writes .codetruth.baseline.json — commit it
codetruth scan ./repo --ci # now fails ONLY on new safe_to_delete code
The baseline keys on symbol ids, so line churn doesn't invalidate it. A
previously-hedged symbol whose deadness becomes provable (its last caller
was removed) counts as new. When accepted findings get cleaned up, the gate
tells you to refresh with codetruth baseline.
What gets scanned (scope)
CodeTruth scans the directory you point it at. It never descends into
dependency, VCS, build, or environment folders — they're pruned from the walk
(so they don't slow it down or pollute results): node_modules, .git/.hg/
.svn, .venv/venv/env/virtualenv, site-packages, __pycache__,
build/dist/.eggs/wheels, the various caches, and vendored-code dirs
(vendor, third_party, _vendor, vendored). So a virtualenv or installed
package left inside your repo won't be treated as your code.
To exclude your own folders (generated code, migrations, fixtures), add a
.codetruth.toml at the repo root:
[codetruth]
ignore_paths = ["generated/", "migrations/", "**/fixtures/**"]
Ignored folders are pruned from the walk too, so excluding a large directory
also makes the scan faster. To scan just one package of a monorepo, point
codetruth scan at that package's directory.
Python API
from codetruth import scan, check_deletion_safety
result = scan("./repo")
for rec in result.candidates():
print(rec.status.value, rec.symbol, rec.evidence_against_deletion)
Cross-repo / cross-service (workspace scan)
Single-repo analysis can't see that an endpoint is called over the wire or a shared package is imported by a sibling service — the exact usage that makes distributed deletion dangerous. Scan several repos as one system:
codetruth workspace ./service-api ./service-worker ./shared-lib
from codetruth import scan_repos
ws = scan_repos(["./service-api", "./service-worker"])
for xref in ws.crossrefs:
print(xref.symbol, "<-", xref.reason)
It matches HTTP routes to client calls (a FastAPI/Flask route linked to a
requests/httpx call in another repo, path templates and params normalized)
and shared imports across repos. A symbol that looks dead in its own repo
but is reached cross-repo is raised from likely_dead/safe_to_delete to
uncertain_dynamic_risk with an explicit reason — the overlay only ever moves
a verdict toward keep. Also exposed as the scan_workspace MCP tool.
Runtime evidence (v1.5)
Static analysis can't see cross-service usage (HTTP calls, queues, cron in
other repos). @codetruth.track logs real invocations in production:
import codetruth
@codetruth.track
def maybe_dead(): ...
Or instrument a whole package with zero source edits:
import codetruth.runtime
codetruth.runtime.instrument_package("myapp") # or CODETRUTH_AUTOTRACK=myapp
Then feed the trace back: codetruth scan ./repo --runtime-log runtime.jsonl.
Observed calls promote a symbol to definitely_used; "0 calls over N days"
becomes the strongest evidence tier for deletion.
Tracing is production-safe: each process writes its own runtime-<pid>.jsonl
(merged at read — no lock contention between workers), and a daemon thread
flushes counts every $CODETRUTH_FLUSH_INTERVAL seconds (default 60), so
long-running servers land evidence without a clean exit.
Finding useless clumps (strict reachability)
codetruth scan ./repo --strict asks a harder question: is this code
reachable from any real entry point (HTTP route, CLI command, __main__,
test, declared entrypoint)? Code that is internally well-connected — functions
calling each other — but never reached from an entry point surfaces as an
orphaned clump, with every member carrying a cluster field listing its
fellow members so the whole island can be reviewed (and deleted) as a group.
Dead-cluster grouping also applies in default mode whenever unreachable
symbols reference each other.
Configuration (.codetruth.toml)
Teach the scanner about usage it can't see:
[codetruth]
app_mode = true # public symbols are internal (application)
entrypoints = [ # externally-reached symbols (cron, RPC, ...)
"jobs.nightly:run",
"services.handlers.*",
]
ignore_paths = ["migrations/", "vendor/**"]
Inline: a # codetruth: keep comment on (or above) a definition marks it as
an entry point.
Deletion plans (advisory)
codetruth plan ./repo pkg.mod:symbol (also the plan_deletion MCP tool, and
attached automatically to every safe_to_delete record) describes exactly what
a removal would involve: the decorator-to-end source span, imports that become
orphaned, and any __all__ entry. CodeTruth never applies a plan — it is
information for whoever decides.
Review-queue ranking
Every record carries a rank_score in [0, 1] — a deterministic ordering
heuristic (not a calibrated probability; see PLAN.md §4). Higher means weaker
evidence of use, so scan() and the CLI surface the strongest deletion
targets first. Within uncertain_dynamic_risk it separates a lone
string-literal reference from forty fuzzy attribute-name matches, so a big
review queue is triageable instead of flat.
Performance
Scans are cached at <repo>/.codetruth/index.json, keyed by a fingerprint of
every source and config file's (mtime, size). An unchanged repo returns the
cached result (≈15× faster on an 8k-symbol repo); any file change triggers a
full rescan. The cache never patches the graph incrementally — a stale
cross-file edge could mask a real usage path, so correctness always wins.
Bypass with --no-cache (CLI) or force_rescan (MCP). Add .codetruth/ to
.gitignore.
Architecture
Layer 1 Symbol Extraction codetruth/languages/python/extractor.py
Layer 2 Relationship Graph codetruth/languages/python/edges.py (strong/weak edges)
Layer 3 Semantic Rules codetruth/languages/python/rules.py + codetruth/rules/python/*.yaml
Layer 4 Evidence + Decision codetruth/core/evidence.py (4-way status)
The core engine is language-agnostic (codetruth/core/, LanguagePlugin
interface).
Python is the full plugin. Framework awareness covers FastAPI/Flask/
Starlette routes, Django (signals, URLs, admin, management commands,
migrations), Celery, click/Typer, pytest, SQLAlchemy events, and — as of
0.5.0 — declarative schema models: fields of pydantic BaseModel/
BaseSettings/SQLModel, Django models/forms, DRF serializers,
TypedDict/NamedTuple, and marshmallow/msgspec are treated as framework-used
(populated, validated and serialized, not referenced like ordinary attributes),
transitively through subclasses, with the Config/Meta convention honoured.
Function-signature annotations (def f(u: User) -> Order) create usage edges,
so a model referenced only in type hints stays alive. New framework rules go
in codetruth/rules/python/*.yaml — no code changes.
JavaScript/TypeScript (pip install "codetruth[javascript]", then
scan --language javascript): tree-sitter extraction, ESM/CommonJS import
resolution, tsconfig/jsconfig paths + baseUrl aliases and monorepo
workspace packages, barrel re-export chains, Vue SFC (.vue)
scripts, package.json entry points (incl. scripts), Express/Fastify/emitter
callback handlers, React/JSX component and event-handler usage, string/config
wiring, eval poisoning, and external-base cautions — the shared evidence,
ranking, cluster, backstop, and cache layers work unchanged. Validated on real
apps (RealWorld React, preact, jupyterlab) with zero false positives; a
hand-labelled JS recall study is the remaining polish. Go is a stub.
Validation
The metric that matters is false positives — a symbol called
safe_to_delete that's actually used. Across 10 real Python packages
(requests, flask, click, jinja2, werkzeug, rich, pydantic, urllib3,
sqlalchemy, networkx — 36,457 symbols), the false-positive audit is
0 — and it still finds genuine dead code (e.g. urllib3._url_from_pool,
rich._svg_hash, requests.dict_to_sequence). Empirical calibration on
labelled data: safe_to_delete is 100% dead, monotone across tiers. JS is
validated on the RealWorld React app and preact (0 unsafe verdicts).
Reproduce with scripts/validation_report.py; details in
validation/VALIDATION.md.
Known limitations
- Cross-service usage is invisible to static analysis alone — runtime tracing is the partial fix.
- 100% certainty is impossible;
safe_to_deletemeans "no usage path found under the defined rules," not a mathematical proof. - Framework rule coverage (Layer 3) is a maintained knowledge base, never
finished. New rules go in
codetruth/rules/python/*.yaml— no code changes.
Установка CodeTruth Server
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/AlaikAsif/CodeTruthFAQ
CodeTruth Server MCP бесплатный?
Да, CodeTruth Server MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для CodeTruth Server?
Нет, CodeTruth Server работает без API-ключей и переменных окружения.
CodeTruth Server — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить CodeTruth Server в Claude Desktop, Claude Code или Cursor?
Открой CodeTruth Server на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare CodeTruth Server with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
