Introduction
The Problem
A route handler loses its middleware registration during a refactor. Now /admin/users serves data without checking credentials. Your unit tests pass. Your linter is silent. Nobody notices until a security audit three months later.
This class of bug -- silent property violations -- is surprisingly common. Authentication gaps, broken architectural boundaries, hardcoded secrets, missing error handling. They slip through because no single tool catches them:
- Unit tests verify individual functions, not cross-cutting properties
- Linters match syntax patterns, but cannot reason about behavior across files
- Code review catches them sometimes, but reviewers get tired and context-switch
What Axiomatic Does
Axiomatic lets you write invariants in plain English, and an LLM agent verifies them against your source code.
# axiomatic/auth-required.yml
condition: >
All route handlers that access user data must require authentication.
Public endpoints (health checks, login, registration) are exempt.
on:
- "app/api/**/*.ts"
severity: error
tags: [security]$ axm run
auth-required ✓ pass (0.95 confidence, $0.03)
Checked 14 route handlers in app/api/.
All mutation endpoints use getServerSession() or withAuth().When someone introduces a violation:
$ axm run
auth-required ✗ fail (0.92 confidence, $0.04)
Violations:
app/api/users/delete/route.ts:12 — DELETE handler performs
mutation without session checkThink of it as a senior engineer reviewing your codebase against a checklist -- except it runs in CI, never gets tired, and checks every file on every commit.
What Makes It Different
Axiomatic fills a gap that existing tools cannot:
| Tool | Strength | Limitation |
|---|---|---|
| Linters (ESLint, golangci-lint) | Fast syntactic patterns | Cannot reason across files or about behavior |
| ArchUnit | Dependency rules in Java/C# | Language-specific, limited to import graphs |
| Semgrep | Structural AST matching | Matches patterns, not behavioral intent |
| Unit tests | Individual function correctness | Cannot verify cross-cutting properties |
| Code review | Catches nuanced issues | Inconsistent, expensive, doesn't scale |
| Axiomatic | Cross-cutting behavioral properties | LLM-based (costs $0.01--0.05/test with caching) |
Axiomatic is best for properties that span multiple files and require understanding intent: authentication enforcement, architectural boundaries, security invariants, error handling consistency.
How It Works
- You write conditions in plain English inside YAML files in your
axiomatic/directory. - When you run
axm run, the agent reads each condition and uses sandboxed tools (read_file,grep,glob,list_dir) to explore your codebase. - The agent reasons about what it finds, iterating through files until it has enough evidence (typically 3--10 tool-call rounds).
- It returns a verdict: pass or fail, with confidence and a list of violations pointing to specific files and lines.
Results are cached against file content hashes. Unchanged code is never re-analyzed, keeping costs near zero for subsequent runs.
Quick Start
# Install
npm install -g @exalto/axiomatic
# Set up your API key
export ANTHROPIC_API_KEY=sk-ant-...
# Initialize and run your first test
axm init
axm runA typical test costs $0.01--0.05 with Claude Haiku. Caching means you only pay when code actually changes.
Real-World Examples
Security: No Hardcoded Secrets
condition: >
No source files should contain hardcoded secrets, API keys, passwords,
or tokens. Patterns like "sk-", "ghp_", "password=", and Base64-encoded
credentials should not appear in source. Environment variable references
(process.env.X, os.environ) are acceptable.
on:
- "src/**/*.{ts,tsx,js,jsx}"
severity: error
tags: [security]Architecture: Database Layer Boundary
condition: >
No files outside of src/data/ should import from the Prisma client
directly or use prisma.* calls. All database access must go through
the repository functions exported from src/data/.
on:
- "src/**/*.ts"
severity: error
tags: [architecture]Error Handling: Meaningful Error Context
condition: >
Error messages returned to users should include enough context to
diagnose where the problem originated. Bare "Something went wrong"
or generic error strings without request-specific details are not
acceptable in production error handlers.
on:
- "src/api/**/*.ts"
severity: warning
tags: [code-quality]Next Steps
- Installation -- install Axiomatic and configure your API key
- First Test -- write and run your first test in under five minutes
- Writing Tests -- learn to write effective conditions, avoid common pitfalls, and see examples across languages
- Configuration -- set up providers, models, and caching
- CI/CD Integration -- run Axiomatic in GitHub Actions, GitLab CI, and other pipelines
- CLI Reference -- complete command and flag reference