Guides

carrick.json

Per-repo config that tells the scanner which services a repo contains and which env vars and domains name internal services versus third-party APIs.

carrick.json defines service boundaries within a repository and classifies outbound network calls that construct target URLs from environment variables or URL prefixes. This configuration enables the scanner to distinguish internal calls to other services in your organisation from external calls to third-party APIs.

carrick.json configures the static analysis scanner, whereas AGENTS.md and CLAUDE.md provide operational rules for AI coding agents.

Single-service configuration

For a repository containing a single service, define the service name and classification lists at the root of carrick.json:

{
  "serviceName": "order-service",
  "internalEnvVars": ["USER_SERVICE_URL", "INVENTORY_API"],
  "externalEnvVars": ["STRIPE_API", "GITHUB_API"],
  "internalDomains": ["https://api.yourcompany.com"],
  "externalDomains": ["https://api.stripe.com", "https://api.github.com"]
}

Field reference

FieldTypeDescription
serviceNamestringIdentifier for this service displayed in MCP responses and the dashboard. Defaults to the repository name if omitted.
internalEnvVarsstring arrayEnvironment variables whose values resolve to internal services in your organisation. Calls constructed using these variables are validated against the index.
externalEnvVarsstring arrayEnvironment variables whose values resolve to third-party APIs. Calls constructed using these variables are ignored during contract verification.
internalDomainsstring arrayURL prefixes for internal services. Outbound calls starting with these prefixes are matched against the index.
externalDomainsstring arrayURL prefixes for external APIs. Outbound calls starting with these prefixes are ignored.

Outbound call classification

When code constructs a request URL dynamically (such as fetch(${process.env.ORDER_SERVICE_URL}/orders)), static analysis cannot automatically determine whether the destination is an internal service or an external vendor.

Classifying these variables ensures accurate contract validation:

  • Environment variables: Match dynamic URL patterns constructed with template literals or string concatenation.
  • Domains: Match explicit URL literals and prefixes.

Calls constructed from unclassified environment variables generate configuration suggestions in pull request comments until they are added to internalEnvVars or externalEnvVars.

Monorepo service configuration

When a repository contains multiple services, declare them using the services array at the top level of carrick.json. Carrick scans, type-checks, and indexes each entry as an independent service, evaluating contracts between services within the monorepo:

{
  "services": [
    {
      "serviceName": "api",
      "directory": "services/api",
      "include": ["packages/shared"],
      "tsconfig": "tsconfig.json",
      "internalEnvVars": ["WORKER_URL"]
    },
    {
      "serviceName": "worker",
      "directory": "services/worker",
      "include": ["packages/shared"]
    },
    {
      "serviceName": "web",
      "directory": "apps/web",
      "tsconfig": "tsconfig.json",
      "externalDomains": ["https://api.stripe.com"]
    }
  ]
}

Service entry fields

FieldTypeDescription
serviceNamestringUnique service identifier. Always provide an explicit name for each service in a monorepo to avoid index collisions.
directorystringPath to the service root directory, relative to carrick.json.
includestring arrayAdditional directories containing shared source code or libraries to include during type resolution.
tsconfigstringPath to the service’s tsconfig.json, relative to directory. For Deno services, omit this to use the nearest deno.json or deno.jsonc.

Each entry in the services array also supports the classification fields (internalEnvVars, externalEnvVars, internalDomains, externalDomains). Files outside declared service directories, node_modules, build output directories, and test files are excluded from indexing.

Declared and routeless operations

Serverless functions (such as AWS Lambdas or Cloudflare Workers) often route requests based on an event payload field or HTTP header rather than an infrastructure path. To index these routeless or dispatching handlers as concrete operations, declare an operations block:

{
  "operations": [
    {
      "service": "orders",
      "route": "POST /v1/orders",
      "dispatch": { "location": "body", "field": "action" },
      "operations": [
        { "value": "create", "handler": "src/create.ts:handleCreate" },
        { "value": "refund" }
      ]
    }
  ],
  "services": [
    { "serviceName": "orders", "directory": "functions/orders" }
  ]
}

Operations block fields

FieldTypeDescription
servicestringTarget service matching a declared serviceName.
routestringThe route served by the handler ("POST /path").
dispatch.locationstringDispatch field source: "body" or "header".
dispatch.fieldstringThe property or header name that determines dispatch.
operations[].valuestringAn accepted dispatch value representing a distinct operation.
operations[].handlerstringOptional "file:symbol" mapping to navigate directly to the specific handler function.

Mixed dependency example

The following configuration demonstrates a service that interacts with internal microservices, an external payment gateway configured via environment variables, and third-party webhooks:

{
  "serviceName": "checkout",
  "internalEnvVars": [
    "ORDER_SERVICE_URL",
    "INVENTORY_SERVICE_URL",
    "USER_SERVICE_URL"
  ],
  "externalEnvVars": [
    "STRIPE_API_BASE"
  ],
  "externalDomains": [
    "https://api.sendgrid.com",
    "https://hooks.slack.com"
  ]
}
  • Quickstart walks through generating configuration files during onboarding.
  • PR comments describes automated feedback on unclassified environment variables.
  • What Carrick covers details framework extraction and routing support.