by LukasNiessen
ArchUnitPython is an architecture testing library. Specify and ensure architecture rules in your Python app. Easy setup and pipeline integration.
# Add to your Claude Code skills
git clone https://github.com/LukasNiessen/ArchUnitPythonLast scanned: 5/18/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-05-18T08:03:41.065Z",
"semgrepRan": false,
"npmAuditRan": true,
"pipAuditRan": true
}See how ArchUnitPython compares with popular alternatives.
ArchUnitPython is an open-source testing skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by LukasNiessen. ArchUnitPython is an architecture testing library. Specify and ensure architecture rules in your Python app. Easy setup and pipeline integration. It has 666 GitHub stars.
Yes. ArchUnitPython passed SkillsLLM's automated security scan — a dependency vulnerability audit plus prompt-injection heuristics — with no high-severity issues. You can read the full report in the Security Report section on this page.
Clone the repository with "git clone https://github.com/LukasNiessen/ArchUnitPython" and add it to your Claude Code skills directory (see the Installation section above).
ArchUnitPython is primarily written in Python. It is open-source under LukasNiessen on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other Testing skills you can browse and compare side by side. Open the Testing category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh ArchUnitPython against similar tools.
No comments yet. Be the first to share your thoughts!
Top skills in this category by stars
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
ArchUnitPython vs agentic bug hunter
See comparison
Enforce architecture rules in Python projects. Check for dependency directions, detect circular dependencies, enforce coding standards and much more. Integrates with pytest and any other testing framework. Very simple setup and pipeline integration. Zero runtime dependencies.
The #1 ArchUnit-style architecture testing library for Python, measured by GitHub stars.
Inspired by the amazing ArchUnit library but we are not affiliated with ArchUnit.
Setup • Use Cases • Features • Why ArchUnitPython? • Sponsor • Contributing • Documentation
pip install archunitpython
Choose the import root: Pass the directory containing your top-level Python packages to
project_files(...)andmetrics(...). Ifimport taskboardrefers tosrc/taskboard/, use"src"; iftaskboard/is at the repository root, use".". This tells ArchUnitPython where to scan and how to resolve your imports. Omitting the argument uses the current working directory; it does not automatically discover asrc/layout. Details and examples.
Simply add tests to your existing test suites. The following is an example using pytest. First we ensure that we have no circular dependencies.
from archunitpython import project_files, metrics, assert_passes
def test_no_circular_dependencies():
rule = project_files("src/").should().have_no_cycles()
assert_passes(rule)
Next we ensure that our layered architecture is respected.
def test_presentation_should_not_depend_on_database():
rule = (
project_files("src/")
.in_folder("**/presentation/**")
.should_not()
.depend_on_files()
.in_folder("**/database/**")
)
assert_passes(rule)
def test_business_should_not_depend_on_database():
rule = (
project_files("src/")
.in_folder("**/business/**")
.should_not()
.depend_on_files()
.in_folder("**/database/**")
)
assert_passes(rule)
# More layers ...
Lastly we ensure that some code metric rules are met.
def test_no_large_files():
rule = metrics("src/").count().lines_of_code().should_be_below(1000)
assert_passes(rule)
def test_high_cohesion():
# LCOM metric (lack of cohesion of methods), low = high cohesion
rule = metrics("src/").lcom().lcom96b().should_be_below(0.3)
assert_passes(rule)
These tests run automatically in your testing setup, for example in your CI pipeline, so that's basically it. This setup ensures that the architectural rules you have defined are always adhered to!
# GitHub Actions
- name: Run Architecture Tests
run: pytest tests/test_architecture.py -v
You can also export dependency graph reports as CI artifacts:
from archunitpython import project_graph
def test_generate_dependency_graph_reports():
graph = project_graph("src/").titled("Application Architecture")
graph.collapse_to_folder_depth(2).export_as_html(
"reports/dependency-graph.html"
)
graph.export_as_mermaid("reports/dependency-graph.mmd")
assert graph.snapshot().summary.node_count >= 0
Installation:
pip install archunitpython
That's it. Works with pytest, unittest, or any Python testing framework.
The optional project_path argument to project_files(...), metrics(...),
project_layers(...), project_slices(...), and project_graph(...) selects the
directory to analyze. Choose the directory containing your top-level Python
packages so absolute imports can be resolved within that directory. Relative
paths are interpreted from the current working directory; omitting the argument
uses that working directory.
For example, suppose your repository contains:
my_repo/
src/
taskboard/
__init__.py
application/board_service.py
domain/task.py
tests/test_architecture.py
An import such as from taskboard.domain.task import Task names
taskboard/domain/task.py underneath src/. It does not include src in the
import name. Run your tests from my_repo/ and use:
from archunitpython import assert_passes, metrics, project_files
def test_no_cycles():
rule = project_files("src").should().have_no_cycles()
assert_passes(rule)
def test_no_large_files():
rule = metrics("src").count().lines_of_code().should_be_below(1000)
assert_passes(rule)
The directory name itself has no special meaning:
| Package location, relative to your working directory | Import name | Argument |
|---|---|---|
src/taskboard/ |
taskboard |
"src" |
taskboard/ |
taskboard |
"." |
backend/taskboard/ |
taskboard |
"backend" |
Selectors such as .in_path("**/domain/**") and .in_folder(...) narrow which
files a rule checks. They do not change the import root. For example,
project_files().in_path("src/**") can select files under src/ while still
resolving absolute imports from the repository root. Set project_files("src")
first, then add selectors if you need to narrow the rule.
With the wrong root, imports between your own modules can be classified as
external, causing cycle and internal-dependency rules to miss violations and
dependency-based metrics to report incorrect values. The root also determines
which files are included in metric measurements. ArchUnitPython does not infer a
src/ import root from pyproject.toml or your Python environment; pass it
explicitly for this layout.
https://github.com/user-attachments/assets/56f2ad65-a2e1-4965-b84d-445cf7bf4cd2
Use assert_passes() for clean assertion messages:
from archunitpython import project_files, assert_passes
def test_my_architecture():
rule = project_files("src/").should().have_no_cycles()
assert_passes(rule)
Use .check() directly and assert on the violations list:
from archunitpython import project_files
rule = project_files("src/").should().have_no_cycles()
violations = rule.check()
assert len(violations) == 0
Both assert_passes() and .check() accept configuration options:
from archunitpython import CheckOptions
options = CheckOptions(
allow_empty_tests=True, # Don't fail when no files match
clear_cache=True, # Clear the graph cache
ignore_type_checking_imports=True, # Ignore imports inside if TYPE_CHECKING
)
violations = rule.check(options)
.archignoreAdd a .archignore file to your project root to permanently exclude generated or
irrelevant files from architecture checks and file-based metrics:
# Generated code
generated/
# Migration scripts
migrations/*.py
# A single root-level file
/legacy_adapter.py
Patterns support comments, blank lines, glob syntax, root-relative paths, path
patterns, and directory patterns with a trailing /.
For straightforward shared rules, you can load a JSON config file and still run the resulting rules in your normal test suite:
{
"project_path": "src",
"rules": [
{
"name": "controllers must not use services directly",
"type": "forbidden_dependency",
"source": "**/controllers/**",
"target": "**/services/**"
},
{
"name": "source files have no cycles",
"type": "no_cycles"
}
]
}
from archunitpython import assert_passes, rules_from_config
def test_configured_architecture_rules():
for rule in rules_from_config("archunitpython.json"):
assert_passes(rule)
Supported rule types are no_cycles, forbidden_dependency, and
forbidden_external_dependency. The fluent Python API remains the primary and
most flexible interface.
.because(...)Attach a rationale to a rule so failing assertions explain why the rule exists:
rule = (
project_files("src/")
.in_folder("**/controllers/**")
.should_not()
.depend_on_files()
.in_folder("**/database/**")
.because("controllers should stay thin and delegate persistence")
)
assert_passes(rule)
When the rule fails, the rationale is included in the assertion message.
Here is an overview of common use cases.
Layered Architecture:
Enforce that higher layers don't depend on lower layers and vice versa.
Clean Architecture / Hexagonal:
Validate that domain logic doesn't depend on infrastructure.
Microservices / Modular:
Ensure services/modules don't have forbidden cross-dependencies.
Here is a repository with a fully functioning example that use