fallow trace
See what calls an exported symbol and what it calls before you change it, or find how one module comes to import another. Fallow trace is a best-effort command, separate from the ranked review brief.
Before you change an exported symbol, use fallow trace to see how it connects to the rest of the codebase. The command walks the call chain of one symbol in two directions, up to --depth:
- Callers, up: the modules that import the symbol.
- Callees, down: the import-symbol edges, plus the call sites in the same module.
fallow trace src/api.ts:fetchUser --format json --quiet
fallow trace src/api.ts:fetchUser --callers --depth 2
fallow trace --path src/app.ts src/db.ts
--path answers a different question: which chain of imports connects one module to another. See Import path between two modules.
fallow trace is a standalone, best-effort command. Its results are not part of the ranked review brief, and they never change the focus map or its ranking. Use trace to see how a symbol connects. For a prioritized review, use the review brief.
Target
fallow trace takes one positional argument in FILE:SYMBOL form:
fallow trace src/api.ts:fetchUser
FILE is a project-relative path, and SYMBOL is the exported symbol name. When you pass --path, omit this argument. --path takes two file paths.
When a file exists at the exact path from the project root, fallow takes that file. src/api.ts then never selects packages/x/src/api.ts. When no file has the exact path, fallow accepts a path suffix. A short path that matches more than one file takes the first match, so use the full project-relative path in a monorepo.
Options
| Flag | Description |
|---|---|
--callers | Walk only the callers direction. |
--callees | Walk only the callees direction. |
--depth <N> | Maximum walk depth in each requested direction (default: 2). |
--path <FROM> <TO> | Find the shortest import path between two modules. You cannot use it with the FILE:SYMBOL target, --callers, --callees, or --depth. |
--eager-only | With --path, follow only static imports that carry a runtime value. The route shows why TO loads before FROM runs. |
Without --callers or --callees, fallow walks both directions. trace also accepts the project, output, and performance global flags: --root, --config, --format with human or json, --quiet, --no-cache, --threads, and --changed-since.
How it works
The walk is best-effort and syntactic. Fallow reports resolved and unresolved callees. An unresolved callee, for example a dynamic call that fallow cannot resolve statically, stays in the output as unresolved. The chain thus shows what fallow could follow and what it could not.
When code references the same export in type space and in value space, the JSON output adds direct_references_by_namespace. This field has separate evidence for each namespace. For compatibility, namespace and direct_references keep their earlier meaning: they describe only the winning namespace. When only one namespace has references, fallow omits direct_references_by_namespace. Read a missing field as the usual case of one namespace.
Ambiguous star exports
When two export * sources both give the requested name, the barrel exports
nothing under that name. The JSON output reports symbol_found: false and adds a
star_export_ambiguity object:
{
"symbol_found": false,
"star_export_ambiguity": {
"sources": ["src/models/admin.ts", "src/models/customer.ts"],
"namespaces": ["type"]
}
}
sources lists the files that declare the name, sorted, as project-relative paths.
namespaces tells you if the collision is in type space, value space,
or both, with type before value. With this object, you can tell a barrel
collision from an unknown or misspelled symbol. To fix the collision, keep one
origin and rename the others, or replace the star exports with explicit re-exports.
You can also get the same best-effort call-chain data as opt-in evidence from fallow inspect --symbol-chain and from the symbol_chain option of the inspect_target MCP tool.
Import path between two modules
Use --path to find out why a module depends on another module. fallow trace --path <FROM> <TO> reports the shortest chain of imports from FROM to TO. Both are project-relative file paths.
An exact project-relative or absolute path wins over a suffix match. Fallow accepts an abbreviation only when it identifies one module. A missing or ambiguous endpoint exits with code 2. To remove the ambiguity, use the full project-relative path.
Shortest import path (syntactic; OFF the ranked path)
from: pages/report.tsx
to: components/Box.tsx
hops: 3
[1] pages/report.tsx:20 -> lib/related.transform.ts
[2] lib/related.transform.ts:1 -> components/RelatedContent.tsx
[3] components/RelatedContent.tsx:3 -> components/Box.tsx
The JSON output has the same walk under kind: "trace", with its own schema_version:
{
"kind": "trace",
"schema_version": "1",
"from": "pages/report.tsx",
"to": "components/Box.tsx",
"reachable": true,
"hops": 3,
"path": [
{
"from": "pages/report.tsx",
"to": "lib/related.transform.ts",
"type_only": false,
"dynamic": false,
"import_line": 20
},
{
"from": "lib/related.transform.ts",
"to": "components/RelatedContent.tsx",
"type_only": false,
"dynamic": false,
"import_line": 1
},
{
"from": "components/RelatedContent.tsx",
"to": "components/Box.tsx",
"type_only": false,
"dynamic": false,
"import_line": 3
}
],
"reason": "pages/report.tsx reaches components/Box.tsx in 3 hops"
}
You can rely on these behaviors:
- Fallow reports a type-only hop with
type_only: trueand does not skip it. A path that exists only in type space is thus visible. - Fallow reports a lazy hop with
dynamic: true. The target of such a hop loads only on demand (import(), a lazy glob) or on another thread (a worker, a fork). The human output tags the hop[dynamic]. - With
--eager-only, the walk follows only static imports that carry a runtime value.import(), lazy globs, worker loads, andimport typedo not qualify. The route explains why a module is in the eager group offallow list --entry-weight. When no such route exists,reachableisfalse. - An unreachable pair is a result, and not an error.
reachableisfalse,pathis empty,hopsis0, andreasonsays that fallow found no import path. The command still exits0. - A trace from a module to itself returns
reachable: truewithhops: 0. The hop count is0in both cases, so branch onreachable.
See also
Get one evidence bundle for a file or exported symbol, with opt-in --symbol-chain.
Get a verdict on changed files, plus the graph-derived review brief and decision surface.
Map runtime stack-trace frames back to the definitions they name.
Use fallow tools from AI coding agents.