Skip to main content
Mollify

Deterministic codebase intelligence for Python.

Dead code · duplication · circular dependencies · complexity & hotspots · architecture · dependency hygiene · type health · security — as evidence, not guesses.

PyPI crates.io Python CI CodeQL License: MIT

Usage · Cookbook · Configuration · Architecture · CI integration · Agent integrations


Mollify is a Rust-native engine that gives humans and AI agents a structured, inspectable map of a Python codebase. It's fallow's model — one fast binary that unifies the whole "what's unused / risky / duplicated / tangled" question — ported to Python and extended with Python-specific signals (type health, notebooks, framework awareness) that fallow doesn't have.

Its one rule: no AI invents findings. Every result is a piece of deterministic evidence with a stable fingerprint, a confidence tier, and a human-readable reason. Mollify produces candidates; you (or your agent) decide what to do with them.

Project status: early but real — published on PyPI and crates.io (see the badges above for the current version). The core analysis phases are implemented, tested (210+ tests), and dogfooded; CI + CodeQL are green. See docs/adr/ for design decisions and Engineering notes below for how it works.

Why Mollify

Why Mollify

  • One tool, eight signals. Most Python shops bolt together vulture + ruff + deptry + tach + radon + jscpd + bandit. Mollify runs the equivalent set in a single deterministic pass with one config and one output contract.
  • Built for coding agents. A first-class MCP server plus shipped integrations for Devin/Cascade, Claude Code, Codex, Cursor, and Gemini CLI — so the agent reads repo truth instead of reconstructing it from grep.
  • Honest about uncertainty. Python dead-code detection is undecidable in general, so every verdict is tiered certain / likely / uncertain and only certain findings are ever auto-fixed. Framework decorators (routes, tasks, fixtures, CLI commands, validators) are understood, killing the #1 false positive.
  • Deterministic & CI-ready. Identical input → byte-identical output. SARIF, JSON, exit codes, and a PR-scoped --gate new-only.

What it detects

What it detects

Area Command Rules
Dead code mollify dead-code unused-file, unused-export, unused-import, unused-variable, unused-parameter, unused-method, unused-attribute, unused-enum-member, unreachable-code, duplicate-export, commented-code
Dependency hygiene mollify deps unused-dependency, missing-dependency, transitive-dependency, misplaced-dev-dependency, unresolved-import (pyproject + requirements/uv/pdm; venv-aware)
Architecture mollify arch circular-dependency, layer-violation, forbidden-import, independence-violation, private-import, custom policies
Complexity & cohesion mollify complexity high-complexity, hotspot (churn × complexity), low-cohesion (LCOM*)
Duplication mollify dupes duplication (clone families)
Type health mollify types untyped-function, private-type-leak
Security mollify security eval/exec, shell, sql-injection, weak hash/cipher, insecure-random, unsafe deserialization, TLS, secrets, missing-timeout, Flask debug, Jinja2 autoescape, broad except: pass — each with a CWE id
Cold paths mollify coverage --coverage-file cold-code (reachable but never executed)
Supply chain mollify supply-chain vulnerable-dependency (live OSV; offline DB fallback)
Metrics mollify metrics Maintainability Index, Halstead, raw LOC, per-file complexity
Everything + score mollify audit all of the above + a 0–100 quality score

Every finding carries one of mollify's eight categories (dead-code, dependency-hygiene, circular-dependency, complexity, architecture, duplication, type-health, security); cold paths, supply chain, and metrics are additional command surfaces over those same categories.

Plus mollify graph [--mermaid] (import-graph export), mollify lsp (editor diagnostics), and --format github|junit for CI.

Also: Jupyter notebooks (.ipynb) are discovered and analyzed cell-by-cell; framework awareness (Flask/FastAPI/Django/Celery/pytest/click/Pydantic/…); architecture presets (layered/hexagonal/feature-sliced/bulletproof) and declarative rule packs (ban imports/calls per path); mollify fix to safely remove certain unused symbols; mollify explain <rule> for rule semantics; and mollify trace <module> for a module's import neighborhood; mollify inspect <file> for a per-file evidence bundle; mollify list for project topology; and regression baselines (--save-baseline / --baseline --fail-on-regression) to gate CI on new issues without git; and --include <dir> (repeatable) to scan a directory normally pruned by the builtin denylist, exclude_dirs, or .gitignore.

Install

Install

Python users (recommended) — via uv:

uvx mollify audit              # one-off, isolated (no install)
uv tool install mollify        # persistent, puts `mollify` on your PATH
uvx mollify@latest audit       # pin/refresh to a specific version

Or pip / cargo:

pip install mollify
cargo install mollify-cli        # builds from crates.io (binary: mollify)

From source (Rust):

git clone https://github.com/FavioVazquez/mollify
cd mollify
cargo build --release          # binary at ./target/release/mollify

Every channel ships the same self-contained binary with the agent integrations embedded: the PyPI wheel bundles the compiled binary (built with maturin); the crates.io build embeds the artifacts from the in-crate assets/. Interactive human runs print a one-line upgrade hint when a newer version is published; machine formats, pipes, CI, and non-TTY agent paths never do. Set MOLLIFY_UPDATE_CHECK=off (or DO_NOT_TRACK=1) to disable it.

Install agent integrations

Scaffold the version-matched skills, rules, hooks, slash-commands, and workflows for your agent straight into a repo (works however mollify was installed):

mollify init --agent claude    # or: cursor / gemini / codex / cascade
mollify init --all             # every supported agent
mollify init --all --force     # overwrite existing files

Quick start

Quick start

mollify audit --path /your/python/project
Mollify audit — /your/project
Quality score: 84/100
12 finding(s) across 47 file(s) — 0 error, 12 warn
  src/app.py:6   [warn/certain]  unused-export — function `_legacy` has no reachable references  (unused-export:931a82e6d41f07c3)
  src/api.py:88  [warn/likely]   high-complexity — function `handle` is complex (cyclomatic 14, cognitive 19)  (high-complexity:1aa9…)
  src/db.py:1    [warn/certain]  circular-dependency — import cycle: db → models → db  (circular-dependency:7c…)
  pyproject.toml:1 [warn/likely] unused-dependency — declared dependency `rich` is never imported  (unused-dependency:93…)

Machine-readable + CI:

mollify audit --format json                       # kind-discriminated contract
mollify audit --format sarif > mollify.sarif      # GitHub/GitLab code scanning
mollify audit --gate new-only --base origin/main  # only fail on regressions
mollify fix                                        # preview safe removals (--apply to write)

Supply-chain (live OSV by default, offline fallback):

mollify supply-chain                 # query OSV.dev live for pinned versions
mollify supply-chain --refresh       # …and cache results to .mollify/advisories.json
mollify supply-chain --offline       # deterministic: local advisory DB only
# `mollify audit` stays offline — it folds in supply-chain from .mollify/advisories.json when present
python3 scripts/fetch-advisories.py .mollify/advisories.json   # seed/refresh the DB out-of-band

Confidence tiers

Tier Meaning Auto-fixable
certain Provable (e.g. a private unused symbol in reachable, non-fixture code; no dynamic dispatch in scope) ✅
likely Strong static signal, small residual dynamic risk —
uncertain Public surface, or near getattr/eval/importlib —

The JSON contract

Every command emits a kind-discriminated envelope (schema_version pinned by agent skills). Clients switch on kind and iterate findings[]:

{
  "kind": "audit", "schema_version": "0.1", "quality_score": 84,
  "summary": { "total": 12, "errors": 0, "warnings": 12, "files_analyzed": 47 },
  "findings": [{
    "fingerprint": "unused-export:931a82e6d41f07c3", "rule": "unused-export",
    "category": "dead-code", "severity": "warn", "confidence": "certain",
    "reason": "function `_legacy` has no reachable references in the project",
    "location": { "path": "src/app.py", "line": 6, "end_line": 7 },
    "actions": [{ "type": "remove-symbol",
                  "description": "Delete unused function `_legacy`",
                  "auto_fixable": true,
                  "suppression_comment": "# mollify: ignore[unused-export]" }]
  }]
}

Configuration — .mollifyrc.json

{
  "severity": { "dead-code": "error", "duplication": "warn", "unused-dependency": "off" },
  "ignore": ["tests/", "migrations/"],
  "max_cyclomatic": 10,
  "max_cognitive": 15,
  "architecture": { "layers": ["api", "service", "domain", "infra"] },
  "policies": [
    { "id": "no-requests-in-domain", "forbid_import": "requests", "in_paths": ["domain/"], "severity": "error" }
  ]
}

Raise rules/categories to error to make CI (and agent hooks) block. Full reference: docs/configuration.md.

Agent integrations

Agent integrations

One MCP server (mollify mcp), many front-ends. Shipped, ready-to-commit artifacts:

Agent Artifacts
Devin Desktop / Cascade .devin/skills/mollify/, .devin/rules/mollify.md, .devin/hooks.v1.json + .windsurf/hooks.json, .windsurf/workflows/mollify-*.md
Claude Code .mcp.json, .claude/skills/mollify/, .claude/commands/, .claude/settings.json hooks
Codex AGENTS.md, .codex/config.toml, .agents/skills/mollify/ (portable)
Cursor .cursor/rules/mollify.mdc, .cursor/mcp.json, .cursor/commands/
Gemini CLI GEMINI.md, .gemini/settings.json, .gemini/commands/mollify/

Scaffold any of these into a repo with mollify init --agent <name> (or --all) — see Install agent integrations above.

Architecture

Architecture

A Cargo workspace; data flows parse → graph → engines → report:

mollify-types (JSON contract) · mollify-parse (Python parsing, ruff AST) · mollify-graph (module/symbol graph + reachability + cycles) · mollify-core (the engines) · mollify-cli (mollify) · mollify-mcp (MCP server) · mollify-lsp (Language Server).

See docs/architecture.md.

How it compares

How it compares

vulture ruff deptry tach radon jscpd bandit Mollify
Whole-project dead code ✅ – – – – – – ✅ (reachability + tiers)
Unused class members / enum members ✅ – – – – – – ✅
Unreachable code ✅ ~ – – – – – ✅
Dependency hygiene (unused/missing/transitive) – – ✅ – – – – ✅
Misplaced dev dependency – – ✅ – – – – ✅
Unresolved / broken imports – ~ – – – – – ✅
Circular deps – – – ✅ – – – ✅
Boundaries / interface (private-import) – – – ✅ – – – ✅
Complexity – ~ – – ✅ – – ✅
Churn × complexity – – – – – – – ✅
Duplication – – – – – ✅ – ✅
Type health + private-type leaks – ~ – – – – – ✅
Security candidates (+CWE) – ~ – – – – ✅ ✅
One deterministic pass + agent/MCP contract – – – – – – – ✅

~ = partial. Mollify's wedge is the unified deterministic pass with one contract — individual tools each already do a piece well; Mollify unifies them into a single evidence stream.

Engineering notes

Mollify banner

Mollify is built to be precise and dependency-light:

  • Full-fidelity parsing. Built on Astral's ruff_python_parser / ruff_python_ast — the same parser behind ruff — pinned to a crates.io release, so every distribution channel builds the identical binary (ADR-0001).
  • Real scope/binding resolution. Reachability resolves each name load to its binding (LEGB), so shadowing function-locals and attribute accesses never mask a dead top-level symbol.
  • Exact duplication. A linear-time SA-IS suffix array + LCP finds exact maximal token clones — no hash-collision guessing, scales to large repos.
  • Supply-chain. Matches pinned/locked versions precisely; for declared ranges it resolves the concrete installed version when a virtualenv is present, otherwise flags (at uncertain confidence) when the range permits a vulnerable version. supply-chain queries OSV live by default (offline DB fallback); mollify audit stays fully offline and deterministic.
  • Candidate-producer model. Security findings are syntactic candidates (never claimed as proven vulnerabilities), surfaced with a confidence tier — by design, not a gap.

Precision is the priority, built on real scope/binding resolution and package-aware import resolution; the deliberate precision tradeoffs (e.g. how lazy imports feed reachability but not architecture) are documented in docs/adr/. Remaining roadmap items are mostly performance optimizations (e.g. Salsa keystroke-incremental reparse for the LSP).

Contributing

Contributing

See CONTRIBUTING.md. The bar: every change compiles, is tested, and is documented; the tree stays fmt + clippy -D warnings clean.

License

MIT © 2026 Favio Vázquez

Metadata

Release files for mollify 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mollify 0.1.7
File Size Uploaded
mollify-0.1.7.tar.gz 224.6 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for mollify 0.1.7
File
mollify-0.1.7-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
mollify-0.1.7-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
mollify-0.1.7-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
mollify-0.1.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
mollify-0.1.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
mollify-0.1.7-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
mollify-0.1.7-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 24.8 MB

Release files / mollify-0.1.7.tar.gz

Download URL mollify-0.1.7.tar.gz
Size 224.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5910f29415cae3b2e68baf1843604fbae35673d18483adc0e714980f5ef5ab59
BLAKE2b-256 checksum
How to use checksums
1f898cc14a16f6dd6e915ab42d51ff508819397f7035d2be8333f965bc132a33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / mollify-0.1.7-py3-none-win_amd64.whl

Download URL mollify-0.1.7-py3-none-win_amd64.whl
Size 3.6 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
d4e2cc9c564f13a5be83a2ba7d1f2fd8f8bdfd3ca437727fa7b537bc803b3901
BLAKE2b-256 checksum
How to use checksums
ded4e395ec5b6a2ec16f58fcd1b680a0c3c84e66106df605cefa1476ae9d7b47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / mollify-0.1.7-py3-none-musllinux_1_2_x86_64.whl

Download URL mollify-0.1.7-py3-none-musllinux_1_2_x86_64.whl
Size 3.7 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
450cd6cfb5087d3d78eea2003882778f1ef73ac43d4cd3547905899ee80bf8c2
BLAKE2b-256 checksum
How to use checksums
dad44bf6c0cba85cfd8a9b8d8b3e081fad984171065e3136b63806024f44e34e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / mollify-0.1.7-py3-none-musllinux_1_2_aarch64.whl

Download URL mollify-0.1.7-py3-none-musllinux_1_2_aarch64.whl
Size 3.4 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
a0c8ae6b977be5753c849f73189d222891bcf7e9fb347b3352bfba3a212faabe
BLAKE2b-256 checksum
How to use checksums
a15c74d071493940fffb40f635ddb02be8bb502e69d0d49ae99207b740c6a775
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / mollify-0.1.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL mollify-0.1.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.6 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
59d6e0c4b1da52061d5cb101dba46188052497fcb052979657135bf232c40575
BLAKE2b-256 checksum
How to use checksums
98b8689b22d824e90236f6bc668bd5027ddfe472f9e18229a91676147cd8514f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / mollify-0.1.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL mollify-0.1.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 3.4 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
afd93947ae1c800821a1b0be91706e813b695a23485bba05133a8c2cff0bf3ca
BLAKE2b-256 checksum
How to use checksums
8bd3e0ff61f0d31e6e5d17a4cb528c4376c0c4131cd229807812564b762f6b33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / mollify-0.1.7-py3-none-macosx_11_0_arm64.whl

Download URL mollify-0.1.7-py3-none-macosx_11_0_arm64.whl
Size 3.3 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a1bcd3e96f9e45affebb0925af9c5923c8d76ace348ecbc6479f8001b07b69ca
BLAKE2b-256 checksum
How to use checksums
84a6a65cca670878a68071962d8db34894021d45fce208288f18947b06a67499
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / mollify-0.1.7-py3-none-macosx_10_12_x86_64.whl

Download URL mollify-0.1.7-py3-none-macosx_10_12_x86_64.whl
Size 3.5 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
2e158a92282be4ddce9bec3f01620104f618f32e2601aa2117d789ad21b5f195
BLAKE2b-256 checksum
How to use checksums
4c731a6000e4f8e449af010272fd2d211c4f5516e372662e12ed6e71e5673c02
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.2

8 release files

0.2.1

8 release files

0.2.0

8 release files

This release

0.1.7 This release

8 release files

0.1.6

8 release files

0.1.5

8 release files

0.1.4

8 release files

0.1.3

8 release files

0.1.2

8 release files

0.1.1

7 release files

0.1.0

8 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page