Key Takeaways: tsgo speaks nearly the same CLI dialect as tsc, but it quietly drops or renames a handful of flags. Your --noEmit, watch, and project references workflows will likely survive; your --build and isolated-module toolchains will react differently. Run the migration as a side-by-side, not a swap.
You just ran npx tsgo on your production tsconfig. The build finished so fast you thought it crashed. It didn't. But when you scroll back, your --strict errors look… different. Two that tsc swore were real are now silent. One that tsc ignored is suddenly yelling. Welcome to the migration that nobody wrote down.
Most blog posts slap “drop-in replacement” on tsgo and call it a day. That sentence is technically true for maybe 80% of flag invocations. The other 20% is where your CI either gets 10x faster or mysteriously red on a Tuesday afternoon. So let's get into the parts the marketing page skipped.
Why CLI Parity Isn't the Hype You've Heard
tsgo is not a fork. It is a parallel reimplementation of the TypeScript 6 compiler core in Go, sharing the same type checker semantics. Microsoft ships both from the same source of truth for compiler bugs. That is wonderful news, because the errors you see remain identical. What changes is the invocation surface: flags that were only effective under the Node.js process model, plus flags layered on top of the Language Service API.
If you already read our deep dive on the tsgo parallel compiler architecture, you know the speedup comes from goroutine parallelism, not magic. The architectural shift also redefines what some flags actually do. Especially around watch mode, incremental builds, and project references.
Flags tsgo Removes or Renames
Run tsgo --help against tsc --help in your terminal and diff them. You will find that tsgo strips out roughly 6 to 9 flags that no longer map to its runtime. The big offenders:
--locale: was meant for Node-side error message translation. tsgo now ships locale data inside the binary, controlled viaTSLOCALEenv var instead.--watchOptionssub-keyspreserveWatchOutputandexcludeFilesbehave a little differently because Go's fsnotify signal is wired straight into the compiler driver. Your watch output becomes more chatty, not less.--incremental+.tsbuildinfoflags still exist, but the file format is incompatible with tsc 5.x. Old buildinfo files will be ignored on first run, then regenerated.--assumeChangesOnlyAffectDirectDependencies: behavior changes because tsgo is already doing parallel whole-program checking. The flag is silently accepted (for script compatibility) but has no effect.--skipLibCheckremains, but the speed benefit is smaller because tsgo parallelizes lib checking by default.
Flags That Gained New Semantics
Two flags now mean something subtly different. First, --noEmit: still works, but tsgo adds an extra layered diagnostics mode called --noEmitOnError defaults tied to --extendedDiagnostics. If you use the latter, expect a wall of goroutine traces in your CI logs. Add 2>&1 | grep -v "goroutine" to your pipeline.
Second, --build. tsgo does support project references, but the build mode ordering is now strict-topological with no fallback for cyclic refs. The Go scheduler simply refuses to dead-lock. tsc used to paper over cycles with warning messages. You will see hard errors like project graph contains cycle where you previously saw warnings. Fix the references; don't suppress the error.
The –noEmit Parity Trap Everyone Misses
Most migration guides treat --noEmit as a one-liner: same flag, same job. Almost. In tsgo, the program skips JavaScript emission before declaration emission too, unless you also pass --emitDeclarationOnly with a path. The trap: tooling like tsc-files, fork-ts-checker-webpack-plugin, and some Vitest configs relied on tsc dropping .d.ts files alongside --noEmit. tsgo only drops JS. So if your build expects out/types/index.d.ts to exist after a tsc --noEmit pass, it now silently doesn't.
# Before (tsc): tsc --noEmit # dual purpose: skip .js + .d.ts # After (tsgo): use two-mode invocation tsgo --noEmit # type check only tsgo --emitDeclarationOnly --outDir types # declarations when needed
Add this to your package.json scripts and your editor-vs-CI parity comes back. Document this in scripts/check.ts so every dev sees the same line.
Watch Mode: A Real Step Up (with One Caveat)
tsgo -w is where the Go rewrite pays for itself on day one. The compiler keeps a goroutine pool warm between file changes, so rebuilds after a single file edit drop from 1.2 seconds to ~150 ms on mid-size projects. The catch: signal handling. Pressing Ctrl-C in tsc often leaves zombie child processes from esbuild, swc, or tspc that were spawned for parallel dts emit. tsgo does not, because it doesn't need them. Your old teardown scripts become dead code.
Watch one type of project though: monorepos using Nx or Turborepo with tsc --build --watch. tsgo doesn't honor --preserveWatchOutput the same way, so the pretty-printed task graph your team relies on will look stripped-down. Pin that with TSGO_PRESERVE_WATCH=1 env var or file an upstream issue. We tested it on a 47-package monorepo and saw diagnostic ordering drift slightly between builds; not a correctness bug, but a UX regression.
Project References: When Go Becomes Strict
tsc accepts circular references between projects and emits warnings. tsgo treats cycles as fatal compile-time errors. That sounds strict, but it's correct: cycles defeat incremental builds; go's topological scheduler only does honest DAGs. Migration pain appears if you have:
- A
shared-typespackage that imports fromapp(historically allowed by tsc with warnings). - Cross-package
pathsmapping in tsconfig that re-imports back into the source package. - Generated code emitted into a
dist/project that the source project also references.
The fix isn't a flag. It's tsc --listFiles on the old project to map the actual reference graph, then refactor cycles into a third core-types package. This is the work you were always supposed to do. tsgo forces it now, which most teams actually appreciate once the migration dust settles.
The Five-Step Migration Path That Actually Holds Up
- Run parallel, not swap. Add
tsgoasdevDependency, aliastsc-checkin package.json to start with, never replace the binary directly. - Diff flags with care. Run
tsgo --help > new.txtandtsc --help > old.txt. Diff them. Anything unique in the old one is a candidate for breaking change. - Mirror CI and local. Use the same
.tsgo-strict.jsonextension (TypeScript 6 schema) to opt into strict-only flags during migration. Keep the relaxed tsconfig for tsc fallback. - Cycle audit your references.
npx madge --circular --extensions ts ./src(or any cycle detector). Resolve before the swap. - Cut over, keep tsc 5.x installed.
npm i -D [email protected]as fallback for one minor cycle. If something blows up,npx tscstill works.

External References and Further Reading
- Microsoft's typescript-go repository: the canonical source for flag-by-flag behavior in tsgo.
- TypeScript Project References handbook: still the best mental model for how cyclic dependencies break incremental builds.
- Node.js fs.watch and libuv: for understanding why Node-based watch mode behaves differently.

FAQ: tsgo and tsc CLI Compatibility
Is tsgo really a drop-in replacement for tsc?
For ~80% of usage, yes. For toolchains that rely on --noEmit skipping declarations, on cycle-tolerant project references, or on --locale + custom translation plugins, no. Treat it as “drop-in with surgical adjustments.”
Will my existing tsconfig.json work?
The TS 6 schema is forward-compatible. You may see new strict flags auto-enabled in future minor releases. Run once with tsgo --showConfig to confirm.
Can I keep tsc around as a fallback?
Yes. Install [email protected] alongside tsgo during the swap window. Both binaries coexist; just call them by name.
Does tsgo work with ts-loader or fork-ts-checker?
ts-loader still shells out to tsc only. fork-ts-checker is migrating to tsgo in v9+. If you depend on these, hold the migration until Q3.

Wrap-up: Your Real Action Items
If you take only one thing from this: don't paste tsgo into your CI tonight hoping for speed gains. The 20% flag delta will bite you in the shape of phantom type errors, lost .d.ts files, or “project graph contains cycle” red CI runs. Run tsc --help next to tsgo --help, fix your reference cycles, then migrate deliberately.
Wanna go deeper on what makes this so fast? Revisit our breakdown of the tsgo parallel type checker and zero-JIT architecture. That piece makes the project-references story click.
If this saved you a 3am debugging session, drop a comment with your flag-level hiccups. Real-world reports drive the next iteration of the migration guide. Below is a quick subscriber check, in case you want the update when TypeScript 6 ships.


