Skip to main content

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.

PyPI Python License: MIT Built with uv Tests: pytest Status: Alpha

cldc terminal preview

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 result
  • 1: runtime or input error
  • 2: 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:

  1. CLAUDE.md
  2. inline fenced ```cldc blocks inside CLAUDE.md
  3. .claude-compiler.yaml or .claude-compiler.yml
  4. bundled presets referenced from .claude-compiler.yaml via extends:
  5. policies/*.yml and policies/*.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.json and 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

claude_md_compiler-0.1.1.tar.gz (278.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

claude_md_compiler-0.1.1-py3-none-any.whl (40.5 kB view details)

Uploaded Python 3

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

Hashes for claude_md_compiler-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b8059bd45f5b715b1a24535aee8e77cf21f9bb8a85546318b7a133cf819e35b6
MD5 0dc8dbbaa848daa864f476475e81351e
BLAKE2b-256 790c2132a322ad4b6f3ae9fe9531362029c8bfafc6db9fb73951751d0846bc53

See more details on using hashes here.

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

Hashes for claude_md_compiler-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e4b12d797f46bd8a7dce5a3c22e00334deaa347149961c9233ba28c9a3f82246
MD5 04d19bd9c0a3244c4083b659fb734b4a
BLAKE2b-256 c794f800545e0595549563fe7ecac7812a8546ab12d06157c7d5beb1bd7e4aef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page