Path inspection
Dependency Queries
Use somepath and allpaths to explain dependency paths through the same graph Codescythe analyzes.
Commands
The query command traces dependency paths between two selectors without changing analysis results or editing files. It uses the same parsed import, export, resolver, alias, dynamic import, and glob edges as normal analysis.
npx codescythe query somepath \
src/main.ts \
src/module.ts
npx codescythe query somepath \
src/main.ts \
src/features/
npx codescythe query allpaths \
src/main.ts \
src/runtime.ts:initRuntimesomepathReturns one shortest dependency path for each reachable matched target. File and export targets usually match one node; directory targets can match many.
allpathsReturns every node and edge that lies on at least one route from the source selector to the target selector.
import-conflictsLists resolved modules reached through runtime-static and dynamic paths from the same configured entrypoint. Exits with status 1 when findings exist.
Static/Dynamic Import Conflicts
Use import-conflicts when a module intended as a lazy boundary may also be pulled into the runtime graph eagerly. Each finding prints the resolved target, every conflicting importer, and every entrypoint with a conflict proof.
npx codescythe query import-conflicts \
-C . \
--config codescythe.json
Found 1 module with runtime static/dynamic import conflicts:
src/module.ts
runtime static imports:
src/main.ts -- named import ./module
dynamic imports:
src/main.ts -- dynamic import ./module
conflicting entrypoints (1; 0 alternate routes):
src/main.ts
shortest conflicting entrypoint route (src/main.ts):
runtime static path:
src/main.ts
-- named import ./module:value -> src/module.ts:value
-- defined in file value -> src/module.ts
dynamic path:
src/main.ts
-- dynamic import ./module -> src/module.tsRuntime-static edges include named imports, side-effect imports, re-exports, and namespace imports or member access. Dynamic edges come from supported string-literal import() calls. Type-only imports remain visible as typeImport edges in path queries but are excluded here because they do not affect runtime bundling. Configured test files are also excluded.
A finding is reported only when one configured entrypoint can reach the target through runtime-static edges and can also reach a dynamic importer of that target. Output lists every entrypoint with such a proof. By default it prints the shortest proof overall; pass --all-paths to print one shortest proof per conflicting entrypoint. This avoids treating imports isolated in separate entrypoint graphs as conflicts while making alternate roots visible.
Suppress one intentional static/dynamic overlap with a required reason:
// codescythe-ignore-next-line import-conflict -- dedicated entrypoint preload
import { Page } from "./Page";The edge remains in graph traversal, so conflicts below the preloaded module still report. Only the annotated importer and resolved target pair is suppressed.
When a dedicated entrypoint intentionally preloads the module’s full static dependency tree, use the preload form:
// codescythe-ignore-next-line import-conflict-preload -- dedicated finance bundle
import { FinanceRouter } from "./FinanceRouter";Conflict proofs that require this edge on their static path are suppressed, including downstream modules. Another static path that avoids the annotated edge still reports, whether it starts from the same entrypoint or another one. Both directives require a reason after --. Text output reports the number of suppressed modules, and JSON exposes it as suppressedConflictCount. JSON also includes entrypoints, alternateEntrypointRouteCount, and alternateEntrypointRoutes when alternate proofs exist.
The command exits with status 1 when findings exist and 0 when the scan is clean. Use --json for CI or scripted cleanup. Fix the listed runtime-static edges, rerun the command, and confirm the target disappears.
{
"scannedFileCount": 2,
"entrypointCount": 1,
"suppressedConflictCount": 0,
"conflicts": [
{
"target": "src/module.ts",
"runtimeStaticImports": [
{
"importer": "src/main.ts",
"specifier": "./module",
"kind": "namedImport"
}
],
"dynamicImports": [
{
"importer": "src/main.ts",
"specifier": "./module",
"kind": "dynamicImport"
}
],
"entrypoints": ["src/main.ts"],
"alternateEntrypointRouteCount": 0,
"entrypointRoute": {
"entrypoint": "src/main.ts",
"runtimeStaticPath": {
"nodes": [
{ "id": "file:src/main.ts", "kind": "file", "path": "src/main.ts" },
{ "id": "export:src/module.ts:value", "kind": "export", "path": "src/module.ts", "symbol": "value" },
{ "id": "file:src/module.ts", "kind": "file", "path": "src/module.ts" }
],
"edges": [
{
"from": "file:src/main.ts",
"to": "export:src/module.ts:value",
"kind": "namedImport",
"importer": "src/main.ts",
"specifier": "./module",
"imported": "value"
},
{
"from": "export:src/module.ts:value",
"to": "file:src/module.ts",
"kind": "exportDefinition",
"imported": "value"
}
]
},
"dynamicPath": {
"nodes": [
{ "id": "file:src/main.ts", "kind": "file", "path": "src/main.ts" },
{ "id": "file:src/module.ts", "kind": "file", "path": "src/module.ts" }
],
"edges": [
{
"from": "file:src/main.ts",
"to": "file:src/module.ts",
"kind": "dynamicImport",
"importer": "src/main.ts",
"specifier": "./module"
}
]
}
}
}
]
}Selectors
Selectors can point at files, directories, or exported symbols. Relative selectors are resolved from the analysis root selected by -C or --config.
src/main.tsselects a project file.src/features/selects every project file under a directory.src/module.ts:usedselects one exported symbol from a file.
Output Formats
Text output is optimized for terminal inspection. It prints the resolved selector kinds, match counts, the returned path or path graph, and a summary line with path and reachability counts. JSON is the stable machine-readable surface and includes the same diagnostics. Mermaid and SVG render the same query graph as a diagram.
npx codescythe query allpaths \
--output text \
src/main.ts \
src/runtime.ts:initRuntime
npx codescythe query allpaths \
--json \
src/main.ts \
src/runtime.ts:initRuntime
npx codescythe query allpaths \
--output mermaid \
src/main.ts \
src/runtime.ts:initRuntime
npx codescythe query allpaths \
--output svg \
src/main.ts \
src/runtime.ts:initRuntime > graph.svg--json is a shortcut for --output json. SVG output is rendered from the Mermaid graph with mermaid-rs-renderer.
--include-unresolved adds every unresolved import discovered while building the graph. Use --include-unresolved=related when you only want unresolved imports from the query endpoints and returned path graph files.
From selector: src/main.ts (file selector, 1 matched node)
To selector: src/module.ts:used (export selector, 1 matched node)
src/main.ts
-- named import ./module:used -> src/module.ts:used
Summary: pathNodes=2, pathEdges=1, reachableFromSource=3/12, reachableToTarget=2/12, unresolvedImports=0Fixture Examples
These examples are generated from checked-in repository fixtures. The Mermaid snippets below are exact CLI output from --output mermaid.
test-file-usage: somepath to one export
A file-to-export query shows a named import edge directly to the exported symbol.
codescythe query somepath \
-C tests/fixtures/test-file-usage \
--output mermaid \
src/main.ts \
src/module.ts:usedflowchart LR
n0["src/module.ts:used"]
n1["src/main.ts"]
n1 -->|"named import ./module:used"| n0oxc-resolution: somepath to a folder
A file-to-directory query returns one shortest path for each reachable matched target file.
codescythe query somepath \
-C tests/fixtures/oxc-resolution \
--output mermaid \
app/index.ts \
app/flowchart LR
n0["app/aliased.ts:aliased"]
n1["app/extension.ts:extension"]
n2["app/internal.ts:internal"]
n3["app/aliased.ts"]
n4["app/extension.ts"]
n5["app/index.ts"]
n6["app/internal.ts"]
n0 -->|"defined in file aliased"| n3
n1 -->|"defined in file extension"| n4
n2 -->|"defined in file internal"| n6
n5 -->|"named import @/aliased:aliased"| n0
n5 -->|"named import ./extension.js:extension"| n1
n5 -->|"named import #internal:internal"| n2knip-export-basics: allpaths through namespace use
An allpaths query keeps every node and edge that can carry the source file to the target export.
codescythe query allpaths \
-C tests/fixtures/knip-export-basics \
--output mermaid \
index.ts \
my-namespace.ts:yflowchart LR
n0["index.ts"]
n1["my-module.ts"]
n2["my-module.ts:myExport"]
n3["my-namespace.ts:y"]
n2 -->|"defined in file myExport"| n1
n0 -->|"named import ./my-module.js:myExport"| n2
n1 -->|"namespace member ./my-namespace.js:y"| n3runfiles-fixture: somepath through an alias
Alias resolution is represented in the edge label, while the target still resolves to the project file export.
codescythe query somepath \
-C tests/fixtures/runfiles-fixture \
--output mermaid \
workspace/frontend/apps/client/platform/platformRuntime.ts \
protobuf/generated/client.ts:clientflowchart LR
n0["protobuf/generated/client.ts:client"]
n1["workspace/frontend/apps/client/platform/platformRuntime.ts"]
n1 -->|"named import #bazel_generated/client:client"| n0Cycles
Dependency cycles are finite in query output. somepath runs breadth-first search with visited nodes and parent edges, so it returns shortest acyclic paths. allpaths does not enumerate paths; it intersects forward reachability from the source with reverse reachability from the target, then returns the induced path subgraph.
