> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stratalint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Strata

> Keeping Python repos from turning into spaghetti.

**Most linters catch bad code inside files. Strata catches architectural drift:
code crossing the wrong boundary, living in the wrong module, or growing into the
wrong shape.**

A repo small enough to fit in one file is fine. The trouble starts as it grows:
code moves, teams change, lessons get forgotten, and the mental map decays.

Tests help preserve behavior, but nothing preserves the *shape* of the repo: what
belongs where, which layer owns what, which modules are public surfaces. That
consistency usually lives in code review and in people's heads.

Strata makes it executable:

* Tests codify behavioral expectations.
* Types codify interface expectations.
* **Strata codifies architectural expectations.**

A prompt or design doc can describe the intended structure. Only an executable rule
can tell you, deterministically and every time, when the repo has drifted from it.

## What Strata checks

Strata is an architecture linter for Python repos. It analyzes your source and
reports **faults**, the places where the code has broken away from the architecture
you declared.

<CardGroup cols={2}>
  <Card title="Layers and boundaries" icon="layer-group">
    Which modules and packages may import which. Absolute imports only, no star
    imports, no reaching into a sibling's internals, no importing from tooling at
    runtime.
  </Card>

  <Card title="Module roles" icon="folder-tree">
    What each kind of file may contain and where it may live. `models.py` holds
    models, `types.py` holds types, `main/` holds orchestrators, `helpers/` holds
    phases, `classes/` holds one class each.
  </Card>

  <Card title="Function shape" icon="ruler-combined">
    Size caps on orchestrators, explicit dataflow, keyword-only arguments,
    mutate-only-if-returned, and no hidden control flow buried in comprehensions.
  </Card>

  <Card title="Naming contracts" icon="signature">
    Names that must mean what they claim. A `validate_*` or `enforce_*` function
    raises or passes, so it must not quietly return a value like a query.
  </Card>
</CardGroup>

It also enforces test-suite conventions (mirrored layout, given-when-then naming,
dataclass-backed parametrization) and annotation conventions (annotate every
parameter, return, and local) in the scopes where those apply. See
[Rule families](/concepts/rule-families) for the full set.

Strata ships a **coherent default architecture**, not a blank rule language. You
adopt it and get a serious starting structure, then disable rules, tune thresholds,
or add your own rules deliberately once you know what you are changing.

Concretely, the default lays out code as domains and subdomains built from a small
set of roles:

```text theme={null}
src/my_package/
└── config/                  # a domain
    └── core/                # a subdomain
        ├── main/            # orchestrators and the public entry surface
        ├── helpers/         # phase functions
        ├── classes/         # one class per module
        ├── models.py        # data models
        ├── types.py         # type declarations
        ├── constants.py
        └── exceptions.py
```

That is the shipped default. See the [architecture model](/concepts/architecture-model)
for the full layout and how to adapt it.

## Enforce it, then see it

Because Strata enforces the structure, it can also render it meaningfully.

* [`strata check`](/cli/check) stops the repo from losing its shape.
* [`strata map`](/cli/map) helps you see that shape again, as a deterministic
  downstream call tree with clickable `path:line` locations.

<Frame caption="strata map run_map">
  <img className="block dark:hidden" src="https://mintcdn.com/strata-docs/L5LQrrH_M8nFwgKy/strata_map_example_light_white.png?fit=max&auto=format&n=L5LQrrH_M8nFwgKy&q=85&s=a9aeb441512a1e2b8bd41a2da86c4d66" alt="A strata map call tree for run_map, showing resolved project calls with path and line locations, an unresolved parameter call, depth-limit markers, and a cycle marker." width="1585" height="992" data-path="strata_map_example_light_white.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/strata-docs/L5LQrrH_M8nFwgKy/strata_map_example.png?fit=max&auto=format&n=L5LQrrH_M8nFwgKy&q=85&s=29245c5b44fddddcc7b77c23cfe693f1" alt="A strata map call tree for run_map, showing resolved project calls with path and line locations, an unresolved parameter call, depth-limit markers, and a cycle marker." width="1586" height="992" data-path="strata_map_example.png" />
</Frame>

The map is useful precisely because it is not guessing at an arbitrary repo. Check
enforces layers, roles, and public surfaces first; map then renders the structure
the code is required to expose. Useful lineage requires declared structure.

## Built for the LLM era

This matters even more with LLMs in the loop. Models are good at local edits but
not at preserving architecture over time. They tend to:

* inline too much and grow functions;
* smear state across boundaries;
* add imports through the wrong layer;
* satisfy the letter of a vague rule while violating its intent.

If you have to remind an agent of the same architectural rule repeatedly, that rule
should probably be executable. Strata's defaults are shaped around exactly these
failure modes.

[`strata skills`](/cli/skills) generates agent guidance straight from your active
ruleset, so the instructions your agents follow cannot drift from the rules your CI
enforces.

## Battle-tested

Strata is not a tool built for an imagined problem. Earlier versions of these checks
ran unnamed for months, first in workplace codebases and then in
[sqlbuild](https://github.com/chio-labs/sqlbuild), a 100k+ line Python project.
Strata turns that hard-won structure into a reusable default. The default is
opinionated; the point is to give you a serious starting structure instead of a
blank page, then let you adapt it once you know what you are changing.

## Get started

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Install Strata, configure a repo, and read your first faults in a few minutes.
  </Card>

  <Card title="Philosophy" icon="compass" href="/philosophy">
    Why Strata is strict by default, and how deliberate deviation works.
  </Card>

  <Card title="Architecture model" icon="sitemap" href="/concepts/architecture-model">
    Scopes, roles, and the default module layout Strata enforces.
  </Card>

  <Card title="Adopting Strata" icon="seedling" href="/adoption">
    Rolling out on a new repo versus an existing one.
  </Card>

  <Card title="Custom rules" icon="code" href="/concepts/custom-rules">
    Write your own rules in Python with the same context the core rules use.
  </Card>
</CardGroup>

<Note>
  The PyPI distribution is `stratalint`; the command is `strata`. Install with
  `pip install stratalint` and run `strata`. Strata is functional and self-hosting,
  but pre-release.
</Note>
