Get started

What Carrick covers

What Carrick scans, the requirements a repo needs to scan cleanly, the framework and protocol story, and the cases that fall outside MVP scope.

Carrick statically scans TypeScript services to extract operations, outbound client calls, and request/response type definitions. It maintains an index of cross-service interfaces that powers diagnostics in your editor, your AI coding agent, and your pull requests.

Supported protocols

Carrick indexes operations and communication patterns across four primary protocols:

REST and HTTP

Carrick extracts route handlers on the producer side and matching client calls (such as fetch, axios, got, and ky) on the consumer side. It pairs producers with consumers based on HTTP method and path patterns, resolving complete TypeScript request and response types for both sides.

GraphQL

Carrick parses Schema Definition Language (SDL) schemas (.graphql, .gql, and gql/graphql tagged template literals) to identify producer fields, and scans executable documents (queries and mutations in .graphql files or tagged templates) to identify consumer operations. Extraction uses a deterministic parser rather than model inference.

Code-first schemas, persisted query manifests, and Relay compiled artefacts are supported when a generated schema.graphql is committed to the repository.

WebSockets

Carrick indexes bidirectional realtime events by event name and direction:

  • Producers: Event listeners such as socket.on("event_name", ...).
  • Consumers: Event emitters such as socket.emit("event_name", ...).

While Socket.IO is the most widely tested client, Carrick supports any realtime library using standard on/emit call shapes. Event names must be string literals. Dynamic event names, custom namespaces (io.of(...)), and reserved lifecycle events (connect, disconnect) are excluded from contract tracking.

Pub/sub

Carrick extracts topic-based messaging operations across message brokers including Kafka, NATS, Redis pub/sub, and BullMQ:

  • Subscribers: Handlers registered for a specific topic act as producers.
  • Publishers: Client calls sending messages to a topic act as consumers.

Operations match on literal topic strings. When a topic payload is decoded using a declared TypeScript type, Carrick extracts and compares the payload shape.

Framework support

Carrick detects REST frameworks by analyzing imported symbols and call shapes rather than relying strictly on package manifest names. It supports major Node and Deno web frameworks:

  • Express: Comprehensive producer and consumer extraction across Express 4 and Express 5, including path parameters, query parameters, request bodies, and response types.
  • Koa, Fastify, Hapi, and NestJS: Supported with dedicated end-to-end test fixtures validating route extraction and contract matching.
  • Hono: Supported across standard routing patterns.
  • Custom routers: In-house routers following Express-style routing conventions (app.get, router.use, route decorators) are extracted automatically.

Repository requirements

Repositories must meet the following criteria to scan cleanly:

TypeScript source

Carrick relies on TypeScript compiler APIs to resolve request, response, and payload types. While JavaScript repositories can produce endpoint route maps, their parameter and payload types resolve to unknown.

Project manifest

Node projects must define a package.json. Deno projects must define a deno.json or deno.jsonc and require Deno 2.9.4 or newer on PATH, which the GitHub Action configures automatically.

During scans, Carrick prepares dependencies using the project’s lockfile (npm, pnpm, Yarn, Bun, or deno install --frozen --node-modules-dir=none) with lifecycle scripts disabled. You can disable this step by setting install-dependencies: false in the scan configuration.

Statically discoverable routes

Routes must be defined as string literals or resolvable expressions in source code. Routes constructed dynamically at runtime from databases, external configuration files, or arbitrary runtime loops cannot be discovered statically.

Configuration and initial scan

Each repository requires a carrick.json at its root defining service boundaries and classifying environment variables. The initial index is compiled by running carrick index locally, after which the Carrick GitHub Action updates the index automatically on default-branch pushes.

Monorepos

Carrick natively supports both single-service repositories and multi-service monorepos:

  • Workspace monorepos: Monorepos managed with npm, pnpm, Yarn, or Deno workspaces are split into distinct services automatically based on workspace package manifests.
  • Single-package monorepos: Repositories containing multiple services under a single root package.json define a services array in carrick.json. Carrick scans, type-checks, and indexes each service independently, evaluating contracts between services within the same repository.

Limitations and unsupported patterns

The following patterns fall outside the scope of static analysis:

Non-TypeScript languages

Carrick does not scan Python, Go, Rust, Java, or Ruby services. In polyglot environments, Carrick indexes the TypeScript services while non-TypeScript services remain unindexed.

Deno runtime scope limits

Carrick resolves modules using Deno’s standard module graph (deno.window and deno.ns scopes). Worker scopes, arbitrary runtime library combinations, and ambient Node types omitted by deno types require explicit declarations.

Binary and RPC protocols

gRPC, tRPC over WebSockets, and custom binary RPC protocols are not indexed.

Advanced broker queue topologies

While topic names in message queues like BullMQ are indexed for pub/sub matching, broker-specific operational semantics (such as consumer groups, delayed job retries, exchange bindings, and dead-letter queues) are not modelled.

Dynamic runtime routing

Routes registered through dynamic runtime execution cannot be indexed:

  • Routes evaluated from remote feature flags or database queries at startup
  • Routes registered in dynamic loops with non-literal string concatenation
  • Plugin architectures that register handlers after application bootstrap

Pre-compiled and generated code

Carrick scans original TypeScript source files. It does not scan .d.ts-only packages without source, pre-compiled bundles, or build output in .gitignore unless generated source files are checked into version control.

  • Introduction outlines Carrick’s three core surfaces and indexing model.
  • carrick.json explains service configuration, monorepos, and environment variable classification.