Skip to main content

Not just structurally sound. Beautiful. An architecture linter for Python projects.

Project description

Gaudi

Not just structurally sound. Beautiful.

Gaudi is an architecture linter for Python projects. It inspects your project's structural design and produces machine-readable error codes that AI coding agents (Claude, Copilot, etc.) can understand and act on.

Style linters catch syntax. Security scanners catch vulnerabilities. Gaudi catches architecture mistakes — the kind that cost you six months of refactoring when you hit 10,000 users.

What It Does

$ gaudi check .

ARCH-001 [ERROR] models.py:14 - Multi-tenant table 'donors' has no tenant isolation column
  -> Add a `tenant_id` ForeignKey and enforce row-level filtering on all queries.

IDX-001 [WARN] models.py:28 - Column 'email' is used in filter queries but has no db_index
  -> Add db_index=True or create a composite index.

SCHEMA-001 [INFO] models.py:45 - Model 'Donor' has no timestamp fields (created_at, updated_at)
  -> Add created_at and updated_at DateTimeField columns for debugging and auditing.

Found 1 error, 1 warning, 1 info across 3 files.

Why Gaudi Exists

AI coding agents are writing more and more of our code. They're great at implementing features. They're terrible at asking, "Should this be built this way?"

Gaudi is the discipline layer. It encodes architectural best practices into structured error codes that any AI agent can parse, understand, and resolve — without ambiguity, without hallucination.

For humans: Catch design mistakes before they become technical debt. For AI agents: Get structured, actionable architecture guidance instead of vague "best practices" prompts.

Installation

pip install gaudi-linter

Quick Start

# Check a project directory
gaudi check .

# Output as JSON (for AI agent consumption)
gaudi check . --format json

# Output as GitHub Actions annotations (inline on PRs)
gaudi check . --format github

# Only errors
gaudi check . --severity error --exit-code

# Check a specific file
gaudi check models.py

# Generate a Markdown report you can paste into a chat with an LLM
gaudi report . --output gaudi-report.md

LLM-collaborative workflow

Gaudi is designed to be the opening move in a developer ↔ LLM conversation, not a list of mechanical autofixes. Most rules are judgment calls — the right thing to do about a finding depends on the surrounding code and the project's priorities.

Two outputs make that conversation cheap to start:

  • gaudi check --format github emits GitHub Actions workflow commands so findings render inline on pull requests, in the Files Changed view, exactly where reviewers (and Copilot/Claude PR reviewers) expect them. See docs/llm-workflow.md for a sample workflow.
  • gaudi report . writes a Markdown report grouped by file. Each finding includes a code snippet, the rule's recommendation, and a pre-written "Discuss with LLM" prompt the developer can paste straight into Claude, ChatGPT, or any other assistant.

What It Checks

Gaudi uses deep AST analysis to inspect Django models, SQLAlchemy tables, FastAPI endpoints, Flask apps, Celery tasks, Pandas operations, Pydantic models, pytest fixtures, and DRF views.

Rule Categories

Prefix Category Examples
ARCH Architecture Tenant isolation, god models, nullable FK sprawl
IDX Indexing Missing indexes on lookup/filter fields
SCHEMA Schema Design Missing timestamps, column sprawl, type choices
SEC Security Hardcoded secrets, missing permissions, unsafe defaults
SCALE Scalability N+1 queries, missing timeouts, iterrows()
STRUCT Structure Fat files, missing app factories

Library-Specific Rules

Prefix Library Rules
DJ Django Secret key exposure, DEBUG=True, fat views
FAPI FastAPI Missing response_model, sync endpoints
SA SQLAlchemy Session leaks, default lazy loading
FLASK Flask Module-level app creation
CELERY Celery Missing retries, missing time limits
PD Pandas inplace=True, iterrows()
HTTP Requests/HTTPX Missing timeouts, no retry logic
PYD Pydantic Mutable default values
TEST pytest Complex assertions, expensive fixtures
DRF Django REST Framework Missing permissions, no throttling
PY314 Python 3.14 Removed APIs, deprecated modules

Error Code Format

Every finding follows a consistent schema:

{
  "code": "ARCH-001",
  "severity": "error",
  "category": "architecture",
  "file": "models.py",
  "line": 14,
  "message": "Multi-tenant table 'donors' has no tenant isolation column",
  "recommendation": "Add a `tenant_id` ForeignKey and enforce row-level filtering."
}

Writing Custom Rules

from gaudi import Rule, Severity, Category

class CheckTenantIsolation(Rule):
    code = "ARCH-001"
    severity = Severity.ERROR
    category = Category.ARCHITECTURE
    message_template = "Multi-tenant table '{table}' has no tenant isolation column"

    def check(self, context):
        for model in context.models:
            if not model.has_column("tenant_id"):
                yield self.finding(
                    file=model.source_file,
                    line=model.source_line,
                    table=model.name,
                )

AI Agent Integration

Gaudi's JSON output is designed to be consumed by AI coding agents. Add it to your Claude Code workflow, your CI pipeline, or your custom agent loop.

# Use in CI
gaudi check . --format json --severity error --exit-code

# Use in a pre-commit hook
gaudi check . --severity error --exit-code

Prompt Fragment for AI Agents

Include this in your system prompt or project instructions:

Before implementing any database schema changes, run `gaudi check .` and resolve
all ERROR-level findings. WARN-level findings should be addressed unless you can
document a specific reason to override them.

Configuration

Create a gaudi.toml in your project root:

[gaudi]
severity = "warn"          # minimum severity to report
exclude = ["migrations/"]  # paths to skip

[gaudi.rules]
"ARCH-001" = "error"       # override severity
"IDX-003" = "off"          # disable a rule entirely

[philosophy]
school = "convention"      # infer with: gaudi philosophy .

Inline suppression

Suppress findings on a single line with # noqa:

SECRET_KEY = "test-only"  # noqa: DJ-SEC-001
urlpatterns = [...]       # noqa

# noqa (bare) suppresses all findings on that line. # noqa: CODE1, CODE2 suppresses only the listed rules.

Philosophy inference

Gaudi can recommend which architectural school best matches your project:

gaudi philosophy .

This analyzes your dependencies and project structure to suggest a school (e.g., convention for Django projects, data-oriented for NumPy pipelines).

Known Limitations (v0.1 alpha)

  • Some library-specific rules use regex on raw text instead of full AST analysis, which can produce false positives.

These are tracked in the issue tracker.

Philosophy

Gaudi is named after Antoni Gaudi, the architect of La Sagrada Familia. He built hanging chain models — inverted catenary arches — to test structural integrity before laying a single stone. Construction on his masterwork began in 1882 and continues today, still following his structural principles.

This tool embodies that philosophy: validate the architecture before you build. The earlier you catch a structural flaw, the less it costs to fix. And with AI agents writing increasingly large portions of our codebases, we need automated architectural discipline more than ever.

The first principles that govern Gaudi — fourteen numbered claims in three pillars (Truthfulness, Economy, Cost-honesty) — are written down in docs/principles.md. They are intended to be portable: any project can adopt them as the doctrine its design decisions appeal to.

Contributing

Contributions welcome. The highest-impact contributions right now:

  1. New rules — especially Django, FastAPI, and SQLAlchemy patterns
  2. Code smell detection — implementing Fowler's 24 code smells programmatically
  3. CI/CD integration examples — GitHub Actions, GitLab CI, etc.

See CONTRIBUTING.md for details.

License

MIT License. See LICENSE for details.


Built by Nathan Krupa — fundraiser, writer, and reluctant architect.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gaudi_linter-0.1.2.tar.gz (130.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gaudi_linter-0.1.2-py3-none-any.whl (146.2 kB view details)

Uploaded Python 3

File details

Details for the file gaudi_linter-0.1.2.tar.gz.

File metadata

  • Download URL: gaudi_linter-0.1.2.tar.gz
  • Upload date:
  • Size: 130.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for gaudi_linter-0.1.2.tar.gz
Algorithm Hash digest
SHA256 9260dfdfd0b52584d6487674c7fa1bcbbeb824786d3aa2b705c88fe773cc623c
MD5 e52ab08a60b8b6d80e4d6ce9a8b4820d
BLAKE2b-256 f36ae3cd8998072068b699885f08ec6f3d67c028bcdd0ecb50018999cea844af

See more details on using hashes here.

File details

Details for the file gaudi_linter-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: gaudi_linter-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 146.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for gaudi_linter-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 df083128e537f32013a3a32c56dcee444949115a46c2d26e184a47ed2fdc1c62
MD5 55469063ba032f7a2cb1097dcd867155
BLAKE2b-256 dca473a800a4c70466c8acc8943bef34d16eefaf7e8cab7a6a81c0752552a206

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page