Skip to content
CodeMorph
Esc
  • No results: ""

Scan & Plan in depth

Exactly how CodeMorph reads your project, resolves every import, builds the dependency graph and turns it into leaf-first batches.

Scan & Plan is the foundation of every migration. It reads your project, builds a dependency graph and turns that graph into an ordered plan. It's fully local, needs no API key and never changes a file.

Start it with Start Migration in the Morph panel or Ctrl Shift M.

1. Finding files

CodeMorph walks your workspace folder and collects source files with these extensions:

.js · .jsx · .mjs · .cjs · .ts · .tsx

It skips:

  • Anything ignored by git. Every .gitignore from your repository root down to the workspace folder is applied, including nested ones, so node_modules, dist and other build output never enter the graph.
  • Files over 1 MB. These are almost always generated or bundled code. They're listed as skipped rather than slowing the scan.

In a multi-root workspace, the first folder is scanned.

2. Parsing

Each file is parsed with tree-sitter, using grammars for JavaScript, JSX, TypeScript and TSX. tree-sitter is fast and error-tolerant: a file with a syntax error still produces a usable tree, and CodeMorph records that the file has errors instead of failing the scan.

From each tree CodeMorph extracts:

  • Imports: import statements, import() calls and require() calls, including destructured requires.
  • Exports: named and default exports, module.exports and exports.x, and re-exports such as export * from and export { x } from.
  • Declarations: functions, classes, variables, types and interfaces, with their line ranges and whether they're exported.

3. Resolving imports

Every import specifier is resolved to a target, using the same rules your toolchain does. The first match wins:

  1. Path aliases. If the specifier matches compilerOptions.paths in tsconfig.json or jsconfig.json, it's rewritten against baseUrl.
  2. The exact path, relative to the importing file.
  3. Extensions, tried in this order: .ts, .tsx, .js, .jsx, .mjs, .cjs.
  4. Index files: the same extensions under /index.
  5. TypeScript-style specifiers. Under NodeNext rules an import of ./dep.js may refer to dep.ts, so .js also matches .ts and .tsx, .jsx matches .tsx, .mjs matches .mts and .cjs matches .cts.

How each import is classified

ClassificationMeaningExample
Local fileResolved to a file in your project./lib/db → src/lib/db.js
Built-inA Node.js built-in modulefs, node:path
PackageA dependency listed in package.jsonexpress, @scope/pkg/sub
AssetA non-code file./styles.css, ./data.json
UnresolvedCouldn't be resolved, with a reasona missing file, or a package not in package.json

Each import edge also records whether it's dynamic (import()), type-only (import type), side-effect only (import "./polyfill") or a re-export, and exactly which names it brings in.

4. The graph

Everything is stored in a local SQLite database:

  • Files with language, lines of code, a content hash, and flags for test files (.test., .spec., __tests__/), entry points (from main and module in package.json) and syntax errors.
  • Symbols with kind, line range and export status.
  • Edges between files, packages, built-ins and assets.
  • Packages from package.json, with versions.
  • Unresolved imports with their reasons.

Morph uses this graph as context when it converts files and answers questions.

5. Planning

The plan is computed from the file-to-file edges:

  1. Strongly connected components. Tarjan's algorithm groups files that import each other in a cycle into a single component. A cycle can only be typed as a whole, so it's never split.
  2. Topological order. Tarjan's algorithm emits a component only after every component it depends on, which gives a leaf-first order: files with no local imports first, your entry point last.
  3. Batches. Components are packed into batches of about ten files. Batch size is for pacing and review; the order underneath never changes.

Only JavaScript files go into batches. Existing TypeScript files are already typed and count toward the typed total.

6. Reading the plan

Plan ready. 38 files in 4 batches. Leaf modules first, so types flow upward through your imports.

You seeIt means
JS filesHow many files will be converted
BatchesHow many review sittings the migration takes
Import edgesHow connected the project is
Batch namesThe folders each batch covers, such as lib/ · utilities or api/ + middleware/

From here you can Start migration or Edit plan.

Scan & Plan building a dependency graph

Re-scanning

Run Scan & Plan again any time your code changes significantly, for example after merging a big branch. Scanning is fast and always reflects the current files on disk.

Something unclear or out of date? Tell us.