Comply
Enforce your team's conventions — automatically, before every merge.
Comply reads a simple rules file, looks at your git diff, and asks an LLM to check each rule. You get a clear PASS / WARN / FAIL report in your terminal.
$ comply check
Comply — checking 4 rules against current diff
✅ PASS tests-required No new source files missing tests
⚠️ WARN auth-security-review auth/login.py modified — needs security review
❌ FAIL migration-docs migrations/0012.py has no rollback plan
⚠️ WARN env-vars-documented JWT_SECRET not in .env.example
1 failure, 2 warnings. Fix before merging.
How it works
your git diff
│
▼
.comply.yml ──► LLM (OpenRouter) ──► PASS / WARN / FAIL per rule
- You write rules in plain English inside
.comply.yml comply checkgets the current staged diff (or last commit)- Each rule is sent to an LLM alongside the diff
- Results are printed as a formatted checklist
Install
Requires Python 3.10+
git clone https://github.com/Lameda12/Comply.git
cd Comply
pip install -e .
Verify it works:
comply --help
Quick start
1. Get an API key
Sign up at openrouter.ai → go to Keys → create one.
export OPENROUTER_API_KEY=sk-or-your-key-here
Add this to your
~/.zshrcor~/.bashrcso you don't have to set it every time.
2. Go to your project
cd /path/to/your/project
git init # if not already a git repo
3. Create your rules file
comply init
This writes a .comply.yml with 4 starter rules. Open it and edit to match your team's conventions.
4. Make some changes and check them
# edit some files...
git add .
comply check
That's it.
Writing rules
Rules live in .comply.yml. There are three rule types:
llm — plain-English instructions (default)
rules:
- id: tests-required
type: llm
description: Every new Python file needs a test file
prompt: |
Look at the diff. If any new .py source files are added
(not in tests/ or test_*.py), check whether a corresponding
test file also appears in the diff.
Return PASS if all new files have tests, WARN if some are missing.
| Field | What it does |
|---|---|
id |
Short name shown in output |
description |
Human-readable summary |
prompt |
Plain-English instruction sent to the LLM |
regex — instant pattern matching, no LLM call
- id: no-print-statements
type: regex
description: No print() calls in production code
pattern: '^\+.*\bprint\s*\('
on_match: WARN # status when pattern is found (default: FAIL)
on_no_match: PASS # status when not found (default: PASS)
Fast and free — runs entirely locally against the raw diff text.
ast — Python static analysis, no LLM call
- id: no-bare-except
type: ast
description: No bare except clauses
check: no-bare-except
Parses changed Python files with Python's built-in ast module.
check value |
What it enforces |
|---|---|
docstrings |
All new functions/classes have docstrings |
type-hints |
All new functions have type annotations |
no-bare-except |
No bare except: — must catch a specific exception |
no-globals |
No global statements |
depends_on — rule chaining
- id: migration-exists
type: llm
prompt: "Return WARN if any migration files are added, else PASS."
...
- id: migration-rollback
type: llm
depends_on: migration-exists # ← only runs if migration-exists returned WARN/FAIL
prompt: "Check that migrations have a downgrade() function."
...
If the dependency returned PASS, the dependent rule shows SKIP in output. This avoids false positives when there's nothing to check.
Starter rules (from comply init)
| Rule | Type | What it checks |
|---|---|---|
tests-required |
llm | New source files have matching test files |
migration-exists |
llm | Detects new migration files |
migration-rollback |
llm | Checks rollback — skipped if no migrations found |
env-vars-documented |
llm | New env vars appear in .env.example |
no-print-statements |
regex | No print() calls in production code |
no-hardcoded-secrets |
regex | No hardcoded passwords/tokens |
no-todo-in-new-code |
regex | No new TODO/FIXME comments |
functions-need-docstrings |
ast | All new functions/classes have docstrings |
no-bare-except |
ast | No bare except: handlers |
Options
# Use a different config file
comply check --config path/to/rules.yml
# Use a different LLM model
export COMPLY_MODEL=openai/gpt-4o
comply check
Default model: qwen/qwen-2.5-72b-instruct — fast and cheap.
Any model on openrouter.ai/models works.
Exit codes
| Code | Meaning |
|---|---|
0 |
All rules passed |
1 |
One or more FAIL or WARN |
This makes it easy to use in CI:
# .github/workflows/comply.yml
- name: Run Comply
run: comply check
env:
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
Project structure
comply/
├── comply/
│ ├── cli.py # comply init + comply check commands
│ └── checker.py # LLM call + rule evaluation (< 100 lines)
├── templates/
│ └── default.yml # starter rules written by comply init
└── pyproject.toml
MCP Server (Phase 2)
Comply ships a built-in MCP server so Claude Desktop or Cursor can call comply_check directly during a conversation — no terminal needed.
What the tool does
comply_check(repo_path=".", config_path=".comply.yml")
Returns structured JSON:
{
"results": [
{ "id": "tests-required", "status": "WARN", "reason": "..." },
{ "id": "auth-security-review", "status": "PASS", "reason": "..." }
],
"summary": {
"total": 4, "passed": 3, "warnings": 1, "failures": 0,
"verdict": "WARN"
}
}
Connect to Claude Desktop
Find your config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
Add this block (replace the path with your actual
comply-mcplocation):
{
"mcpServers": {
"comply": {
"command": "/Library/Frameworks/Python.framework/Versions/3.13/bin/comply-mcp",
"env": {
"OPENROUTER_API_KEY": "sk-or-your-key-here"
}
}
}
}
Find your
comply-mcppath with:which comply-mcp
Restart Claude Desktop. You'll see comply in the tools list.
In any conversation, ask Claude:
"Check my repo at /path/to/project for convention violations"
Claude will call comply_check and show you the results inline.
Connect to Cursor
Add to your .cursor/mcp.json or Cursor MCP settings:
{
"comply": {
"command": "/Library/Frameworks/Python.framework/Versions/3.13/bin/comply-mcp",
"env": {
"OPENROUTER_API_KEY": "sk-or-your-key-here"
}
}
}
Roadmap
- [x] Phase 1 — Core CLI (
comply init,comply check) - [x] Phase 2 — MCP server (
comply-mcp, works in Claude Desktop + Cursor) - [x] Phase 3 — Rule types:
llm,regex,ast+depends_onchaining
License
MIT
Log in or sign up for Devpost to join the conversation.