# Architecture Suite
Four chained Claude Code skills for the full architecture lifecycle: **design**, **decide**, **document**, **evaluate**. Paradigm-agnostic (supports layered, hexagonal, microservices, event-driven, CQRS, DDD, and others). Language-aware (framework-agnostic checks work everywhere; language-specific linters augment when configured).
## The Chain
```
┌─────────────────┐
New project → │ arch-design │ → .architecture/brief.md
└────────┬────────┘
│
(for each open decision)
│
▼
┌─────────────────┐
│ arch-decide │ → docs/adr/NNNN-*.md
└────────┬────────┘
│
(when ready to formalize)
│
▼
┌─────────────────┐
│ arch-document │ → docs/architecture/*.md
└────────┬────────┘ (dispatches to c4-analyze, c4-diagram)
│
(once code exists, periodically)
│
▼
┌─────────────────┐
│ arch-evaluate │ → .architecture/evaluation-YYYY-MM-DD.md
└─────────────────┘
```
Skills are standalone — invoke any one directly. The flow above is the canonical path; you can enter at any point if the prerequisite artifacts already exist.
## What Each Skill Does
### [arch-design](../../arch-design/SKILL.md)
Elicits the architecture: intake (stakeholders, scale, team, timeline), quality-attribute prioritization, constraints, then proposes 2-4 candidate paradigms with honest trade-off analysis. Picks one with rationale. Lists open decisions that become ADRs.
**Output:** `.architecture/brief.md`
### [arch-decide](../../arch-decide/SKILL.md)
Records significant technical decisions as ADRs. Five template variants (MADR, Nygard, Y-statement, lightweight, RFC). Covers ADR lifecycle (proposed / accepted / deprecated / superseded), review checklist, and `adr-tools` automation.
**Output:** `docs/adr/NNNN-
.md`, plus an index at `docs/adr/README.md`.
**Forked from [wshobson/agents](https://github.com/wshobson/agents) — MIT.**
### [arch-document](../../arch-document/SKILL.md)
Produces full arc42-structured documentation from the brief + ADRs + codebase. All twelve arc42 sections. Dispatches to `c4-analyze` (for code-present systems) and `c4-diagram` (for textual descriptions) for the diagrams in sections 3, 5, 6, and 7.
**Output:** `docs/architecture/01-introduction.md` through `12-glossary.md`, plus diagrams under `docs/architecture/diagrams/`.
### [arch-evaluate](../../arch-evaluate/SKILL.md)
Audits the codebase against the brief + ADRs. Four framework-agnostic checks (cyclic deps, stated-layer violations, public API drift, forbidden deps). Opportunistically invokes language-specific linters if they're already configured in the repo.
**Output:** `.architecture/evaluation-YYYY-MM-DD.md`
## Installation
These skills live in this rulesets repo alongside the other skills (`debug`, `add-tests`, `c4-analyze`, etc.). Install globally once:
```bash
make -C ~/code/rulesets install
```
This symlinks every skill (including the four `arch-*`) into `~/.claude/skills/`. Any Claude Code session on this machine will see them.
To uninstall:
```bash
make -C ~/code/rulesets uninstall
```
To check install state:
```bash
make -C ~/code/rulesets list
```
## Optional: Language-Specific Linters
`arch-evaluate` works without any external tooling — its framework-agnostic checks cover cycles, layer violations, API drift, and forbidden deps on any language Claude can read. **Installing the linters below is optional** and augments those checks with dedicated tooling: faster on large codebases, CI-friendly, and precise.
Install only the ones you need for your active languages.
### Python — import-linter
Declarative import contracts. Config in `.importlinter` or `[tool.importlinter]` in `pyproject.toml`.
```bash
pipx install import-linter
# or: pip install --user import-linter
# or (in a uv-managed project): uv add --dev import-linter
```
Verify:
```bash
lint-imports --help
```
Example config (`.importlinter`):
```ini
[importlinter]
root_package = myapp
[importlinter:contract:layers]
name = Core layers
type = layers
layers =
myapp.presentation
myapp.application
myapp.domain
myapp.infrastructure
[importlinter:contract:framework_isolation]
name = Domain isolation
type = forbidden
source_modules =
myapp.domain
forbidden_modules =
django
fastapi
```
### TypeScript / JavaScript — dependency-cruiser
Rich import analysis with a JS config file. The de-facto standard for TS architectural linting.
```bash
npm install --save-dev dependency-cruiser
# or globally: npm install -g dependency-cruiser
```
Verify:
```bash
npx dependency-cruiser --version
```
Generate an initial config:
```bash
npx dependency-cruiser --init
```
Then edit `.dependency-cruiser.cjs` to encode your architecture. Example rule:
```javascript
module.exports = {
forbidden: [
{
name: 'domain-no-infrastructure',
severity: 'error',
from: { path: '^src/domain' },
to: { path: '^src/infrastructure' },
},
],
options: { tsPreCompilationDeps: true, tsConfig: { fileName: 'tsconfig.json' } },
};
```
### Go — golangci-lint (with depguard)
`go vet` (part of the stdlib) covers built-in checks. `depguard` (via golangci-lint) enforces import rules.
```bash
# macOS
brew install golangci-lint
# Linux / anywhere with Go
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
```
Verify:
```bash
golangci-lint --version
go vet ./...
```
Example `.golangci.yml`:
```yaml
linters:
disable-all: true
enable:
- depguard
linters-settings:
depguard:
rules:
domain:
list-mode: lax
files:
- "$all"
- "!**/infrastructure/**"
deny:
- pkg: "github.com/yourorg/yourapp/infrastructure"
desc: "domain must not depend on infrastructure"
```
### Java — ArchUnit (v2+)
Test-driven: architectural rules live in JUnit tests. Not invoked by `arch-evaluate` in v1.
**Maven:**
```xml
com.tngtech.archunit
archunit-junit5
1.3.0
test
```
**Gradle:**
```groovy
testImplementation 'com.tngtech.archunit:archunit-junit5:1.3.0'
```
Example rule (`src/test/java/archtest/LayerRules.java`):
```java
@AnalyzeClasses(packages = "com.yourorg.yourapp")
class LayerRules {
@ArchTest
static final ArchRule layered =
layeredArchitecture().consideringAllDependencies()
.layer("Presentation").definedBy("..presentation..")
.layer("Application").definedBy("..application..")
.layer("Domain").definedBy("..domain..")
.whereLayer("Presentation").mayNotBeAccessedByAnyLayer()
.whereLayer("Application").mayOnlyBeAccessedByLayers("Presentation")
.whereLayer("Domain").mayOnlyBeAccessedByLayers("Application", "Presentation");
}
```
Then run `mvn test` or `gradle test`.
### C / C++ — include-what-you-use (v2+)
Checks each source file's `#include` discipline. Not invoked by `arch-evaluate` in v1; listed for completeness.
```bash
# macOS
brew install include-what-you-use
# Arch Linux
sudo pacman -S include-what-you-use
# Ubuntu/Debian
sudo apt install iwyu
```
Integrate via CMake:
```cmake
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE include-what-you-use)
```
Verify:
```bash
include-what-you-use --version
```
## Typical Flow
### New project
```bash
# 1. Shape the architecture
# In Claude Code:
/arch-design
# Answer intake questions, rank quality attributes, review candidates.
# Output: .architecture/brief.md
# 2. Record each open decision
/arch-decide
# Once per significant decision. Output: docs/adr/0001-*.md, 0002-*.md, etc.
# 3. Formalize (when ready)
/arch-document
# Generates all twelve arc42 sections + diagrams.
# Output: docs/architecture/*.md
# 4. Audit (once code exists)
/arch-evaluate
# Report at .architecture/evaluation-YYYY-MM-DD.md
```
### Existing project with no architecture docs
```bash
# 1. Retroactively capture
/arch-design # reconstruct the brief from what exists
/arch-decide # write ADRs for past decisions (date them honestly)
/arch-document # produce current-state arc42 docs
# 2. Audit against the reconstructed intent
/arch-evaluate
```
### Continuous
- Re-run `/arch-evaluate` periodically (on PR, before release, monthly)
- Every significant new decision → `/arch-decide`
- Brief or ADR changes → `/arch-document` to refresh
## Where Things Land
```
/
├── .architecture/
│ ├── brief.md ← arch-design
│ └── evaluation-YYYY-MM-DD.md ← arch-evaluate
├── docs/
│ ├── adr/
│ │ ├── README.md ← arch-decide (index)
│ │ └── NNNN-.md ← arch-decide
│ └── architecture/
│ ├── README.md ← arch-document (index)
│ ├── 01-introduction.md … ← arch-document
│ ├── 12-glossary.md
│ └── diagrams/ ← arch-document (via c4-*)
│ ├── context.svg
│ ├── container.svg
│ └── runtime-.svg
```
## Dependencies Between Skills
- `arch-decide` is standalone; nothing required from the others
- `arch-document` reads the brief and ADRs; without them, it stubs sections as TODO
- `arch-evaluate` requires the brief; without it, the skill stops and tells the user to run `arch-design`
- `arch-document` dispatches to `c4-analyze` (if code exists) and `c4-diagram` (otherwise) — both live in this same rulesets repo
## Versioning and Deferred Work
v1 covers the four core skills with the chain above. The deferred feature list — CI integration, auto-generated linter configs, ArchUnit integration, DDD aggregate boundaries, etc. — is tracked at [`v2-todo.org`](v2-todo.org).
## Licensing
- `arch-design`, `arch-document`, `arch-evaluate` — part of this rulesets repo
- `arch-decide` — forked from [wshobson/agents](https://github.com/wshobson/agents), **MIT**. See `arch-decide/LICENSE`.
## Contributing / Modifying
These are personal skills; fork as needed. If you change a skill and want to re-sync the global install symlink, re-run `make -C ~/code/rulesets install`. Symlinks point back at this repo, so edits propagate without re-install.