hexcheck
hexcheck is a Go architecture linter for hexagonal and clean architecture boundaries.
It is built on golang.org/x/tools/go/analysis, runs as a standalone CLI, and can be embedded in a custom golangci-lint binary through the Module Plugin System.
What it checks
- dependency direction between configurable architecture roles
- framework or infrastructure types leaking into core/port APIs
- suspicious business logic in adapters and entrypoints
- missing generated mocks for port interfaces
- local fakes or concrete adapters in tests where generated mocks should be used
Architecture roles
hexcheck does not require folders to be named domain, usecase, or adapters. A repository maps its own paths to roles in .hexcheck.yaml.
Supported roles:
core — domain/core business logic
usecase — application use cases and orchestration
ports — interfaces/contracts
adapter — infrastructure, persistence, external services, outbound adapters
entrypoint — CLI, HTTP handlers, UI entrypoints, app bootstrap
ignore — generated code, mocks, vendored paths
Quick config
version: 1
components:
core:
role: core
paths:
- internal/domain/**
- internal/core/**
usecases:
role: usecase
paths:
- internal/application/usecase/**
- internal/application/usecases/**
- internal/usecase/**
- internal/usecases/**
ports:
role: ports
paths:
- internal/application/port/**
- internal/domain/repository/**
adapters:
role: adapter
paths:
- internal/infrastructure/**
- internal/adapters/**
entrypoints:
role: entrypoint
paths:
- cmd/**
generated:
role: ignore
paths:
- '**/mocks/**'
- '**/generated/**'
- '**/*_templ.go'
- '**/*_gen.go'
rules:
no-adapter-imports-in-core: error
no-infra-imports-in-usecase: error
no-framework-types-in-core: error
no-infra-types-in-ports: error
no-adapter-to-adapter-imports: warn
suspicious-business-logic-in-adapter: warn
no-local-fakes-for-ports: warn
missing-generated-mock-for-port: warn
prefer-generated-mocks: warn
heuristics:
businessLogicThreshold: 8
businessLogicMinStrongSignals: 2
businessLogicMinWeakSignals: 2
businessLogicMaxFunctionNodes: 2000
businessLogicMaxDiagnosticsPerPackage: 10
businessLogicMode: audit # audit|ci
businessLogicMinConfidence: medium # low|medium|high
excludeTestFiles: true
mocking:
generatedMockPaths:
- internal/mocks/**
- internal/application/mocks/**
- internal/application/port/mocks/**
generatedMockNamePatterns:
- Mock{{Interface}}
- '{{Interface}}Mock'
A fuller example lives in examples/hexcheck.yaml.
Business-logic diagnostics include a confidence level. audit mode reports findings at or above businessLogicMinConfidence; ci mode reports only high-confidence findings.
Standalone CLI
Because hexcheck is a go/analysis analyzer, standalone flags use the analyzer prefix:
hexcheck -hexcheck.config .hexcheck.yaml -hexcheck.root . ./...
During development:
go run ./cmd/hexcheck -hexcheck.config examples/hexcheck.yaml -hexcheck.root . ./...
golangci-lint module plugin
Build a custom golangci-lint binary using the module plugin system:
golangci-lint custom -c examples/custom-gcl.yml
Example builder config:
version: v2.12.2
name: hex-golangci-lint
destination: ./bin
plugins:
- module: github.com/bnema/hexcheck
import: github.com/bnema/hexcheck/golangci
version: v0.1.0
Enable it in a project:
version: "2"
linters:
enable:
- hexcheck
settings:
custom:
hexcheck:
type: module
description: Checks hexagonal architecture boundaries.
settings:
config: .hexcheck.yaml
Agent configuration guide
SKILL.md explains how an agent should configure hexcheck for a new repository, including non-standard layouts such as core/boundaries.
Local development
make test
make check
HEXCHECK_SMOKE_REPO=/path/to/local/go/repo make smoke-local
source
1# hexcheck
2
3`hexcheck` is a Go architecture linter for hexagonal and clean architecture boundaries.
4
5It is built on `golang.org/x/tools/go/analysis`, runs as a standalone CLI, and can be embedded in a custom `golangci-lint` binary through the Module Plugin System.
6
7## What it checks
8
9- dependency direction between configurable architecture roles
10- framework or infrastructure types leaking into core/port APIs
11- suspicious business logic in adapters and entrypoints
12- missing generated mocks for port interfaces
13- local fakes or concrete adapters in tests where generated mocks should be used
14
15## Architecture roles
16
17`hexcheck` does not require folders to be named `domain`, `usecase`, or `adapters`. A repository maps its own paths to roles in `.hexcheck.yaml`.
18
19Supported roles:
20
21- `core` — domain/core business logic
22- `usecase` — application use cases and orchestration
23- `ports` — interfaces/contracts
24- `adapter` — infrastructure, persistence, external services, outbound adapters
25- `entrypoint` — CLI, HTTP handlers, UI entrypoints, app bootstrap
26- `ignore` — generated code, mocks, vendored paths
27
28## Quick config
29
30```yaml
31version: 1
32components:
33 core:
34 role: core
35 paths:
36 - internal/domain/**
37 - internal/core/**
38 usecases:
39 role: usecase
40 paths:
41 - internal/application/usecase/**
42 - internal/application/usecases/**
43 - internal/usecase/**
44 - internal/usecases/**
45 ports:
46 role: ports
47 paths:
48 - internal/application/port/**
49 - internal/domain/repository/**
50 adapters:
51 role: adapter
52 paths:
53 - internal/infrastructure/**
54 - internal/adapters/**
55 entrypoints:
56 role: entrypoint
57 paths:
58 - cmd/**
59 generated:
60 role: ignore
61 paths:
62 - '**/mocks/**'
63 - '**/generated/**'
64 - '**/*_templ.go'
65 - '**/*_gen.go'
66
67rules:
68 no-adapter-imports-in-core: error
69 no-infra-imports-in-usecase: error
70 no-framework-types-in-core: error
71 no-infra-types-in-ports: error
72 no-adapter-to-adapter-imports: warn
73 suspicious-business-logic-in-adapter: warn
74 no-local-fakes-for-ports: warn
75 missing-generated-mock-for-port: warn
76 prefer-generated-mocks: warn
77
78heuristics:
79 businessLogicThreshold: 8
80 businessLogicMinStrongSignals: 2
81 businessLogicMinWeakSignals: 2
82 businessLogicMaxFunctionNodes: 2000
83 businessLogicMaxDiagnosticsPerPackage: 10
84 businessLogicMode: audit # audit|ci
85 businessLogicMinConfidence: medium # low|medium|high
86 excludeTestFiles: true
87
88mocking:
89 generatedMockPaths:
90 - internal/mocks/**
91 - internal/application/mocks/**
92 - internal/application/port/mocks/**
93 generatedMockNamePatterns:
94 - Mock{{Interface}}
95 - '{{Interface}}Mock'
96```
97
98A fuller example lives in [`examples/hexcheck.yaml`](examples/hexcheck.yaml).
99
100Business-logic diagnostics include a confidence level. `audit` mode reports findings at or above `businessLogicMinConfidence`; `ci` mode reports only high-confidence findings.
101
102## Standalone CLI
103
104Because `hexcheck` is a `go/analysis` analyzer, standalone flags use the analyzer prefix:
105
106```bash
107hexcheck -hexcheck.config .hexcheck.yaml -hexcheck.root . ./...
108```
109
110During development:
111
112```bash
113go run ./cmd/hexcheck -hexcheck.config examples/hexcheck.yaml -hexcheck.root . ./...
114```
115
116## golangci-lint module plugin
117
118Build a custom golangci-lint binary using the module plugin system:
119
120```bash
121golangci-lint custom -c examples/custom-gcl.yml
122```
123
124Example builder config:
125
126```yaml
127version: v2.12.2
128name: hex-golangci-lint
129destination: ./bin
130plugins:
131 - module: github.com/bnema/hexcheck
132 import: github.com/bnema/hexcheck/golangci
133 version: v0.1.0
134```
135
136Enable it in a project:
137
138```yaml
139version: "2"
140linters:
141 enable:
142 - hexcheck
143 settings:
144 custom:
145 hexcheck:
146 type: module
147 description: Checks hexagonal architecture boundaries.
148 settings:
149 config: .hexcheck.yaml
150```
151
152## Agent configuration guide
153
154[`SKILL.md`](SKILL.md) explains how an agent should configure `hexcheck` for a new repository, including non-standard layouts such as `core`/`boundaries`.
155
156## Local development
157
158```bash
159make test
160make check
161HEXCHECK_SMOKE_REPO=/path/to/local/go/repo make smoke-local
162```