Architectural audit tool for multi-module Gradle Android projects.
Project description
๐งฑ modulith-android
Architectural audit for multi-module Gradle Android projects โ cycles, layer violations, visibility issues, unused dependencies, and impact cascades, all in a single self-contained HTML report.
Point it at any Gradle Android repo. It parses your settings.gradle[.kts], walks every module's build file, scans your Kotlin/Java sources for cross-module imports, and produces a single self-contained HTML file with:
- ๐ธ๏ธ Module graph โ every
:layer:namemodule and its dependency edges, colour-coded by layer. - ๐ Cycle detection โ Tarjan-based strongly-connected components; any cyclic coupling between modules is flagged.
- ๐ซ Layer violations โ edges that cross a forbidden layer pair (e.g.
core โ featureunder Clean Architecture), with the offending Gradle dependency listed. - ๐๏ธ Visibility audit โ for the modules you choose, every
publicsymbol is classified asinternalize_candidate,di_required,external_consumer, orstar_import_uncertainso you know what's actually load-bearing. - ๐ชฆ Unused module dependencies โ flags
project(":foo")declarations whose target module's packages the consumer's source never imports. - ๐ฅ Impact cascades โ pick a module, see every module that transitively depends on it.
- ๐ Rankings โ modules sorted by fan-in, fan-out, instability, and abstractness.
Configuration-driven and project-agnostic. Every project-specific value (root package, layer names, forbidden layer pairs, audited modules) lives in a single
modulith.tomlat your repo root. Runmodulith-android initand the wizard auto-detects sensible defaults in seconds โ confirm with Enter, edit otherwise. Drop it into any Gradle Android project and you're scanning in under a minute.
A report generator, not a CI gate. modulith-android never fails a build and never exits non-zero based on findings. It reads, computes, and writes โ interpretation and policy belong to whoever reads the report. By design.
๐ง Status
Pre-alpha. v0.1.0 in active development. The repository scaffold is in place; CLI, wizard, and analysis pipeline land progressively as the milestones in the roadmap ship. The quick start below describes the shipped behaviour at v0.1.0.
๐ Quick start
# one-shot, no install โ needs uv (https://docs.astral.sh/uv/)
uvx --from modulith-android modulith-android init # wizard writes ./modulith.toml
uvx --from modulith-android modulith-android # writes build/dependency-graph/index.html
Prefer an installed entry-point? Use pipx:
pipx install modulith-android
modulith-android init
modulith-android
The default run writes build/dependency-graph/index.html. Open it in any browser โ no static server, no JavaScript build, no external assets.
๐ ๏ธ Commands
| Command | What it does | Output |
|---|---|---|
modulith-android init |
runs the interactive wizard with auto-detected defaults | ./modulith.toml |
modulith-android |
runs the full analysis using ./modulith.toml |
build/dependency-graph/index.html |
modulith-android --repo PATH |
analyse a project in a different directory | report in that project's build/ |
modulith-android --out PATH |
write the report somewhere else | HTML at the supplied path |
modulith-android --config PATH |
use a config file at a non-default location | unchanged |
Exit codes are 0 on success and 1 on configuration / I/O errors. Findings never change the exit code.
๐ช The wizard
modulith-android init runs four short questions, each with an auto-detected default. Confirm with Enter; edit anything that looks off.
| # | Question | Auto-detected from |
|---|---|---|
| 1 | Root package (e.g. com.example) |
Scans .kt/.java files, computes the longest common package prefix. |
| 2 | Layer names (e.g. core, data, feature, app) |
Reads settings.gradle[.kts], extracts the first segment of each module path. |
| 3 | Modules to audit for visibility | Pre-selects all modules in the innermost layer; multi-select to customise. |
| 4 | Forbidden layer pairs | Offers presets (Clean Architecture, MVI/MVVM) or "Custom" for manual entry. |
The wizard prints the generated modulith.toml for review and asks before writing.
โ๏ธ Configuration
The full modulith.toml schema:
# Generated by `modulith-android init`. Hand-edit anything you like.
[scan]
# Root Java/Kotlin package. Used by the visibility analyzer to scope
# import-index scanning to symbols declared in this package tree.
root_package = "com.example"
[layers]
# Ordered list of layer names, derived from the first segment of each
# Gradle module path (e.g. ":core:logger" -> "core"). Modules whose
# first segment isn't listed are parsed for edges but excluded from
# violation checking.
names = ["core", "data", "feature", "app"]
[visibility]
# Gradle module paths whose public API will be enumerated and
# cross-checked for external references.
target_modules = [
":core:logger",
":core:network",
]
# Each [[violations]] entry forbids a directed edge between two layers.
# Multiple entries are independent โ they don't compose.
[[violations]]
from = "core"
to = "data"
[[violations]]
from = "core"
to = "feature"
[[violations]]
from = "data"
to = "feature"
Missing sections are silently treated as "skip this analysis" โ e.g. an absent [visibility] skips the visibility audit, an empty [[violations]] table means no violation rules are active. A missing modulith.toml is a hard error with a "run modulith-android init" hint.
๐ Requirements
| Tool | Why | Notes |
|---|---|---|
| Python 3.10+ | runs the analyzer | stdlib-only on 3.11+; one backport (tomli) on 3.10 |
uv or pipx (recommended) |
one-shot or isolated install | pip install --user modulith-android works too |
| Gradle project | the analysis target | Groovy or Kotlin DSL settings.gradle โ both are supported |
The analyzer itself has zero runtime dependencies on Python 3.11+ and exactly one (tomli) on Python 3.10. No HTML/JS framework, no JSON schema library, no graph library โ pure stdlib. No third-party Gradle plugin in the consumer's project either: every feature works against a vanilla Gradle build.
๐งฉ How it works
modulith-android
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 1. read modulith.toml โ every project-specific value โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 2. parse settings.gradle[.kts] โ list of modules โ
โ parse each module's build.gradle[.kts] โ edges โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 3. core graph algorithms (stdlib only): โ
โ Tarjan SCC โ cycles โ
โ layer-pair filter โ violations โ
โ reverse-BFS โ cascades โ
โ fan-in/out, etc. โ metrics โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 4. cross-check declared project deps against source imports โ
โ โ unused module dependencies โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 5. scan public API of audited modules; classify each symbol โ
โ by external-consumer count + Hilt/Koin DI markers โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 6. render a single self-contained HTML file โ
โ โ build/dependency-graph/index.html โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Every output is deterministic: given identical inputs the HTML is byte-for-byte the same, so regenerating after a code change produces a clean diff you can review.
๐๏ธ Project layout
modulith-android/
โโโ src/modulith_android/
โ โโโ cli.py entry-point; argparse dispatch
โ โโโ config.py ModulithConfig dataclass + TOML loader
โ โโโ wizard.py interactive `init` flow with auto-detect
โ โโโ parsers/
โ โ โโโ gradle_modules.py settings.gradle[.kts] + build.gradle[.kts] reader
โ โโโ analyzers/
โ โ โโโ unused_module_deps.py cross-checks declared project deps against source imports
โ โ โโโ visibility_audit.py public-API scanner + DI-marker classifier
โ โโโ core/
โ โ โโโ model.py Edge, Module, GraphSnapshot
โ โ โโโ cycles.py Tarjan SCC
โ โ โโโ cascades.py transitive impact computation
โ โ โโโ metrics.py fan-in, fan-out, instability, abstractness
โ โ โโโ violations.py layer-rule checker
โ โโโ reports/
โ โ โโโ html.py the self-contained HTML+CSS+JS report
โ โ โโโ json_export.py machine-readable graph dump
โ โโโ common/
โ โ โโโ paths.py module-path utilities
โ โโโ flows/
โ โโโ analyze.py orchestrates the full pipeline
โโโ tests/ stdlib-unittest suite, no pip deps
โโโ pyproject.toml
โโโ LICENSE
โโโ README.md
๐งโ๐ป Direct CLI
uvx/pipx are the easy paths, but the package is a normal CLI. Once installed:
modulith-android [SUBCOMMAND] [OPTIONS]
Subcommands:
init run the wizard; writes ./modulith.toml
Options (default run):
--repo PATH repository root (default: cwd)
--out PATH output directory (default: <repo>/build/dependency-graph)
--config PATH config file (default: <repo>/modulith.toml)
-h, --help show this help and exit
--version show version and exit
Exit codes:
0 success; HTML report written
1 configuration or I/O error
๐งช Development
pip install -e ".[dev]"
python -m pytest tests/ # full suite
python -m pytest tests/test_visibility_audit.py # one module
ruff check src/ tests/ # lint
Tests use stdlib unittest; pytest discovers them with no configuration. CI runs the suite on Python 3.10 and 3.12.
๐บ๏ธ Roadmap
- v0.1.0 โ analyzer core,
modulith.tomlconfig, wizard with auto-detect, self-contained HTML report, PyPI publication. - v0.2.0 โ JSON export improvements; richer cascade visualisation; configurable Hilt/Koin marker sets.
- v0.3.0 โ multi-DSL improvements (KTS multi-line includes, type-safe project accessors).
- v1.0.0 โ API stability promise.
๐ฏ Scope
modulith-android focuses on modularity: graph shape, layer rules, visibility, and unused inter-module dependencies. It does NOT audit external Maven dependencies or Gradle configuration hygiene (api vs implementation, scope choices). For that, plugins like the Dependency Analysis Gradle Plugin are excellent companions and orthogonal to what this tool does.
๐ License
MIT โ see LICENSE.
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 modulith_android-0.1.1.tar.gz.
File metadata
- Download URL: modulith_android-0.1.1.tar.gz
- Upload date:
- Size: 50.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d07f76cfc76ca643c7b6f76a5892217f634902cd8687ab490fdc6d1691c5db2
|
|
| MD5 |
fbff62cbf8584ec341bae80ae613afc8
|
|
| BLAKE2b-256 |
49672c19e2fc68b0972791555775ce528bfba630b05b37142224be3c96378f29
|
File details
Details for the file modulith_android-0.1.1-py3-none-any.whl.
File metadata
- Download URL: modulith_android-0.1.1-py3-none-any.whl
- Upload date:
- Size: 44.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a63f1a833329bcfc313395a8ba25b23070cf0ff1e12dbc6c8cb38e2b9516a2c2
|
|
| MD5 |
a918de50d76a765236f8c634476f4467
|
|
| BLAKE2b-256 |
7d7eed64be74a779f0dc0e94a0052c772bf6b6a36a0753923c529ce1e3c39e78
|