What It Does
The circular dependencies check analyzes your project’s import/require statements to detect circular dependency chains — a common source of bugs, initialization issues, and bundling problems. Key Features:- Walks your source directory to build a dependency graph
- Detects cycles using depth-first search (DFS)
- Resolves relative imports (
./ ../) to absolute paths - Supports TypeScript and JavaScript projects
- Shows up to 3 cycles to keep output readable
- Ignores
node_modulesand build directories
Source:
/src/checks/circular.tsWhat It Checks
The check follows this process:-
Determine File Extensions:
- Checks for
tsconfig.jsonto detect TypeScript projects - TypeScript:
.ts,.tsx,.js,.jsx,.mjs - JavaScript:
.js,.jsx,.mjs,.cjs
- Checks for
-
Find Source Directory:
- Prefers
src/directory if it exists - Falls back to current working directory
- Prefers
-
Walk Directory Tree:
- Recursively scans for matching file extensions
- Skips:
node_modules,.git,dist,build,.next,coverage
-
Extract Imports:
- Parses ES6 imports:
import foo from './bar' - Parses CommonJS:
require('./bar') - Ignores type-only imports:
import type { Foo } from './bar' - Skips external packages (non-relative imports)
- Parses ES6 imports:
-
Build Dependency Graph:
- Resolves relative paths to absolute paths
- Tries extensions and
indexfiles - Creates adjacency list representation
-
Find Cycles:
- Uses DFS with stack tracking
- Reports all detected cycles
- Limits output to first 3 cycles
View Source Code
View Source Code
/src/checks/circular.ts:152-224
Example Output
Why It Matters
How to Fix
1. Identify the Cycle
Look at the cycle path from the check output:index.tsimports fromuser.tsuser.tsimports fromsession.tssession.tsimports back toindex.ts← This is the problem
2. Break the Cycle
Common strategies:3. Verify the Fix
Import Resolution
The check resolves imports using this logic:/src/checks/circular.ts:10-34
- Exact path:
./foo→./foo(if it exists) - With extension:
./foo→./foo.ts - Index file:
./foo→./foo/index.ts
Ignored Import Types
The check ignores:-
Type-only imports (erased at runtime):
-
External packages (from
node_modules): -
Built-in modules:
/src/checks/circular.ts:36-59 for import extraction logic.
Performance Considerations
The check is optimized for large codebases:- Skips common build directories:
node_modules,dist,build,.next,coverage - Limits output: Shows only first 3 cycles
- Fast parsing: Uses regex instead of full AST parsing
- Caches file reads: Only reads each file once
- 100 files: ~100ms
- 500 files: ~400ms
- 1000+ files: ~1s
Advanced: Using Madge
For deeper analysis, the check mentions usingmadge (though not currently implemented):
/src/checks/circular.ts:5-6 for future integration notes.
Common Patterns to Avoid
Barrel exports creating cycles
Barrel exports creating cycles
Problem:Solution: Import directly from sibling files:
src/utils/index.ts
src/utils/format.ts
src/utils/format.ts
Bidirectional relationships
Bidirectional relationships
Problem:Solution: Use IDs instead of direct references:
Global state dependencies
Global state dependencies
Problem:Solution: Use context or dependency injection:
src/store/index.ts
src/store/user.ts
src/store/user.ts
Configuration
To disable this check:stackprobe.config.json
Next Steps
Check Overview
Learn about all available checks
Configuration
Customize check behavior