Skip to content

Explain Command ​

Dump all active architecture rules as structured JSON. Useful for team onboarding, AI system prompts, and CI auditing.

Usage ​

bash
npx ts-archunit explain arch.rules.ts
npx ts-archunit explain arch.rules.ts --markdown
npx ts-archunit explain arch.rules.ts --config ts-archunit.config.ts

JSON output ​

The default output is a JSON object containing an array of rule descriptions. Each entry includes the rule's auto-generated description, its ID (if set via .rule()), and the because, suggestion, and docs metadata fields. Rules without .rule() metadata still appear — they just have empty optional fields.

json
{
  "rules": [
    {
      "rule": "that reside in folder \"**/services/**\" should not contain call to 'prisma'",
      "id": "arch/no-db-in-services",
      "because": "services must not bypass the repository layer",
      "suggestion": "Move the query to a repository method"
    }
  ],
  "generatedAt": "2026-03-30T12:00:00Z"
}

Markdown output ​

When you need a human-readable summary (for wiki pages, PR descriptions, or team documentation), use --markdown. It outputs the same data as a pipe-separated table:

| ID | Rule | Because | Suggestion |
|----|------|---------|------------|
| arch/no-db-in-services | that reside in ... | services must not... | Move the query... |

Use cases ​

AI system prompt ​

Pipe the output into your AI tool's context so it understands the project's constraints:

bash
npx ts-archunit explain arch.rules.ts > .arch-rules.json
# Add to CLAUDE.md or system prompt

Team onboarding ​

New developers read the explain output to understand why certain patterns are enforced — the because and suggestion fields provide the rationale.

CI audit logging ​

Log the active rule set alongside test results:

yaml
- name: Log architecture rules
  run: npx ts-archunit explain arch.rules.ts

How it works ​

The explain command loads your rule files the same way check does, but calls .describeRule() on each builder instead of .check(). No rules are evaluated — metadata is extracted directly from the builder state.

For explain to produce useful output, annotate your rules with .rule() metadata:

typescript
functions(p)
  .that()
  .resideInFolder('**/services/**')
  .should()
  .satisfy(mustCall(/Repository/))
  .rule({
    id: 'arch/service-delegation',
    because: 'services orchestrate — data access belongs in repositories',
    suggestion: 'Inject a repository and call its methods',
    docs: 'https://wiki.internal/architecture#services',
  })
  .check() // or just build the rule — explain reads metadata without executing

Rules without .rule() metadata will have empty id, because, and suggestion fields — they still appear in the output with their auto-generated rule description.

Released under the MIT License.