{"slug": "why-claude-md-is-not-enough-to-protect-your-architecture", "title": "Why CLAUDE.md Is Not Enough to Protect Your Architecture", "summary": "A developer built ArchLint, an open-source CLI that enforces architecture rules by checking Git diffs, aiming to prevent architectural drift in AI-assisted coding. The tool supports deterministic rules like forbidden dependencies and import boundaries, integrates with GitHub Actions, and does not require an LLM or API key.", "body_md": "Files such as `CLAUDE.md`\n\nand `AGENTS.md`\n\nare useful for explaining a project to coding agents.\n\nThey can describe decisions like:\n\nThe problem is that these are still instructions, not enforcement.\n\nAn agent can understand a rule and still violate it during a large change. The generated code may compile and pass its tests while quietly introducing an architectural dependency that the project was supposed to avoid.\n\nHumans do this too. The problem is not specifically AI-generated code. AI agents simply make it easier to produce larger changes faster, which makes architectural drift easier to miss.\n\nI wanted the most important architecture decisions to behave more like lint rules.\n\nThat led me to build [ArchLint](https://github.com/errrt/archlint), a small open-source CLI that checks Git changes against architecture rules stored in the repository.\n\nThe basic flow is:\n\n```\nAI agent or developer changes code\n                  ↓\n               Git diff\n                  ↓\n               ArchLint\n                  ↓\n           PASS or BLOCKED\n```\n\nArchLint does not need to know whether the change came from Claude Code, Codex, Cursor, or a human contributor. It evaluates the resulting Git diff.\n\nA project can define its rules in `.archlint.yml`\n\n:\n\n```\nversion: 1\n\nrules:\n  - id: no-firebase\n    type: forbidden_dependency\n    packages:\n      - firebase\n    message: \"Use Supabase Auth only.\"\n\n  - id: db-boundary\n    type: import_boundary\n    from:\n      - \"src/components/**\"\n    deny:\n      - \"src/db/**\"\n    message: \"UI components must not access the database directly.\"\n\n  - id: protect-auth\n    type: protected_path\n    paths:\n      - \"src/auth/**\"\n    severity: warning\n```\n\nThese rules express three different decisions:\n\nThe configuration lives beside the code, so it can be reviewed and versioned like any other architectural decision.\n\nFrom the root of a Git repository:\n\n```\nnpx archlint-ai init\nnpx archlint-ai check\n```\n\nThe first command creates a starter configuration. The second checks staged, unstaged, and untracked changes.\n\nNo account, API key, dashboard, or global installation is required.\n\nA successful check looks like this:\n\n```\n✓ 3 rules passed\n\nNO ARCHITECTURE DRIFT DETECTED\n```\n\nWhen a rule is broken, ArchLint reports the rule, file, evidence, and message:\n\n```\n[no-firebase]\n\nsrc/auth/firebase.ts:1\n\nUse Supabase Auth only.\n\nEvidence: firebase\nSeverity: ERROR\n```\n\nThe same check can run in GitHub Actions:\n\n```\nname: ArchLint\n\non:\n  pull_request:\n\njobs:\n  archlint:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - run: npx archlint-ai check --base origin/${{ github.event.repository.default_branch }}\n```\n\nIf a pull request introduces an error-level violation, the command exits with a non-zero status and the check fails.\n\nAt that point, the team has two choices:\n\n`.archlint.yml`\n\nbecause the architecture decision itself has intentionally changed.The second option is important. Architecture rules should not be permanent by accident. They should be explicit and reviewable.\n\nArchLint primarily checks additions in the current diff rather than scanning the entire repository.\n\nThis has two practical benefits:\n\nIt also keeps the tool focused on one question:\n\nDid this change make the architecture worse?\n\nAn LLM could review a diff and decide whether it violates an architectural principle. That may become useful for rules that cannot be expressed structurally.\n\nHowever, many important constraints do not require an LLM:\n\nFor these rules, deterministic checks are faster, cheaper, easier to understand, and produce repeatable results.\n\nArchLint v0.1 therefore focuses on deterministic rules. It defines an experimental provider-neutral interface for future semantic checks, but the current package does not send repository code to an LLM.\n\nArchLint is still an early release.\n\nThe current dependency and import checks focus on JavaScript and TypeScript syntax. Import-boundary rules are path-based, and the project does not yet attempt to understand every framework or programming language.\n\nThat is intentional. I wanted to start with a small tool that solves a clear problem before expanding the rule system.\n\nThe next rules should be driven by real projects rather than guesses.\n\nArchLint is not intended to replace `CLAUDE.md`\n\n, `AGENTS.md`\n\n, architecture decision records, or code review.\n\nThose documents explain the reasoning and help agents make better choices.\n\nArchLint handles the smaller set of decisions that are important enough to enforce automatically.\n\nA useful separation is:\n\n```\nDocumentation explains the architecture.\nArchLint protects its critical boundaries.\nCode review handles context and judgment.\n```\n\nThe project is available on GitHub:\n\n[https://github.com/errrt/archlint](https://github.com/errrt/archlint)\n\nIt can be tried with:\n\n```\nnpx archlint-ai init\nnpx archlint-ai check\n```\n\nI would especially like feedback from developers using coding agents on real repositories:\n\n**Which architecture rule would you want to enforce first?**", "url": "https://wpnews.pro/news/why-claude-md-is-not-enough-to-protect-your-architecture", "canonical_source": "https://dev.to/errrt/why-claudemd-is-not-enough-to-protect-your-architecture-2bl5", "published_at": "2026-08-25 13:59:10+00:00", "updated_at": "2026-08-25 14:15:17.111154+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-products"], "entities": ["ArchLint", "GitHub Actions", "Claude Code", "Codex", "Cursor"], "alternates": {"html": "https://wpnews.pro/news/why-claude-md-is-not-enough-to-protect-your-architecture", "markdown": "https://wpnews.pro/news/why-claude-md-is-not-enough-to-protect-your-architecture.md", "text": "https://wpnews.pro/news/why-claude-md-is-not-enough-to-protect-your-architecture.txt", "jsonld": "https://wpnews.pro/news/why-claude-md-is-not-enough-to-protect-your-architecture.jsonld"}}