An agent built on the Claude Agent SDK that checks a codebase against defined architecture rules and finds violations (drift).
Supports: TypeScript/JS, Kotlin/Java, Dart/Flutter, Python, Go, Swift, Objective-C, Rust.
| Violation type | Severity | Example |
|---|---|---|
| Layer violation | 🔴 CRITICAL | domain/ imports from database/ |
| Forbidden dependency | 🔴 CRITICAL | controller → repository directly |
| Circular dependency | 🟠 HIGH | A → B → C → A |
| Naming convention | 🟡 MEDIUM | UserHelper.py instead of UserService.py |
| Threshold exceeded | 🟡 MEDIUM | File with 20+ imports |
| Orphan module | 🔵 LOW | Module with no incoming dependencies |
# Simple mode — single agent, suitable for projects < 50 files
python arch_drift_agent.py --project /path/to/project --mode simple
# Multi-agent — orchestrator + parallel subagents, for large projects
python arch_drift_agent.py --project /path/to/project --mode multi
# Advanced — custom tools (fast deterministic parsing, DFS for cycles)
python arch_drift_agent.py --project /path/to/project --mode advanced--project Project root directory (default: .)
--rules Path to arch_rules.yaml (default: ./arch_rules.yaml)
--report Output report path (default: ./arch_drift_report.md)
--model Claude model: sonnet / opus / haiku (default: sonnet)
--mode simple | multi | advanced (default: simple)
For humans — use
simpleormulti: the agent explains its reasoning at every step, making it easy to follow and debug. For AI agents / CI — useadvanced: deterministic tools replace LLM for parsing and cycle detection, which is faster, cheaper, and more predictable.
One agent reads the rules, scans files, detects violations, and writes the report. Best for small projects. Cost: ~$0.05–0.20.
The orchestrator splits the project into modules and spawns parallel subagents for scanning. Faster for large projects. Cost: ~$0.10–0.50.
Orchestrator
├── module-scanner (spawned N times in parallel, one per module)
├── violation-checker
└── report-generator
Imports are parsed deterministically with regex (no LLM). Cycles are detected with DFS (no LLM). LLM is used only for analysis and report generation — faster, cheaper, more reliable. Cost: ~$0.03–0.10.
Custom tools exposed via an embedded MCP server:
parse_imports— extracts import statements from a source file, returns structured JSONfind_circular_deps— runs DFS on a dependency graph, returns all cycles
Hooks:
PreToolUse— logs every tool invocationPostToolUse— validates that tool results are valid JSON
Define your architecture constraints in a YAML file. See rules/example.arch_rules.yaml for a full Flutter/Clean Architecture example.
project:
name: "my-app"
root: "lib"
language: "dart"
layers:
- name: domain
packages: ["lib/features/*/domain"]
allowed_dependencies: [] # domain depends on nothing
- name: data
packages: ["lib/features/*/data"]
allowed_dependencies: [domain, core]
forbidden_dependencies:
- from: "lib/features/*/domain"
to: "lib/features/*/data"
reason: "Domain must not depend on the data layer (DIP)"
circular_dependencies:
max_depth: 0 # strictly forbidden
thresholds:
max_file_imports: 15
max_file_lines: 500# .github/workflows/arch-drift.yml
name: Architecture Drift Check
on: [pull_request]
jobs:
arch-drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install claude-agent-sdk pyyaml
- name: Check architecture drift
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
python arch_drift_agent.py \
--project . \
--mode advanced \
--model haiku \
--report arch_report.md
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: arch-drift-report
path: arch_report.md
- name: Comment PR
uses: marocchino/sticky-pull-request-comment@v2
with:
path: arch_report.md# Architecture Drift Report
**Project:** my-backend-service
**Date:** 2026-02-21
**Total violations:** 7
## Summary
| Severity | Count |
|-------------|-------|
| 🔴 CRITICAL | 2 |
| 🟠 HIGH | 1 |
| 🟡 MEDIUM | 3 |
| 🔵 LOW | 1 |
## Violations
### 🔴 [CRITICAL] Layer Violation
**File:** src/domain/user.py:15
**Rule:** Domain layer must not depend on infrastructure
**Import:** `from src.database.connection import get_db`
**Fix:** Use repository interface defined in domain layer
### 🟠 [HIGH] Circular Dependency
**Cycle:** src/services → src/utils → src/services
**Fix:** Extract shared code into a common module
## Dependency Graph
\```mermaid
graph LR
api --> services
services --> domain
services --> repositories
repositories --> database
domain -.->|❌ VIOLATION| database
services <-->|🔄 CYCLE| utils
\```
## Metrics
| Module | Fan-in | Fan-out | Files |
|------------|--------|---------|-------|
| domain | 8 | 0 | 12 |
| services | 5 | 4 | 8 |
| database | 3 | 1 | 5 |Add custom checks via tools in run_advanced_agent(). For example: verify that all public APIs are documented, or that database migrations match the models.
This tool uses AI-based analysis. It is provided "as is" without warranties of any kind. Users are responsible for any architectural decisions or changes made based on the agent's output.