--incremental Made My TypeScript Hook 3. 6x Slower. A 200KB Threshold Fixed It

A solo developer built an autonomous Claude Code setup that earned ¥1.2M/month. The key to scaling was a clever TypeScript hook that switches between incremental and normal mode based on a 200KB cache size. This switch eliminates the 3.6x slowdown seen in large projects, keeping verification fast a…

When a solo developer in Tokyo started freelancing during college, he earned ¥100,000 a month. By stacking side gigs he reached ¥600,000, only to be laid off and drop to zero overnight. Within six months he rebuilt his income with an autonomous Claude Code system that now nets ¥1.2 million per month. The story is not just about revenue; it’s about the technical hurdle that nearly stalled the entire operation: a TypeScript compiler that made code slower when he tried to make it faster.

Why Verification Slows Down

In a solo dev environment, the biggest bottleneck is not how fast you write code, but how quickly you can verify it. A type error caught immediately after you type it can be fixed in a minute. If you notice it 30 seconds later, you have to reload context from memory. By the time you’re 60 seconds out, you’re already drifting into a new task, and the context switch cost spikes. Claude Code solves this by hooking into the compiler: after every tool execution, a PostToolUse hook runs a tsc --noEmit check. If the compiler reports an error, the hook feeds that feedback straight back into the next instruction, closing the “write‑then‑verify” loop without human intervention.

The Cold‑Start Problem

The TypeScript compiler loads the entire dependency graph on startup. With a handful of files it’s quick, but as imports chain out, the graph can balloon into hundreds of modules. Re‑parsing from scratch each time costs 30–60 seconds on a project called closet‑os. A hook that blocks for a minute on every tool call turns an autonomous system into a bottleneck. The solution is the --incremental flag, which performs a full analysis only once and caches the result in a .tsbuildinfo file. Subsequent runs re‑analyze only the diff, cutting runtimes to 1–3 seconds for small changes.

When Incremental Backfires

Adding --incremental to the closet‑os hook made cold runs 3.6 times slower. The culprit was the growing .tsbuildinfo file. As the project grew, generating the incremental diff data became expensive, and reading a large JSON file on every run added overhead that outweighed the diff benefit. For small‑to‑medium projects incremental wins, but for large ones plain --noEmit is faster. The hook needed a way to decide automatically which mode to use.

The 200KB Threshold Guard

Observing that the cache file size correlated strongly with project size, the developer introduced a one‑line guard: if the .tsbuildinfo file exceeds 200 KB, fall back to normal mode. The threshold was set empirically—at 200 KB the incremental mode started to slow down, while smaller projects stayed fast. The hook’s logic now checks the file size before deciding whether to add --incremental to the compiler arguments.

The full flow of the hook is:

  • Exit immediately if tsconfig.json is missing.
  • Determine the timeout command (macOS may use gtimeout or timeout).
  • Check the .tsbuildinfo size; use incremental if ≤200 KB, otherwise normal.
  • Run tsc --noEmit --pretty false (with or without --incremental).
  • If the compiler times out, emit a warning and exit 0.
  • If there are type errors, prefix the output with === TypeScript型エラー検出 === and exit 0.
  • Otherwise exit 0 with no output.

Key Implementation Details

1. The script lives in node_modules/.cache/tsc-hook.tsbuildinfo to avoid conflicts with the project’s own build cache. 2. The size check uses stat -f %z on macOS (or stat -c %s on Linux) to get the file size in bytes. 3. The hook captures both stdout and stderr, then pipes the output through head -30 to limit the amount of data sent to the agent. 4. It always returns exit code 0, even when type errors are present, so Claude Code continues its tool execution loop. 5. The script is only 61 lines long, making it easy to copy into other projects.

Common Pitfalls and Fixes

  • Pipe exit code confusion: In a pipeline, $? returns the exit code of the last command. The hook uses a timeout wrapper so that tsc’s exit code is preserved.
  • macOS stat syntax: The original script used stat -c %s, which fails on macOS. Switching to stat -f %z fixes the size check.
  • Exiting with 1: Returning 1 on type errors stops Claude Code’s loop. The hook now returns 0 and only prints errors.

By combining a smart cache size guard with careful shell scripting, the developer turned a 3.6× slowdown into a smooth, 1–3 second verification cycle. The result is a fully autonomous workflow that keeps verification fast, even as the codebase grows.

What Happens Next

The hook is now part of the standard Claude Code setup and can be dropped into any TypeScript project. Future work includes adding a dynamic threshold that adapts to machine performance and exploring parallel compilation for even larger codebases.

Why This Matters

For solo developers, verification latency can turn a simple code change into a productivity nightmare. A small, data‑driven tweak—like the 200 KB threshold—can unlock hours of saved time and keep an autonomous system running smoothly.

Takeaways

  • Verification latency is often the real bottleneck, not code writing speed.
  • Incremental builds help, but only up to a point; cache size matters.
  • A simple file‑size guard can automatically choose the fastest mode.
  • Always return exit code 0 from hooks to avoid breaking the tool loop.
  • Keep scripts short and portable to ease adoption across projects.

FAQs

  • What if my project never reaches 200 KB? The hook will always use incremental mode, giving you the fastest possible checks.
  • Can I change the threshold? Yes—edit the 204800 constant in the script to a different byte count.
  • Will this work on Windows? The script uses POSIX commands; on Windows you’ll need a compatible shell or adapt the commands.
  • Why use head -30? It limits the output to the first 30 lines, preventing large error dumps from bloating the agent’s log.
  • Does this affect production builds? No—--noEmit only checks types; it does not produce output files.

Why it matters

By automating type checking with a smart incremental strategy, solo developers can keep verification fast and avoid costly context switches, directly boosting productivity and revenue.

Key points

  • Verification latency is the main bottleneck for solo devs
  • Incremental builds help only until cache size grows too large
  • A 200 KB cache guard automatically selects the fastest mode
  • Always return exit code 0 to keep tool loops running
  • Short, portable scripts ease adoption

Frequently asked questions

What if my project never reaches 200 KB?

The hook will always use incremental mode, giving you the fastest possible checks.

Can I change the threshold?

Yes—edit the 204800 constant in the script to a different byte count.

Will this work on Windows?

The script uses POSIX commands; on Windows you’ll need a compatible shell or adapt the commands.

Why use head -30?

It limits the output to the first 30 lines, preventing large error dumps from bloating the agent’s log.

Does this affect production builds?

No—--noEmit only checks types; it does not produce output files.

Reporting drawn from

More from World

Felo News, House 42, Bridge Colony, Kot Lakhpat, Lahore, Pakistan
+92 308 4354717 · felopronews@gmail.com