Documentation menu
Configuration
Everything is optional. Little Owl is designed to be useful on the very first run, before any configuration exists.
Creating a config
little-owl initThis writes .little-owl/config.ts. Configuration is also read from .little-owl/config.{js,mjs,json}, little-owl.config.{ts,js,mjs,json}, .littleowlrc.{ts,js,mjs,json}, or a bare .littleowlrc holding JSON.
.little-owl/config.ts
import { defineConfig } from 'little-owl-code';
export default defineConfig({
strictness: 'balanced', // 'relaxed' | 'balanced' | 'strict'
architecture: {
// Layers top to bottom. A layer may depend on the one below it.
layers: {
ui: ['app', 'components'],
application: ['services', 'domain'],
data: ['repositories', 'lib/db'],
},
layerPolicy: 'adjacent', // 'adjacent' | 'downward'
featureRoot: 'features',
forbidden: [['components/**', 'lib/db/**']],
},
thresholds: {
maxFileLines: 800,
maxFunctionLines: 100,
maxComponentLines: 800,
maxComplexity: 15,
},
rules: {
'architecture/circular-dependency': 'error',
'complexity/large-file': 'warning',
'maintainability/duplicate-block': 'off',
},
ignore: ['generated/**'],
ci: {
failOn: 'error',
maxOverallDrop: 5,
},
});Strictness
A preset that moves every threshold and several rule severities at once. Pick one, then override individual values if you need to.
relaxed— only clear structural problems. Several stylistic rules are off entirely.balanced— the default, and what the examples on this site use.strict— small files, tight boundaries, more findings on purpose.
Architecture
Layers
Listed top to bottom, mapping a layer name to the directories that belong to it. Without this, layers are inferred from conventional directory names and every report says the structure was a guess.
Layer policy
adjacent— a layer may only use the one directly below it, soui → datais reported as a skipped layer.downward— a layer may use any layer below it.
Forbidden edges
Explicit [from, to] glob pairs that must never appear, checked independently of the layer model. Useful for the one rule your team argues about most.
Thresholds
Defaults by strictness preset. Override any of them individually.
| Threshold | Relaxed | Balanced | Strict | Meaning |
|---|---|---|---|---|
| maxFileLines | 1200 | 800 | 400 | Lines before a file is oversized. |
| maxFunctionLines | 160 | 100 | 60 | Lines before a function is oversized. |
| maxComponentLines | 1000 | 800 | 300 | Separate budget for React components. |
| maxComplexity | 25 | 15 | 10 | Cyclomatic complexity per function. |
| maxNesting | 6 | 4 | 3 | Control-flow depth inside a function. |
| maxParams | 8 | 5 | 4 | Positional parameters per function. |
| maxImportDepth | 12 | 8 | 6 | Length of an import chain from an entry point. |
| minDuplicateLines | 12 | 8 | 6 | Identical lines before a block counts as duplicated. |
| maxAnyPerKLoc | 12 | 6 | 2 | `any` usages per 1,000 lines before type safety is penalised. |
Rule severities
Any rule can be set to off, info, warning or error, keyed by rule id. Every finding prints its id, so you always know what to write.
little-owl config --rulesInclude and ignore
include narrows the analysis to specific paths — leave it out to analyse everything. ignore adds glob patterns on top of the built-in list, which already covers node_modules, build output, virtual environments and vendored directories. Your root .gitignore is read as well.
Scope
Default glob patterns for review --scope. Most teams leave this empty and pass the scope per change, since it describes one task rather than the project.
CI
failOn—error,warningornever.maxOverallDrop— the largest acceptable fall in the overall score before the build fails.newFindingsOnly— when true, which is the default, pre-existing findings cannot fail a build.