archstrict
archstrictv0.4.0MIT
TypeScript module boundary checker: default-private module surfaces, layers, cycles, and a todo freeze that can only shrink.
Install
npm install archstrictarchstrict checks TypeScript module boundaries, in the sense of ArchUnit. tsc and type checkers examine types, and ESLint examines style. archstrict examines the boundary between modules. A module shows the rest of the codebase one public-surface file, and an import that reaches past it is a violation. Each report carries a rule id, a location, the reason, and the command that fixes it, so an agent can repair its own mistake.
Features
Section titled “Features”- Declared modules.
archstrict.config.tsis one TypeScript value.declaredModulesnames each module as a directory or a single file, andsurfacenames its public file. A file that matches no module and noexcludepattern is anuncovered-moduleviolation. An unknown key in the config is an error that names the accepted keys. - Reports an agent can act on.
archstrict checkprints each violation with a rule id,path:line:col, the evidence, abecausereason, and ado:command.--jsongives the same data, and--ruleand--modulenarrow it. - Layer and domain rules.
classifyputs tags on files, andedgeschecks the imports between tags withallowDeny,order, andpointrules.guard: trueon anallowDenyorpointrule bans an import that no file has yet.archstrict diagramdraws the config as a Mermaid flowchart. - A todo file that only shrinks. The first
archstrict todofreezes the current violations intoarchstrict.todo.json, and later runs only remove entries. A module listed instrictcan hold no entry at all. - Questions before an edit.
archstrict rules <path>reports the module, tags, and constraints that govern a path, even one that does not exist yet.archstrict simulatepreviews a source or config change without writing it. - Next steps for the map.
archstrict recommendproposesedgesrules and surfaces from the real import graph.archstrict hotspotsscores modules by commits and fan-in, and lists module pairs that change together.
How an agent uses it
Section titled “How an agent uses it”- Before it creates a file or adds an import, the agent runs
npx archstrict rules <path>. - After the edit, it runs
npx archstrict checkand does what eachdo:line says. - In Claude Code, the archstrict plugin’s PostToolUse hook runs
archstrict check <file>after each edit and returns any violation into the agent’s context. Its MCP server offerscheck,rules,search, andsimulateas tools. - On other hosts,
npx archstrict agentsadds the pre-edit instructions toAGENTS.md, and CI runsarchstrict checkon every change.
Getting started
Section titled “Getting started”archstrict needs Node.js 22 or newer.
npm install -D archstrictnpx archstrict initnpx archstrict checkinit declares one module per top-level source directory and one per loose top-level source file, so the first check covers every analyzed file.
That first map is an inventory. Run npx archstrict recommend next, and add an edges rule before you treat the check as a finished architecture.
Try it on a fixture
Section titled “Try it on a fixture”The repository keeps two small projects in fixtures/.
In the first, one file imports billing/rounding.ts directly, past the public surface of the billing module.
public-surface-bypass, with the file, line, and column. checked with archstrict 0.3.0
$ archstrict check[public-surface-bypass] ./fixtures/archstrict-bypass/src/app/main.ts:1:28
'../billing/rounding.ts' resolved to a file inside module 'billing' other than its index.ts, index.tsx, index.mts, index.cts
because: a module's public surface is its only public surface; everything else is private
config: ./fixtures/archstrict-bypass/archstrict.config.ts:33:5 declaredModules[1] (governs)
do: import from src/billing/index.ts instead of src/billing/rounding.ts, adding the export there first if it is missing
modules: 2
modules without a public surface: 1
edges: 1
not covered by any declared module: 0
unresolved specifiers: 0
unsupported syntax: 0
type leaks: 0
todo: 0
summary: this config freezes today's import graph, not a target architecture; no edges rule is configured yet
do: archstrict recommend
do: archstrict hotspots
do: read node_modules/archstrict/skills/archstrict/references/rearchitect.md
do: archstrict todoIn the second project, the same code imports through billing/index.ts.
Before you create a file, ask which module governs it.
archstrict rules <path> names the module that governs a path and says whether the file is a public surface. checked with archstrict 0.3.0
$ archstrict rules src/billing/rounding.tspath: ./fixtures/archstrict-bypass/src/billing/rounding.ts
exists: true
excluded: no
module: billing
tags: (none)
surface file: no
must-be-empty: ok
importable from: (none)
friend access: (none)
allowDeny constraints: (none)
order constraints: (none)
point constraints: (none)