Compile CLAUDE.md into enforceable repo policy for Claude Code
Project description
claude-md-compiler
Compile CLAUDE.md into a versioned policy lockfile and enforce it against file edits, commands, and git diffs.
What It Does
cldc is a Python CLI that compiles repository policy from CLAUDE.md, .claude-compiler.yaml, and policies/*.yml into a versioned lockfile, then checks file edits, commands, and git diffs against that policy.
Why It Exists
CLAUDE.md is usually advisory text. cldc turns repo rules into a deterministic artifact that local runs, CI, and review tooling can enforce the same way every time.
Who It Is For
- Developers using agentic coding tools in real repositories.
- Platform or infra teams that want repo-level guardrails.
- Maintainers who want explainable, local-first policy checks instead of hidden heuristics.
Install
cldc requires Python 3.11+.
# persistent install
uv tool install claude-md-compiler
# or
pipx install claude-md-compiler
# one-shot
uvx --from claude-md-compiler cldc --version
For local development inside this repository, use the development workflow instead of installing the project into itself.
Quickstart
# 1. Compile policy into .claude/policy.lock.json
cldc compile .
# 2. Check a change directly
cldc check . --write src/main.py --command "pytest -q"
# 3. Explain or save the report
cldc explain . --write src/main.py --format markdown
# 4. Generate a remediation plan
cldc fix . --write src/main.py --format markdown
# 5. Gate a staged diff or PR range
cldc ci . --staged
cldc ci . --base origin/main --head HEAD
Exit codes:
0: clean or non-blocking result1: runtime or input error2: blocking policy violations
Every command supports --json, and every command can also persist its output with --output <file>.
How Policy Is Authored
Sources are discovered from the repo root or any nested path inside the repo. Merge order is deterministic:
CLAUDE.md- inline fenced
```cldcblocks insideCLAUDE.md .claude-compiler.yamlor.claude-compiler.yml- bundled presets referenced from
.claude-compiler.yamlviaextends: policies/*.ymlandpolicies/*.yaml
Example:
# CLAUDE.md
```cldc
rules:
- id: generated-lock
kind: deny_write
mode: block
paths: ["generated/**"]
message: Generated files must not be edited by hand.
```
# .claude-compiler.yaml
default_mode: warn
extends:
- default # bundled preset: generated/** is read-only, lockfile-follows-manifest
- strict # bundled preset: tests-follow-source, arch-read, ci-green claim
rules:
- id: keep-tests-in-sync
kind: couple_change
paths: ["src/**"]
when_paths: ["tests/**"]
message: Update tests when source changes.
Preset Policy Packs
cldc ships with opinionated rule packs you can merge into your repo policy via extends: in .claude-compiler.yaml.
| Preset | What it does |
|---|---|
default |
Blocks writes to generated/**, dist/**, build/**; warns when a dependency manifest changes without a matching install/sync/tidy command. |
strict |
Requires tests to move with source, requires an architecture/RFC read before editing src/**, and requires a ci-green claim to ship src/** changes. |
docs-sync |
Couples public CLI / runtime / API changes with README/docs updates, and couples version bumps with changelog entries. |
Inspect the bundled packs:
cldc preset list
cldc preset show default
cldc preset show strict --json
Use them by listing one or more names under extends::
# .claude-compiler.yaml
extends:
- default
- docs-sync
Preset rules merge alongside your own rules. Duplicate rule IDs fail the compile, so pick unique IDs for your own rules.
Rule Model
| Kind | Meaning |
|---|---|
deny_write |
Paths matching paths must not be written. |
require_read |
Writing paths requires a prior read matching before_paths. |
require_command |
Writing when_paths requires at least one listed command to run. |
couple_change |
Writing paths requires a companion write matching when_paths. |
require_claim |
Writing when_paths requires at least one listed policy claims to be asserted. |
Example require_claim rule — block edits to src/** until a reviewer asserts qa-reviewed:
rules:
- id: qa-sign-off
kind: require_claim
mode: block
when_paths: ["src/**"]
claims: ["qa-reviewed", "security-reviewed"]
message: QA or security must sign off before editing source.
| Mode | Meaning |
|---|---|
observe |
Record the result but do not block. |
warn |
Report the result but do not block. |
block |
Report the result and exit 2. |
fix |
Report the result as blocking and include remediation guidance. |
Evidence Inputs
Runtime commands accept evidence three ways:
# direct flags
cldc check . --read docs/spec.md --write src/main.py --command "pytest -q" --claim qa-reviewed
# JSON file
cldc check . --events-file .cldc-events.json --json
# stdin JSON
cat .cldc-events.json | cldc check . --stdin-json --json
Use --claim once per asserted claim; claims satisfy require_claim rules in the compiled policy.
Accepted payload shape:
{
"read_paths": ["docs/spec.md"],
"write_paths": ["src/main.py"],
"commands": ["pytest -q"],
"claims": ["qa-reviewed"],
"events": [
{"kind": "read", "path": "docs/spec.md"},
{"kind": "write", "path": "src/main.py"},
{"kind": "command", "command": "pytest -q"},
{"kind": "claim", "claim": "qa-reviewed"}
]
}
Saved report workflow:
cldc check . --write src/main.py --json --output artifacts/policy-report.json
cldc explain . --report-file artifacts/policy-report.json --format markdown --output artifacts/policy-report.md
cldc fix . --report-file artifacts/policy-report.json --json --output artifacts/policy-fix-plan.json
Architecture
cldc has a pure-core / thin-shell shape:
src/cldc/ingest/: discover the repo root and load canonical policy sources.src/cldc/parser/: validate and normalize rule documents.src/cldc/compiler/: build.claude/policy.lock.jsonand doctor the repo state.src/cldc/runtime/: evaluate evidence, render reports, build fix plans, and integrate with git.src/cldc/cli/: expose the commands and exit-code behavior.
Development
git clone https://github.com/AbdelStark/claude-md-compiler
cd claude-md-compiler
uv sync --locked
uv run pytest -q
uv build
Useful local commands:
uv run cldc --help
uv run cldc compile tests/fixtures/repo_a
uv run cldc check tests/fixtures/repo_a --write src/main.py --json
uv run cldc ci tests/fixtures/repo_a --base HEAD --head HEAD --json
uv run cldc explain tests/fixtures/repo_a --write src/main.py --format markdown
uv run cldc fix tests/fixtures/repo_a --write src/main.py --json
The repository does not require runtime environment variables.
Learn More
- ARCHITECTURE.md — layered design, data flow, schema contracts, and extension points
- CHANGELOG.md — release history in Keep a Changelog format
License
MIT. See LICENSE.
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 claude_md_compiler-0.1.1.tar.gz.
File metadata
- Download URL: claude_md_compiler-0.1.1.tar.gz
- Upload date:
- Size: 278.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8059bd45f5b715b1a24535aee8e77cf21f9bb8a85546318b7a133cf819e35b6
|
|
| MD5 |
0dc8dbbaa848daa864f476475e81351e
|
|
| BLAKE2b-256 |
790c2132a322ad4b6f3ae9fe9531362029c8bfafc6db9fb73951751d0846bc53
|
File details
Details for the file claude_md_compiler-0.1.1-py3-none-any.whl.
File metadata
- Download URL: claude_md_compiler-0.1.1-py3-none-any.whl
- Upload date:
- Size: 40.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e4b12d797f46bd8a7dce5a3c22e00334deaa347149961c9233ba28c9a3f82246
|
|
| MD5 |
04d19bd9c0a3244c4083b659fb734b4a
|
|
| BLAKE2b-256 |
c794f800545e0595549563fe7ecac7812a8546ab12d06157c7d5beb1bd7e4aef
|