Boundary enforcement for AI coding agents: plain-YAML module contracts compiled into CLAUDE.md, hooks, and CI checks that keep agents inside your architecture.
Project description
ANMA
Boundary enforcement for AI coding agents. ANMA turns plain-YAML module
contracts into the CLAUDE.md, hooks, and checks that keep Claude Code inside
your architecture — and it measurably works where it matters most.
In a controlled benchmark (Python), a cheaper/faster model (Claude Haiku 4.5)
violated a declared module boundary in 13 of 19 runs of a plain repo. With
ANMA, across 20 runs of the same task it violated it 0 times (Fisher's exact
p < 0.0001). See docs/BENCHMARKS.md for the full study, including the
honest part: a frontier model (Opus 4.8) respected the boundary on its own, so
ANMA's value is insurance for running cheaper agents plus a CI/governance
guarantee — not making a frontier model smarter.
Languages: Python, Go, and TypeScript (language: in the root anma.yaml,
one per project). Go and TypeScript enforce module→module dependencies; interface
(public:) enforcement is Python-only today. The Go/TS adapters are validated
(anma check + the hook detect and block real cross-module violations), but
whether ANMA changes model behavior in Go/TS is not established — the benchmark
above is Python, and the Go/TS live run is a null/underpowered result that does not
transfer the Python numbers. Details: CONCEPTS § Languages.
What it does
You declare each module's public interface and what it may depend on. anma sync
compiles that into everything else, so the architecture the agent reads can never
drift from the rules CI enforces:
anma.yaml project config (schema_version, source_roots)
src/domains/billing/
anma.yaml the module contract — see docs/CONCEPTS.md for all fields
CLAUDE.md (generated) loads when Claude opens billing/
CLAUDE.md (generated) architecture map, between markers
.claude/rules/boundaries.md (generated) always-loaded imperative
.claude/hooks/anma_pretooluse.py (generated) blocks a boundary-breaking edit (exit 2)
tach.toml (generated) engine config (Go: .go-arch-lint.yml; TS: .dependency-cruiser.cjs)
.github/workflows/anma.yml (generated) CI: drift check + boundary check
DECISIONS.md append-only: why each boundary exists
Quickstart (60 seconds)
pip install anma[tach] # tach backend recommended; works without it too
anma init # scaffolds contracts + a worked accounts/billing example
anma sync # generates CLAUDE.md, nested docs, hooks, tach.toml, CI
anma check # ✓ boundaries respected
For Go or TypeScript, scaffold with anma init --language go /
anma init --language typescript (the external backends — go-arch-lint,
dependency-cruiser — are optional; a builtin scanner is the zero-dep fallback).
Full walkthrough: docs/QUICKSTART.md.
Commands
anma init # scaffold contracts + a worked example
anma sync # regenerate all artifacts from contracts
anma sync --check # CI guard: fail if generated artifacts drifted from contracts
anma check # enforce boundaries (hook / pre-commit / CI)
anma check --warn # report violations but exit 0 (incremental adoption)
anma check --json # machine-readable output for pipelines
Exit codes: 0 ok · 1 violations, contract errors, or drift.
Two layers: guidance and enforcement
ANMA works at two levels, and the benchmark shows they play different roles:
- Guidance — the generated root and per-module
CLAUDE.mdand.claude/rulesput your architecture in the agent's context. This is what drove the 68% → 0 result: the model was steered to the correct design and didn't attempt a bad edit. - Enforcement — the
PreToolUsehook judges the proposed edit and returns exit 2 to block any new disallowed import before it lands; the same check runs at pre-commit and in CI. This is the guarantee that holds for the edits guidance doesn't catch, and regardless of which model or human wrote the diff.
The enforcement hook is verified to fire (feed it a forbidden edit → exit 2); in
the benchmark it never needed to, because guidance pre-empted every bad edit. Both
matter; see the benchmarks for exactly what each one is shown to do.
Who it's for
- Teams running cheaper or faster agents (cost-sensitive pipelines, bulk tasks, non-frontier or non-Claude models) that don't reliably respect an architecture on their own — this is where ANMA's steering is decisive.
- Anyone who wants an enforced architecture: a guarantee in CI/pre-commit that module boundaries hold no matter who or what wrote the change.
- Teams that want architecture as governance: declared interfaces, ownership → CODEOWNERS, and docs that can't silently drift from the rules.
If you only ever drive a frontier model on small, well-described tasks, ANMA may add turns without changing outcomes — and the benchmarks say so plainly.
Lightweight by design
~800 lines, no runtime, no DSL, one small dependency (PyYAML) — the builtin
engine needs nothing more, and the faster external backends (tach for Python,
go-arch-lint for Go, dependency-cruiser for TypeScript) are all optional. A
security team can read the whole tool in an afternoon.
Enterprise
- Drift detection —
anma sync --checkfails CI if generated docs/config fall out of sync with the contracts. - Incremental adoption —
anma check --warnand per-moduledeprecated_depslet a large codebase adopt without a red build on day one. - Governance —
owners:per module generatesCODEOWNERS;source_roots:supports monorepos. - Supply chain — signed releases (PyPI Trusted Publishing + provenance + SBOM),
pip-auditin CI, Apache-2.0. See SECURITY.md.
Documentation
- docs/QUICKSTART.md — install to first blocked edit
- docs/CONCEPTS.md — the model, the contract schema reference, generated artifacts, the engine
- docs/BENCHMARKS.md — the with/without study, methodology, and honest limits
- CONTRIBUTING.md — dev setup, tests, the dogfood, the schema-stability rule
- SECURITY.md · RELEASE.md · CHANGELOG.md
Apache-2.0 · ANMA Labs LLC
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 anma-0.7.0.tar.gz.
File metadata
- Download URL: anma-0.7.0.tar.gz
- Upload date:
- Size: 74.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ee706ec45fa67e09656a0a881523a333e37b0b043f60725cdd6a01c0fa88fb4
|
|
| MD5 |
23d2cec692d079dcf411788e9b77ed2e
|
|
| BLAKE2b-256 |
f638c89223241b56e19219303dd67f8954cc573530e8d511896a4c3b441bdbb1
|
Provenance
The following attestation bundles were made for anma-0.7.0.tar.gz:
Publisher:
release.yml on anma-labs/anma
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
anma-0.7.0.tar.gz -
Subject digest:
7ee706ec45fa67e09656a0a881523a333e37b0b043f60725cdd6a01c0fa88fb4 - Sigstore transparency entry: 1747359167
- Sigstore integration time:
-
Permalink:
anma-labs/anma@72fd34d9d34bbcfabc454501186c94e8f7ac7aab -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/anma-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@72fd34d9d34bbcfabc454501186c94e8f7ac7aab -
Trigger Event:
release
-
Statement type:
File details
Details for the file anma-0.7.0-py3-none-any.whl.
File metadata
- Download URL: anma-0.7.0-py3-none-any.whl
- Upload date:
- Size: 36.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e2dc1141256e465619d93834c60961f80413f7428183e42b9141d5ad772238f
|
|
| MD5 |
5bda8c3bc7748c2e71d7593a853e18a6
|
|
| BLAKE2b-256 |
b2433f9f075492c36974592bac823fd31dd1f13eaab39854902b01ea33e29e98
|
Provenance
The following attestation bundles were made for anma-0.7.0-py3-none-any.whl:
Publisher:
release.yml on anma-labs/anma
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
anma-0.7.0-py3-none-any.whl -
Subject digest:
8e2dc1141256e465619d93834c60961f80413f7428183e42b9141d5ad772238f - Sigstore transparency entry: 1747359288
- Sigstore integration time:
-
Permalink:
anma-labs/anma@72fd34d9d34bbcfabc454501186c94e8f7ac7aab -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/anma-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@72fd34d9d34bbcfabc454501186c94e8f7ac7aab -
Trigger Event:
release
-
Statement type: