Tommkruix/archprint

Infers architecture rules from your TypeScript repo's real import graph, gates each on statistical evidence, and emits them into the tools you already use (ESLint, dependency-cruiser, ts-arch). Turns the boundaries your code already follows into enforcement, so architecture drift gets caught, not just documented.

2

stars

101

commits

TypeScript

primary language

Sep 8, 2026

updated

tommkruix.github.io/archprint/
ai-coding-agents
ast
cli
code-quality
developer-tools
eslint
eslint-plugin
import-graph
linter
node
software-architecture
static-analysis
ts-morph
typescript

README

Archprint

npm version CI npm downloads license docs

Mine the architecture rules your repo already enforces, with the evidence attached.

Archprint scans a TypeScript repository's real import graph, finds the architectural boundaries the code already respects, and turns the ones that pass a statistical confidence gate into deterministic, ready to install lint rules. Every rule ships with the evidence behind it: how many files conform, how many break it, and how confident the inference is.

Your CLAUDE.md is guidance. Your lint rules are enforcement. Archprint closes the gap by generating the enforcement from patterns your codebase already demonstrates, so you adopt rules you can trust instead of authoring them by hand.

Validated at scale: scan and recommend ran across all 92,861 real public TypeScript repositories with zero crashes, and the full init/wire/eject round-trip ran clean on a 2,000-repo stratified sample. A companion benchmark, AgentRuleBench, measures the guidance-vs-enforcement question directly (a pre-registered, honest null result on the boundary it tested).

What auto-enforces vs. what you review. Archprint is honest about which of its inferences it will stand behind unattended. An adversarial correctness audit (three rounds over four real repositories) found that the mechanical families, ones grounded in unambiguous signals (no cycles, production must not import tests, no console in library code, no undeclared dependencies, deep-relative import style, public-API barrels, no reaching into a dependency's internals, and the DB/UI-in-server-entry rule), had zero false positives every round. So those auto-generate as enforcement. The structural-inference families (layer and role boundaries, UI/data separation, entry purity, server/client, feature-slice and app isolation) infer a "layer" or "role" from paths, which can be wrong, so Archprint holds them for human review by default rather than silently enforcing them. Nothing whose inferred layer or role could be wrong is written as enforcement without you opting in.

Status: published on npm, pre-stable (0.x may break between minor versions). Production-ready today: the insight commands (scan, recommend) and the auto-enforcement of the mechanical families above. The structural families are review-only while they are hardened.

What makes it different

Established TypeScript tools (dependency-cruiser, eslint-plugin-boundaries, Nx, Sheriff, ts-arch) all enforce architecture rules you write by hand. Archprint infers them from the actual import graph and gates each one on statistical evidence before proposing it. Across the TypeScript ecosystem, no other tool does either (see the comparison below). It then emits into those existing tools' formats, so it complements your stack rather than replacing it.

Install

npm install --save-dev archprint

Then run it (or use npx archprint … without installing):

npx archprint scan .

Or build from source:

git clone https://github.com/Tommkruix/archprint
cd archprint
npm ci
npm run build
node dist/cli.js scan <path-to-your-app>

Requires Node >= 20. Point Archprint at an app directory that has a tsconfig.json (for a monorepo, a package such as apps/web; a monorepo root is fine too, Archprint discovers the app directories).

Quick start

# One-shot setup: detect the stack, enforce the rules your code already follows,
# and record what to adopt next in archprint.json
archprint init apps/web

# See the rules your repo already follows, with the evidence
archprint scan apps/web

# Write the auto-trusted (mechanical) rules to disk (rule files + tool configs).
# Structural-inference rules are held for review; add --include-structural to emit them too.
archprint generate apps/web --out archprint-rules

# Inspect the gate evidence behind one rule
archprint explain AP-002 apps/web

# Generate a single rule by id after reviewing it (including a SUGGEST rule)
archprint generate apps/web --rule AP-001

# Recommend a rule set from the evidence and the detected stack (fresh repos too)
archprint recommend apps/web

# Reference the generated rules from the enforcement tools your repo uses (managed, reversible)
archprint wire

# Remove archprint's files and any wired references (clean uninstall)
archprint eject

Re-running generate (or init) refreshes the files in archprint-rules/ and removes any rule the evidence no longer supports, so the output never drifts from the current codebase. wire detects the enforcement tools your repo already uses (a flat eslint config, a .dependency-cruiser.json) and inserts a single managed reference into each, one that survives those regenerations; eject removes archprint's files and every wired reference, restoring each config exactly. For a tool config it cannot safely edit (a JS dependency-cruiser config, say), it prints the exact snippet to paste. The flagship forbidden-import rules (AP-) ship as a generated local eslint plugin that the eslint reference activates, so wiring the eslint config enforces them too, no extra install.

recommend sorts every rule family into three tiers: rules your code already follows (enforce now), rules with thin evidence (review and adopt), and rules that comparable repos commonly follow but yours does not yet (adopt from day one). Each recommendation carries the evidence behind it: the share of comparable repos (your detected stack, else overall) that already enforce that rule, mined from a census of tens of thousands of public TypeScript repositories. The "adopt from day one" tier is driven by that census rather than hand-picked defaults, so on a fresh repo, where there is little code to infer from, it still gives you a stack-aware baseline backed by what the ecosystem actually does.

Example

A real scan of inbox-zero (apps/web, 2,232 TypeScript files), trimmed:

Archprint v0.2.0
Scanned 2,232 TypeScript files
Workspace aliases: 18 resolved

GENERATED RULES
  AP-002  no-ui-layer-in-server-entry      confidence 97%
          Evidence: 216/217 role files conform (99.5% observed)
          Exceptions: 1

LAYER BOUNDARIES (review before enforcing)
  utils !-> app  layer boundary   confidence 99%
          Evidence: 650/653 utils files conform (99.5%); 451 app file(s) depend on utils
  hooks !-> app  layer boundary   confidence 94%
          Evidence: 65/65 hooks files conform (100%); 121 app file(s) depend on hooks

AP-002 is a mechanical family, so it auto-generates as enforcement. The layer boundaries are inferred, so they are shown for review, not written as enforcement unless you pass --include-structural.

Every number is measured from the import graph, not estimated.

What Archprint detects

Ships as: Auto = auto-generated as enforcement (mechanical families, 0 false positives across the correctness audit). Review = held for human review by default; emit with --include-structural (the inferred layer/role can be wrong, so it is not enforced silently). Report = surfaced only, never enforced.

Framework aware: Archprint recognizes the stack (Next.js, Nest, SvelteKit, Nuxt, Remix) and classifies UI components across React (.tsx), Angular (.component.ts, .directive.ts), and Vue and Svelte single-file components (it reads the <script> block of .vue/.svelte files), so the component-aware rules apply regardless of framework.

DetectorRule it can inferShips as
Forbidden imports (marker based)A role (route handler, server entry) must not import a target (the DB client, the UI layer)Auto
Circular dependenciesThe module graph should stay acyclic (gated on how cycle free it already is)Auto
Test isolationProduction (non-test) code must not import test or spec filesAuto
Dependency hygieneImport third-party packages by their public entry, not a dependency's src/internal internalsAuto
Dependency declarationEvery imported third-party package must be declared in package.json (no phantom/transitive deps)Auto
Import stylePrefer workspace aliases over deep relative imports (../../../)Auto
Console isolationLibrary (non-CLI) code must not call console.*Auto
Public API (barrel) boundariesFiles outside a feature or package must import it through its index barrel, not deep import its internalsAuto
Layer boundariesFiles in one layer must not import another, inferred from the dominant dependency directionReview
Role layeringSemantic tiers keep their direction (a REPOSITORY must not import a SERVICE, a SERVICE must not import a CONTROLLER)Review
Entry purityFramework entries (pages, routes, layouts) must not be imported by other first-party codeReview
UI / data separationReusable UI components must not import the DB/data layer directlyReview
Server / client boundaryA Next.js "use client" module must not import a server-only moduleReview
Feature-slice isolationSibling slices under a features/modules/slices/domains container must not import each otherReview
App isolationSibling apps under an apps/services container must not import each other directlyReview
Env accessRead process.env only in the config/env layerReview
Workspace package APIImport a monorepo workspace package by its name, not a deep path into its sourceReview
Stories isolationStorybook .stories files must not be imported by other codeReview
Orphan modulesFiles nothing imports and that are not framework entries (dead code candidates)Report
Transitive reachabilityA layer boundary that a plain import rule passes but that leaks through an intermediary layerReport

The confidence gate

Archprint never proposes a rule as enforceable on a thin sample. Each candidate is scored with a Wilson score lower bound on its true conformance rate, which fuses the observed ratio and the sample size into one number, so 5 of 5 clean files is not treated as evidence of a 90% rule but 40 of 40 is.

  • AUTO (enforceable): the 95% lower bound on conformance is at least 90%, with at most 3 exceptions and a confidently classified role.
  • SUGGEST (provisional): the pattern looks like a rule (at least 80% observed) but the sample is too thin to be confident. Surfaced for review, not auto generated.
  • REJECT: not enough signal.

The statistical gate is necessary but not sufficient: a rule can be statistically clean yet semantically wrong if the inferred "layer" or "role" is not real. So a second, evidence-based gate sits on top of it: only the mechanical families (see the "Ships as: Auto" rows above), which an adversarial correctness audit found had zero false positives across three rounds and four repositories, auto-generate as enforcement. The structural-inference families are capped at review regardless of their statistical score until they earn the same clean record. The bias is deliberate and conservative: one wrong enforced rule hurts credibility more than zero rules.

Output formats

archprint generate writes into the formats your existing tools already read:

  • dependency-cruiser forbidden rulesets: by default the mechanical boundaries (public-API deep-import, test-isolation, dependency-internals); the structural ones (layer, role-layering, feature-slice, app-isolation, entry-purity) are written only with --include-structural, after you review them
  • eslint-plugin-boundaries element-types config, and ESLint core rules (no-restricted-imports) for import-style boundaries
  • ESLint rule files for marker based patterns: a rule card (.md), the rule (.ts), and a passing and a failing fixture
  • A shareable ESLint preset: one self-contained eslint-preset.archprint.mjs that inlines the inferred rules and needs only eslint, so you can commit it, publish it, or hand it to another repo and adopt the rules in one line
  • ts-arch tests for the first-party boundaries (layer, role, UI/data), so the inferred architecture can run inside your existing Vitest or Jest suite
  • Mermaid and Graphviz DOT of the layer dependency graph, so the inferred architecture is visible and its violations are marked

How it compares

Verified against each tool's documentation (TypeScript ecosystem). The two columns that matter are the ones no other TypeScript tool fills:

ToolEnforces arch rulesAuto-infers from the import graphAttaches statistical evidence
Archprintyesyesyes
dependency-cruiseryesnono
eslint-plugin-boundariesyesnono
@nx/enforce-module-boundariesyesnono
Sheriffyesnono
ts-archyesnono
madge / knipanalysis onlynono

Honest caveat: in other ecosystems, Tach (Python) and ArchLint (Java) do auto-infer module boundaries, so Archprint's specific niche is auto-inference plus statistical evidence gating in the TypeScript ecosystem. Archprint also overlaps in detection with dependency-cruiser (cycles, orphans, reachability) and knip (dead code); rather than compete, it emits into those tools' formats.

Commands

CommandWhat it does
archprint init [path]Zero-config setup: detect the stack, enforce the rules the code already follows, and write an archprint.json with the adopt tiers. --include-structural, --out <dir>, --fast, --force.
archprint scan [path]Report the rules the repo already follows, with evidence. --deep resolves through barrels and aliases.
archprint generate [path]Write the auto-trusted mechanical rules + tool configs; structural rules held for review. --rule <id> emits one reviewed rule (including a SUGGEST rule). --include-structural, --out <dir>, --fast.
archprint explain <id> [path]Show the gate breakdown for one rule, with a codeframe per exception plus how-to-fix, when-not-to-use, and how-to-enforce.
archprint recommend [path]Recommend a rule set from the repo's evidence and detected stack (works on a fresh repo too).
archprint wireReference the generated rules from the enforcement tools your repo uses (flat eslint config, .dependency-cruiser.json) via a managed, reversible reference. --out <dir>, --dry-run.
archprint ejectRemove archprint's generated files, its manifests, and any wired references. --out <dir>, --dry-run.

Documentation

Full docs live in docs/: getting started, concepts (the confidence gate, mechanical vs. structural, fast vs. deep, the generate/wire/eject lifecycle), and the rule-family reference (what each rule detects, how it ships, and when not to use it).

Fast and deep modes

scan defaults to a fast specifier level pass (no type checker). generate defaults to a deep pass that resolves through barrels and workspace aliases, since generation is the commitment point. Structural analysis (cycles, orphans, reachability, public-API) always uses the fast graph: it is faithful to deep resolution for those, and public-API detection in fact requires it (deep resolution would resolve through a barrel and erase the barrel-versus-deep signal).

Determinism

Same repo plus same version produces the same output. Analysis is pure and sorted; there is no randomness.

Status and roadmap

Pre-stable (0.x). The engine (twenty detectors, the confidence gate, and emitters for ESLint, a shareable preset, dependency-cruiser, ts-arch, and the layer graph) is in place and tested, and an adversarial correctness audit (three rounds, four real repositories) drove the false-positive rate on auto-generated rules to zero for the mechanical families, which is why those auto-enforce while the structural-inference families are held for review.

Production-ready today: scan and recommend (insight), and auto-enforcement of the mechanical families, with a self-consistency check at generate time, an init scaffolder for fresh repos, and framework coverage across React, Angular, Vue, and Svelte. Still ahead: hardening the structural families toward auto-enforcement (a real per-file role-confidence measure, layer-cohesion, role-classifier ordering).

Contributing

See CONTRIBUTING.md. The project lints, type checks, and tests itself; every change keeps coverage above its thresholds and ships a changeset.

License

MIT

Contributors

Tommkruix

97 commits

Tommkruix/archprint

Infers architecture rules from your TypeScript repo's real import graph, gates each on statistical evidence, and emits them into the tools you already use (ESLint, dependency-cruiser, ts-arch). Turns the boundaries your code already follows into enforcement, so architecture drift gets caught, not just documented.

2

stars

101

commits

TypeScript

primary language

Sep 8, 2026

updated

tommkruix.github.io/archprint/
ai-coding-agents
ast
cli
code-quality
developer-tools
eslint
eslint-plugin
import-graph
linter
node
software-architecture
static-analysis
ts-morph
typescript

README

Archprint

npm version CI npm downloads license docs

Mine the architecture rules your repo already enforces, with the evidence attached.

Archprint scans a TypeScript repository's real import graph, finds the architectural boundaries the code already respects, and turns the ones that pass a statistical confidence gate into deterministic, ready to install lint rules. Every rule ships with the evidence behind it: how many files conform, how many break it, and how confident the inference is.

Your CLAUDE.md is guidance. Your lint rules are enforcement. Archprint closes the gap by generating the enforcement from patterns your codebase already demonstrates, so you adopt rules you can trust instead of authoring them by hand.

Validated at scale: scan and recommend ran across all 92,861 real public TypeScript repositories with zero crashes, and the full init/wire/eject round-trip ran clean on a 2,000-repo stratified sample. A companion benchmark, AgentRuleBench, measures the guidance-vs-enforcement question directly (a pre-registered, honest null result on the boundary it tested).

What auto-enforces vs. what you review. Archprint is honest about which of its inferences it will stand behind unattended. An adversarial correctness audit (three rounds over four real repositories) found that the mechanical families, ones grounded in unambiguous signals (no cycles, production must not import tests, no console in library code, no undeclared dependencies, deep-relative import style, public-API barrels, no reaching into a dependency's internals, and the DB/UI-in-server-entry rule), had zero false positives every round. So those auto-generate as enforcement. The structural-inference families (layer and role boundaries, UI/data separation, entry purity, server/client, feature-slice and app isolation) infer a "layer" or "role" from paths, which can be wrong, so Archprint holds them for human review by default rather than silently enforcing them. Nothing whose inferred layer or role could be wrong is written as enforcement without you opting in.

Status: published on npm, pre-stable (0.x may break between minor versions). Production-ready today: the insight commands (scan, recommend) and the auto-enforcement of the mechanical families above. The structural families are review-only while they are hardened.

What makes it different

Established TypeScript tools (dependency-cruiser, eslint-plugin-boundaries, Nx, Sheriff, ts-arch) all enforce architecture rules you write by hand. Archprint infers them from the actual import graph and gates each one on statistical evidence before proposing it. Across the TypeScript ecosystem, no other tool does either (see the comparison below). It then emits into those existing tools' formats, so it complements your stack rather than replacing it.

Install

npm install --save-dev archprint

Then run it (or use npx archprint … without installing):

npx archprint scan .

Or build from source:

git clone https://github.com/Tommkruix/archprint
cd archprint
npm ci
npm run build
node dist/cli.js scan <path-to-your-app>

Requires Node >= 20. Point Archprint at an app directory that has a tsconfig.json (for a monorepo, a package such as apps/web; a monorepo root is fine too, Archprint discovers the app directories).

Quick start

# One-shot setup: detect the stack, enforce the rules your code already follows,
# and record what to adopt next in archprint.json
archprint init apps/web

# See the rules your repo already follows, with the evidence
archprint scan apps/web

# Write the auto-trusted (mechanical) rules to disk (rule files + tool configs).
# Structural-inference rules are held for review; add --include-structural to emit them too.
archprint generate apps/web --out archprint-rules

# Inspect the gate evidence behind one rule
archprint explain AP-002 apps/web

# Generate a single rule by id after reviewing it (including a SUGGEST rule)
archprint generate apps/web --rule AP-001

# Recommend a rule set from the evidence and the detected stack (fresh repos too)
archprint recommend apps/web

# Reference the generated rules from the enforcement tools your repo uses (managed, reversible)
archprint wire

# Remove archprint's files and any wired references (clean uninstall)
archprint eject

Re-running generate (or init) refreshes the files in archprint-rules/ and removes any rule the evidence no longer supports, so the output never drifts from the current codebase. wire detects the enforcement tools your repo already uses (a flat eslint config, a .dependency-cruiser.json) and inserts a single managed reference into each, one that survives those regenerations; eject removes archprint's files and every wired reference, restoring each config exactly. For a tool config it cannot safely edit (a JS dependency-cruiser config, say), it prints the exact snippet to paste. The flagship forbidden-import rules (AP-) ship as a generated local eslint plugin that the eslint reference activates, so wiring the eslint config enforces them too, no extra install.

recommend sorts every rule family into three tiers: rules your code already follows (enforce now), rules with thin evidence (review and adopt), and rules that comparable repos commonly follow but yours does not yet (adopt from day one). Each recommendation carries the evidence behind it: the share of comparable repos (your detected stack, else overall) that already enforce that rule, mined from a census of tens of thousands of public TypeScript repositories. The "adopt from day one" tier is driven by that census rather than hand-picked defaults, so on a fresh repo, where there is little code to infer from, it still gives you a stack-aware baseline backed by what the ecosystem actually does.

Example

A real scan of inbox-zero (apps/web, 2,232 TypeScript files), trimmed:

Archprint v0.2.0
Scanned 2,232 TypeScript files
Workspace aliases: 18 resolved

GENERATED RULES
  AP-002  no-ui-layer-in-server-entry      confidence 97%
          Evidence: 216/217 role files conform (99.5% observed)
          Exceptions: 1

LAYER BOUNDARIES (review before enforcing)
  utils !-> app  layer boundary   confidence 99%
          Evidence: 650/653 utils files conform (99.5%); 451 app file(s) depend on utils
  hooks !-> app  layer boundary   confidence 94%
          Evidence: 65/65 hooks files conform (100%); 121 app file(s) depend on hooks

AP-002 is a mechanical family, so it auto-generates as enforcement. The layer boundaries are inferred, so they are shown for review, not written as enforcement unless you pass --include-structural.

Every number is measured from the import graph, not estimated.

What Archprint detects

Ships as: Auto = auto-generated as enforcement (mechanical families, 0 false positives across the correctness audit). Review = held for human review by default; emit with --include-structural (the inferred layer/role can be wrong, so it is not enforced silently). Report = surfaced only, never enforced.

Framework aware: Archprint recognizes the stack (Next.js, Nest, SvelteKit, Nuxt, Remix) and classifies UI components across React (.tsx), Angular (.component.ts, .directive.ts), and Vue and Svelte single-file components (it reads the <script> block of .vue/.svelte files), so the component-aware rules apply regardless of framework.

DetectorRule it can inferShips as
Forbidden imports (marker based)A role (route handler, server entry) must not import a target (the DB client, the UI layer)Auto
Circular dependenciesThe module graph should stay acyclic (gated on how cycle free it already is)Auto
Test isolationProduction (non-test) code must not import test or spec filesAuto
Dependency hygieneImport third-party packages by their public entry, not a dependency's src/internal internalsAuto
Dependency declarationEvery imported third-party package must be declared in package.json (no phantom/transitive deps)Auto
Import stylePrefer workspace aliases over deep relative imports (../../../)Auto
Console isolationLibrary (non-CLI) code must not call console.*Auto
Public API (barrel) boundariesFiles outside a feature or package must import it through its index barrel, not deep import its internalsAuto
Layer boundariesFiles in one layer must not import another, inferred from the dominant dependency directionReview
Role layeringSemantic tiers keep their direction (a REPOSITORY must not import a SERVICE, a SERVICE must not import a CONTROLLER)Review
Entry purityFramework entries (pages, routes, layouts) must not be imported by other first-party codeReview
UI / data separationReusable UI components must not import the DB/data layer directlyReview
Server / client boundaryA Next.js "use client" module must not import a server-only moduleReview
Feature-slice isolationSibling slices under a features/modules/slices/domains container must not import each otherReview
App isolationSibling apps under an apps/services container must not import each other directlyReview
Env accessRead process.env only in the config/env layerReview
Workspace package APIImport a monorepo workspace package by its name, not a deep path into its sourceReview
Stories isolationStorybook .stories files must not be imported by other codeReview
Orphan modulesFiles nothing imports and that are not framework entries (dead code candidates)Report
Transitive reachabilityA layer boundary that a plain import rule passes but that leaks through an intermediary layerReport

The confidence gate

Archprint never proposes a rule as enforceable on a thin sample. Each candidate is scored with a Wilson score lower bound on its true conformance rate, which fuses the observed ratio and the sample size into one number, so 5 of 5 clean files is not treated as evidence of a 90% rule but 40 of 40 is.

  • AUTO (enforceable): the 95% lower bound on conformance is at least 90%, with at most 3 exceptions and a confidently classified role.
  • SUGGEST (provisional): the pattern looks like a rule (at least 80% observed) but the sample is too thin to be confident. Surfaced for review, not auto generated.
  • REJECT: not enough signal.

The statistical gate is necessary but not sufficient: a rule can be statistically clean yet semantically wrong if the inferred "layer" or "role" is not real. So a second, evidence-based gate sits on top of it: only the mechanical families (see the "Ships as: Auto" rows above), which an adversarial correctness audit found had zero false positives across three rounds and four repositories, auto-generate as enforcement. The structural-inference families are capped at review regardless of their statistical score until they earn the same clean record. The bias is deliberate and conservative: one wrong enforced rule hurts credibility more than zero rules.

Output formats

archprint generate writes into the formats your existing tools already read:

  • dependency-cruiser forbidden rulesets: by default the mechanical boundaries (public-API deep-import, test-isolation, dependency-internals); the structural ones (layer, role-layering, feature-slice, app-isolation, entry-purity) are written only with --include-structural, after you review them
  • eslint-plugin-boundaries element-types config, and ESLint core rules (no-restricted-imports) for import-style boundaries
  • ESLint rule files for marker based patterns: a rule card (.md), the rule (.ts), and a passing and a failing fixture
  • A shareable ESLint preset: one self-contained eslint-preset.archprint.mjs that inlines the inferred rules and needs only eslint, so you can commit it, publish it, or hand it to another repo and adopt the rules in one line
  • ts-arch tests for the first-party boundaries (layer, role, UI/data), so the inferred architecture can run inside your existing Vitest or Jest suite
  • Mermaid and Graphviz DOT of the layer dependency graph, so the inferred architecture is visible and its violations are marked

How it compares

Verified against each tool's documentation (TypeScript ecosystem). The two columns that matter are the ones no other TypeScript tool fills:

ToolEnforces arch rulesAuto-infers from the import graphAttaches statistical evidence
Archprintyesyesyes
dependency-cruiseryesnono
eslint-plugin-boundariesyesnono
@nx/enforce-module-boundariesyesnono
Sheriffyesnono
ts-archyesnono
madge / knipanalysis onlynono

Honest caveat: in other ecosystems, Tach (Python) and ArchLint (Java) do auto-infer module boundaries, so Archprint's specific niche is auto-inference plus statistical evidence gating in the TypeScript ecosystem. Archprint also overlaps in detection with dependency-cruiser (cycles, orphans, reachability) and knip (dead code); rather than compete, it emits into those tools' formats.

Commands

CommandWhat it does
archprint init [path]Zero-config setup: detect the stack, enforce the rules the code already follows, and write an archprint.json with the adopt tiers. --include-structural, --out <dir>, --fast, --force.
archprint scan [path]Report the rules the repo already follows, with evidence. --deep resolves through barrels and aliases.
archprint generate [path]Write the auto-trusted mechanical rules + tool configs; structural rules held for review. --rule <id> emits one reviewed rule (including a SUGGEST rule). --include-structural, --out <dir>, --fast.
archprint explain <id> [path]Show the gate breakdown for one rule, with a codeframe per exception plus how-to-fix, when-not-to-use, and how-to-enforce.
archprint recommend [path]Recommend a rule set from the repo's evidence and detected stack (works on a fresh repo too).
archprint wireReference the generated rules from the enforcement tools your repo uses (flat eslint config, .dependency-cruiser.json) via a managed, reversible reference. --out <dir>, --dry-run.
archprint ejectRemove archprint's generated files, its manifests, and any wired references. --out <dir>, --dry-run.

Documentation

Full docs live in docs/: getting started, concepts (the confidence gate, mechanical vs. structural, fast vs. deep, the generate/wire/eject lifecycle), and the rule-family reference (what each rule detects, how it ships, and when not to use it).

Fast and deep modes

scan defaults to a fast specifier level pass (no type checker). generate defaults to a deep pass that resolves through barrels and workspace aliases, since generation is the commitment point. Structural analysis (cycles, orphans, reachability, public-API) always uses the fast graph: it is faithful to deep resolution for those, and public-API detection in fact requires it (deep resolution would resolve through a barrel and erase the barrel-versus-deep signal).

Determinism

Same repo plus same version produces the same output. Analysis is pure and sorted; there is no randomness.

Status and roadmap

Pre-stable (0.x). The engine (twenty detectors, the confidence gate, and emitters for ESLint, a shareable preset, dependency-cruiser, ts-arch, and the layer graph) is in place and tested, and an adversarial correctness audit (three rounds, four real repositories) drove the false-positive rate on auto-generated rules to zero for the mechanical families, which is why those auto-enforce while the structural-inference families are held for review.

Production-ready today: scan and recommend (insight), and auto-enforcement of the mechanical families, with a self-consistency check at generate time, an init scaffolder for fresh repos, and framework coverage across React, Angular, Vue, and Svelte. Still ahead: hardening the structural families toward auto-enforcement (a real per-file role-confidence measure, layer-cohesion, role-classifier ordering).

Contributing

See CONTRIBUTING.md. The project lints, type checks, and tests itself; every change keeps coverage above its thresholds and ships a changeset.

License

MIT

Contributors

Tommkruix

97 commits

Languages

TypeScript

99.7%