← Back September 30, 2026

Re-Introducing Carrick

TypeScript codebase intelligence for AI agents & IDEs

A lone figure standing on a pale platform above a vast crowd, beneath a dark wall of curved lines sweeping around the scene

In early 2025 I wrote a blog post about making TypeScript work across repository boundaries. At the time coding agents were in their infancy, Claude Code was just starting to gain traction, and it wasn’t clear (to me at least) that this multi-agent future was where we were headed. In that moment I was focused on a narrow problem that I had chosen after many years in industry as a SWE, seeing the same failure modes, repeatedly. The concept was simple - could I catch developers breaking API contracts with the type checker and raise those errors in CI without shared types, specific protocols or testing frameworks? The developer just writes the code and a programme would stitch together the parts that communicated across the system and shout loudly when they weren’t in sync. Unsurprisingly this was…complicated. I had a working prototype, but the blocker was identifying call sites and API definitions. Thankfully AI happened to be very good at code classification, even in the early days, so I knew the direction this had to travel in - part deterministic, part probabilistic, but I had run out of time and needed to move onto other projects.

I started working at an AI startup, and as the development ramped up, and the concurrent agent sessions started to weigh on me, it was becoming apparent that the failure modes I had always tried to combat were amplified by agents, not removed. On a greenfield codebase, AI coding agents are hugely efficient, but their efficiency gains diminish as the codebase increases. Agents are trained to use tools like Search and Grep, and once a codebase gets past a certain size, it’s easy for them to miss parts of the codebase and make mistakes. The kind of mistakes a seasoned developer would pick up in code review, but the sheer quantity of agent output makes this impossible.

This experience heavily informed my thinking around how an agent native developer tool should perform. What if I could identify and correct these failure modes that are common to both humans and agents? So promote code reuse, an understanding of API usage across a code base, and how functions are used and consumed? The answer was sitting in my early 2025 explorations into correcting cross service failures. The answer was the TypeScript compiler.

When tsc compiles your code it builds a complete model of the program along the way. It follows every import, resolves every symbol to its declaration and infers types wherever there’s no annotation, and that model is what your editor reads from when you hit Go to Definition or Find References.

For an agent, there are two fundamental problems with how standard tooling works. First, the language service answers questions about a specific position in a file (what type sits on this line, or where a symbol is defined), but an agent is usually looking for behaviour. An agent about to write something new has no file position to query, so it falls back to grep for a name it guesses might exist. Second, the compiler's view stops at project boundaries. Between a frontend and backend, or across services in a monorepo or polyrepo, each service is compiled in isolation. Types are copied, manually typed, or asserted with as, leaving tsc with no cross-boundary visibility to catch subtle type drift.

Carrick handles the first problem with semantic search. During a scan, a model runs through every function across your project and composes a concise description of what it actually does. Those descriptions are vectorised, so an agent can search by what code does rather than what it’s called. If it asks for something like “check if a user’s subscription is active”, it gets back the code that does exactly that, whatever it happens to be named, and can reuse it instead of writing a duplicate.

For the second, Carrick doesn't just read type definitions statically. It taps directly into the TypeScript compiler across each service to record the actual types emitted by route handlers on one side and the types expected at call sites on the other, along with every declaration they depend on. It then dynamically stitches both sides into a single program and lets tsc test assignability directly. If a copied type drifts, or an as assertion no longer holds, tsc flags the incompatibility across service boundaries exactly as if it were sitting in a single file.

All of this reaches agents over MCP (the Model Context Protocol), so Claude Code, Cursor, Windsurf, Codex, and any other MCP-compatible tool can query it in the middle of a task. Before an agent writes a helper, it can check whether an implementation already exists, and before it modifies an endpoint, it can inspect the real request/response shapes and see every consumer that depends on it.

The same index now shows up across three core surfaces:

  1. In your agent: MCP tools to search by intent, inspect exact types on either side of a call, and navigate service dependencies.
  2. In your editor: Jump from a fetch call directly to its handler in another service, view route consumers, and surface cross-service type mismatches as live diagnostics in VS Code, Cursor, Windsurf, or any LSP-compatible editor.
  3. In your pull requests: Automated CI checks that flag contract mismatches and dependency version drift before code hits main.

An agent is only as good as the context it works from, and on a large codebase, that context is usually whatever it happened to grep. Carrick replaces guesswork with the compiler’s view of the entire system.

Under the hood, it's a Rust scanner built on SWC that integrates deeply with the TypeScript compiler, paired with an inference pipeline that maps function intent and inter-service relationships. It ships with a unified language server, 17 dedicated MCP tools, and four targeted agent skills (impact, reuse, drift, and census) built specifically to prevent common failure modes like breaking downstream callers or duplicating existing logic.

The scanner is source-available and runs seamlessly from your CLI or directly inside CI.

Getting Started

Carrick is free up to 5,000 indexed functions (roughly 150,000 lines of TypeScript), which covers most small to medium systems, and you don’t need a card. For bigger systems, the paid plans start with a 30-day free trial.

To set up your workspace, install the CLI and run carrick init:

npm install -g carrick
carrick init

The quickstart guide covers the rest, and there’s more on how it all works at carrick.tools.