project-references-migration
Use when a layered TypeScript workspace needs an incremental project-references migration without breaking package boundaries or editor resolution.
Version
1.0.0
Maturity
draft
Repository
agent-skills
License
GNU GPL v3
Skill metadata
SKILL.md
Project references migration
Use this skill when
- The repository has multiple TypeScript packages or layers and needs faster, more reliable builds.
- The user wants to adopt
tsc -bproject references incrementally. - Declaration output, package boundaries, or editor performance are suffering in a growing TypeScript workspace.
- You need to make the graph coherent enough for
tsc -b, fresh declarations, and editor go-to-definition to agree.
Do not use this skill when
- The repository is a small single-project TypeScript setup.
- The task is only to fix one package's local
tsconfig. - The workspace already has healthy project references and only needs routine maintenance.
- The main goal is strictness hardening or general
tsconfigcleanup rather than adoptingcomposite,references, ortsc -b.
Inputs to gather
Required before editing
- The package or layer graph and their current
tsconfigfiles. - The existing build and typecheck commands.
- Whether each package emits declarations, JavaScript, or types only.
- Output directories, package exports, and path alias usage.
Helpful if present
- Existing workspace tooling such as Nx, Turborepo, pnpm workspaces, or custom scripts.
- Known circular dependencies.
- Editor or CI pain points that motivate the migration.
First move
- Inventory the package graph, current
tsconfigchain, and any obvious cycles. - Pick one leaf or low-risk package as the pilot migration surface.
- Confirm how declarations, outputs, and package boundaries work today before adding references.
- Stop and split the boundary if a proposed reference would create a cycle.
Common shapes
Solution config:
{
"files": [],
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/ui" }
]
}
Pilot package config:
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true,
"rootDir": "src",
"outDir": "dist"
},
"references": [{ "path": "../core" }]
}
Workflow
- Create or normalize a shared base config only for settings that truly belong across referenced packages.
- Enable
compositeand the required declaration settings on the pilot package. - Add explicit
referencesonly where the dependency graph is already real. - Align output directories, package exports, and path aliases with the referenced build layout.
- Migrate packages incrementally from leaves upward.
- Switch scripts to
tsc -bor the repository's equivalent only after the referenced graph is coherent. - If a cycle appears, stop widening and split the dependency before adding more references.
Outputs
- tsconfig and import changes that enable project references without breaking editor or build resolution for the workspace.
- Evidence (build, type-check, or test) that the migration is safe.
Guardrails
- Must not migrate the whole workspace in one leap without a proven pilot.
- Must not introduce circular references to mirror accidental runtime coupling.
- Should keep runtime resolution, package exports, and declaration output aligned.
- Should prefer real package boundaries over giant shared path-alias surfaces.
- May leave exceptional packages on local configs temporarily when the graph is not ready.
- Should treat a repeated cycle or stale output mismatch as a sign to pause migration, not to add another config layer.
Troubleshooting
- If the build succeeds but the editor opens stale declarations, restart the TypeScript server or reopen the workspace after confirming the package graph changed.
- If go-to-definition lands in the wrong emitted folder, verify
rootDir,outDir,declaration, and package exports point at the same build layout. - If outputs land beside source or in an unexpected subdirectory, inspect the package's
tsconfiginheritance before widening the reference graph.
Routing boundary
- Use this skill when a multi-package TypeScript workspace needs a deliberate
composite/referencesmigration path. - Route to
tsconfig-hardeningwhen the task is mainly single-package compiler-option cleanup or strictness tuning. - Route to
tsc-error-triagewhen the references migration has already landed and remaining work is source-level compiler failure triage.
Validation
Run the repository's referenced build or the nearest equivalent after each migration batch.
Confirm declarations and outputs land in the expected locations.
Run the typecheck workflow that consumes cross-package imports, not just the referenced build.
Open a consuming file in the editor when possible, trigger go-to-definition on an imported symbol, and confirm it resolves to the expected referenced package source or fresh declarations rather than stale outputs.
Smoke test:
- should trigger: "Add tsconfig references across our TS packages so tsc -b works."
- should not trigger: "Enable noUncheckedIndexedAccess in one package safely." (→
tsconfig-hardening)
Examples
Before{ "compilerOptions": { "composite": false } }After{ "compilerOptions": { "composite": true, "declaration": true, "declarationMap": true }, "references": [{ "path": "../core" }] }- Pilot one leaf package first, then validate that
tsc -band editor go-to-definition resolve against the fresh declarations instead of stale outputs.
Reference files
references/migration-checklist.md- staged checklist for introducing project references without destabilizing the workspace.