Problem
I've been using CodeGraph to navigate a large TypeScript monorepo, and circular imports have been a recurring pain point — they cause build failures with tsc, slow down bundlers, and create maintenance traps where refactoring one module breaks another in non-obvious ways.
I went looking for a tool to catch these cycles early and discovered something interesting: CodeGraph already has a complete circular import detector buried in the codebase — it's just never called.
Evidence
The detector lives at src/graph/queries.ts:225:
findCircularDependencies(): string[][] {
// ... full DFS implementation with white/gray/black coloring
}
It's re-exported on the CodeGraph class at src/index.ts:1017. The algorithm is complete, well-tested, and handles multi-cycle graphs correctly.
But it has zero callers. It's dead code — implemented but never wired to any output channel.
I verified this by grepping the entire codebase:
$ grep -r "findCircularDependencies" src/
src/graph/queries.ts:225: findCircularDependencies(): string[][] {
src/index.ts:1017: findCircularDependencies(): string[][] {
Only the definition and re-export. No function ever calls it.
Why This Matters
Circular imports are one of those problems that:
- Don't show up in code review (hard to spot manually in large graphs)
- Only surface when the build breaks (or worse, cause subtle runtime bugs)
- Get worse over time (one cycle begets more as developers work around it)
Having a tool that catches them before CI would save significant debugging time. CodeGraph already has the graph data needed to detect them — the algorithm is sitting right there.
Proposed Solution
Surface findCircularDependencies() on two channels:
1. MCP tool: codegraph_check
A new tool that AI agents can call to detect circular imports in the current project.
// Tool definition
{
name: 'codegraph_check',
description: 'Detect circular import cycles in the project graph',
inputSchema: { type: 'object', properties: {} }
}
Output (markdown, sorted deterministically):
**Circular imports detected (2 cycle(s)):**
**Cycle 1** (2 file(s)): src/a.ts → src/b.ts → src/a.ts
**Cycle 2** (3 file(s)): src/c.ts → src/d.ts → src/e.ts → src/c.ts
When no cycles exist:
No circular imports found. The dependency graph is acyclic.
Key design decision: Ship functional but NOT in DEFAULT_MCP_TOOLS. Rationale: CLAUDE.md documents extensive eval evidence that agents under-pick new tools, and adding to the default surface without proven demand could dilute tool selection. The tool is callable — agents just need to know it exists.
2. CLI subcommand: codegraph check [path]
A deterministic, user-invoked command for developers.
# Check current project
codegraph check
# Check specific path
codegraph check src/modules
# JSON output for CI
codegraph check --json
Exit behavior:
- Exit 0 — graph is acyclic
- Exit 1 — cycles detected (file paths listed in output)
This makes it git-hook ready:
# .git/hooks/pre-commit
codegraph check || exit 1
Implementation Scope
5 files, ~340 lines, 0 deletions:
| File |
Change |
src/mcp/tools.ts |
Tool definition + dispatch case + handleCheck handler |
src/bin/codegraph.ts |
check [path] subcommand |
__tests__/mcp-check-circular-imports.test.ts |
4 MCP tests (new) |
__tests__/cli-check.test.ts |
2 CLI tests (new) |
CHANGELOG.md |
[Unreleased] entry |
No schema changes. No breaking changes. No new dependencies.
What I Need
I have the implementation ready on a branch (feat/codegraph-check-circular-imports). Looking for feedback on:
- Is the callable-but-not-listed approach for the MCP tool the right call? I followed the existing
DEFAULT_MCP_TOOLS philosophy, but open to other opinions.
- Should the CLI exit non-zero on cycles? This makes it git-hook ready but could be surprising if someone just wants to see the cycles. The
--json flag provides machine-readable output.
- Anything else you'd want to see before merging?
Happy to open a PR if the direction looks right.
Problem
I've been using CodeGraph to navigate a large TypeScript monorepo, and circular imports have been a recurring pain point — they cause build failures with
tsc, slow down bundlers, and create maintenance traps where refactoring one module breaks another in non-obvious ways.I went looking for a tool to catch these cycles early and discovered something interesting: CodeGraph already has a complete circular import detector buried in the codebase — it's just never called.
Evidence
The detector lives at
src/graph/queries.ts:225:It's re-exported on the
CodeGraphclass atsrc/index.ts:1017. The algorithm is complete, well-tested, and handles multi-cycle graphs correctly.But it has zero callers. It's dead code — implemented but never wired to any output channel.
I verified this by grepping the entire codebase:
Only the definition and re-export. No function ever calls it.
Why This Matters
Circular imports are one of those problems that:
Having a tool that catches them before CI would save significant debugging time. CodeGraph already has the graph data needed to detect them — the algorithm is sitting right there.
Proposed Solution
Surface
findCircularDependencies()on two channels:1. MCP tool:
codegraph_checkA new tool that AI agents can call to detect circular imports in the current project.
Output (markdown, sorted deterministically):
When no cycles exist:
Key design decision: Ship functional but NOT in
DEFAULT_MCP_TOOLS. Rationale: CLAUDE.md documents extensive eval evidence that agents under-pick new tools, and adding to the default surface without proven demand could dilute tool selection. The tool is callable — agents just need to know it exists.2. CLI subcommand:
codegraph check [path]A deterministic, user-invoked command for developers.
Exit behavior:
This makes it git-hook ready:
Implementation Scope
5 files, ~340 lines, 0 deletions:
src/mcp/tools.tshandleCheckhandlersrc/bin/codegraph.tscheck [path]subcommand__tests__/mcp-check-circular-imports.test.ts__tests__/cli-check.test.tsCHANGELOG.md[Unreleased]entryNo schema changes. No breaking changes. No new dependencies.
What I Need
I have the implementation ready on a branch (
feat/codegraph-check-circular-imports). Looking for feedback on:DEFAULT_MCP_TOOLSphilosophy, but open to other opinions.--jsonflag provides machine-readable output.Happy to open a PR if the direction looks right.