> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coderabbit.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration via TypeScript file

> Author CodeRabbit configuration as TypeScript code with type checking, shared fragments, pull request context, and CLI-aware settings.

A `.coderabbit.config.ts` file lets you author your CodeRabbit configuration as TypeScript code instead of static YAML. You get editor autocomplete and author-time type checking, you can build configuration with ordinary JavaScript (loops, conditionals, functions), you can share fragments across repositories, and you can adapt settings to the pull request and invocation that triggered the review.

The `@coderabbitai/config` SDK used in the examples below is **optional**. CodeRabbit evaluates your configuration file server-side either way; installing the package only adds types and autocomplete while you write it. See [Install the SDK](#install-the-sdk-optional).

<Warning>
  A committed `.coderabbit.yaml` (or `.coderabbit.yml`) always takes precedence over `.coderabbit.config.ts`. If both files exist in a repository, the YAML file is used and the TypeScript file is ignored entirely. Delete the YAML file to activate your TypeScript configuration.
</Warning>

## When to use TypeScript configuration

TypeScript configuration adds capabilities a static YAML file does not have:

<CardGroup cols={2}>
  <Card title="Catch mistakes before review" icon="spell-check">
    With the optional SDK, misspelled keys and invalid enum values are flagged in your editor and in CI, not silently at review time
  </Card>

  <Card title="Adapt to the review context" icon="git-pull-request">
    Change the review profile based on labels, target branch, author association, or whether the review runs in the CLI
  </Card>

  <Card title="Generate repetitive settings" icon="repeat">
    Build `path_instructions` for a dozen packages from an array instead of hand-writing each entry
  </Card>

  <Card title="Share configuration fragments" icon="share-2">
    Compose organization-wide defaults with repository-specific overrides
  </Card>
</CardGroup>

## Install the SDK (optional)

The `@coderabbitai/config` package is **entirely optional**. CodeRabbit evaluates your configuration server-side with its own implementation of `defineConfig`, `mergeConfig`, and `includeRemote`, so a `.coderabbit.config.ts` works exactly the same whether or not the package is installed. Nothing in this guide requires it.

What the package adds is **author-time tooling**: types, editor autocomplete, and the ability to type-check your configuration in CI. If you would rather not add a dependency, write the same file without it and CodeRabbit will still evaluate it — you just lose autocomplete and local type errors.

The SDK is currently published under the `next` tag. To install it as a development dependency:

<CodeGroup>
  ```bash npm theme={null}
  npm install --save-dev @coderabbitai/config@next
  ```

  ```bash pnpm theme={null}
  pnpm add --save-dev @coderabbitai/config@next
  ```

  ```bash yarn theme={null}
  yarn add --dev @coderabbitai/config@next
  ```

  ```bash bun theme={null}
  bun add --dev @coderabbitai/config@next
  ```
</CodeGroup>

## Your first configuration

Create a `.coderabbit.config.ts` file in the root of your repository, with a `defineConfig` call as its default export:

```ts .coderabbit.config.ts theme={null}
import { defineConfig } from "@coderabbitai/config"

export default defineConfig({
  language: "en-US",
  reviews: {
    profile: "chill",
    poem: false,
  },
})
```

This example expresses the same settings as the YAML below. See the [configuration reference](/reference/configuration#reference) for available settings and [Constraints and limits](#constraints-and-limits) for TypeScript-specific restrictions.

```yaml .coderabbit.yaml theme={null}
language: "en-US"
reviews:
  profile: "chill"
  poem: false
```

## Adapt configuration to the review context

`defineConfig` also accepts a factory function that receives a context object describing the platform, repository, organization, and pull request. This is the capability a static YAML file cannot provide.

### Pull request context

Review outside contributions more strictly than internal ones:

```ts .coderabbit.config.ts theme={null}
import { defineConfig } from "@coderabbitai/config"

export default defineConfig((ctx) => ({
  reviews: {
    profile:
      ctx.pr?.authorAssociation === "FIRST_TIME_CONTRIBUTOR"
        ? "assertive"
        : "chill",
  },
}))
```

Treat hotfixes differently from ordinary changes:

```ts .coderabbit.config.ts theme={null}
import { defineConfig, type CodeRabbitContext } from "@coderabbitai/config"

function isHotfix(ctx: CodeRabbitContext): boolean {
  const pr = ctx.pr
  if (!pr) return false
  return (
    /hotfix/i.test(pr.title) ||
    pr.headBranch.startsWith("hotfix/") ||
    pr.labels.some((label) => label.toLowerCase() === "hotfix")
  )
}

export default defineConfig((ctx) => ({
  reviews: {
    profile: isHotfix(ctx) ? "assertive" : "chill",
    poem: !isHotfix(ctx),
  },
}))
```

The factory may also be `async` and return a promise.

### Invocation context for CLI reviews

The invocation context distinguishes local [CodeRabbit CLI](/cli/index) reviews from reviews started through a source control provider. For example, use the `chill` profile when running `coderabbit review` locally and the `assertive` profile for hosted pull request reviews:

```ts .coderabbit.config.ts theme={null}
import { defineConfig } from "@coderabbitai/config"

export default defineConfig((ctx) => ({
  reviews: {
    profile: ctx.invocation.source === "cli" ? "chill" : "assertive",
    poem: ctx.invocation.source === "cli",
  },
}))
```

`ctx.invocation.source` is `"cli"` for a local `coderabbit review` invocation and `"review"` for reviews initiated through a source control provider or another review client. Use this field instead of `ctx.platform` when configuration depends on whether the CLI started the review.

The CLI automatically discovers configuration in the repository root. It checks `.coderabbit.yaml`, `.coderabbit.yml`, `coderabbit.yaml`, and `coderabbit.yml` before `.coderabbit.config.ts`; the first YAML file found takes precedence.

### Context reference

CodeRabbit computes the context and injects it at evaluation time. It contains only non-sensitive metadata — there are no tokens or secrets in it.

| Field                      | Type                       | Description                                                                                                                                                                                                                                                                   |
| -------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ctx.invocation.source`    | `"cli" \| "review"`        | `"cli"` for local `coderabbit review` runs; `"review"` for source control provider and other review-client runs                                                                                                                                                               |
| `ctx.platform`             | `string`                   | Provider or product surface reported by the current client, for example `"GitHub"`, `"GitLab"`, `"Azure DevOps"`, `"Bitbucket Cloud"`, `"cli"`, or `"vscode"`                                                                                                                 |
| `ctx.repo.owner`           | `string`                   | Repository owner or namespace                                                                                                                                                                                                                                                 |
| `ctx.repo.name`            | `string`                   | Repository name                                                                                                                                                                                                                                                               |
| `ctx.repo.fullName`        | `string`                   | Fully qualified name, for example `"acme/api"` (on GitLab, the path with namespace)                                                                                                                                                                                           |
| `ctx.repo.language`        | `string \| null`           | Primary **programming** language of the repository as reported by the provider, for example `"TypeScript"`. Not the same as the top-level `language` configuration option, which sets the natural language reviews are written in. `null` if the provider does not report one |
| `ctx.repo.isPrivate`       | `boolean`                  | `true` for a private repository                                                                                                                                                                                                                                               |
| `ctx.repo.isSelfHosted`    | `boolean`                  | `true` on a customer-hosted instance such as GitHub Enterprise Server, self-hosted GitLab, or Bitbucket Data Center                                                                                                                                                           |
| `ctx.repo.defaultBranch`   | `string`                   | Default branch name. Empty string if it could not be resolved — check for empty rather than assuming it is set                                                                                                                                                                |
| `ctx.org`                  | `{ name: string } \| null` | Owning organization, or `null` when the provider has no organization concept or none was resolved                                                                                                                                                                             |
| `ctx.pr`                   | `object \| null`           | Pull or merge request being reviewed. `null` only when there genuinely is no pull request (for example, a pure issue event) or it could not be resolved                                                                                                                       |
| `ctx.pr.number`            | `number`                   | Pull request number                                                                                                                                                                                                                                                           |
| `ctx.pr.title`             | `string`                   | Pull request title                                                                                                                                                                                                                                                            |
| `ctx.pr.baseBranch`        | `string`                   | Branch the pull request merges **into**                                                                                                                                                                                                                                       |
| `ctx.pr.headBranch`        | `string`                   | Branch the pull request is **from**                                                                                                                                                                                                                                           |
| `ctx.pr.author`            | `string`                   | Author's username or handle                                                                                                                                                                                                                                                   |
| `ctx.pr.authorAssociation` | `string \| null`           | On GitHub: `OWNER`, `MEMBER`, `COLLABORATOR`, `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE`. `null` when the provider does not report it                                                                                                                                 |
| `ctx.pr.labels`            | `readonly string[]`        | Label names on the pull request                                                                                                                                                                                                                                               |
| `ctx.pr.isDraft`           | `boolean`                  | `true` for a draft pull request                                                                                                                                                                                                                                               |

<Info>
  `ctx.pr` is resolved for every event that triggers a review, not only the pull request webhook — comment commands such as `@coderabbitai review`, label events, and manual re-reviews included. Still guard with `ctx.pr?.` because it is `null` for events with no pull request. Any field that cannot be resolved degrades gracefully instead of failing configuration resolution.
</Info>

The context inferred for a `defineConfig` factory has a required `invocation` field. The exported `CodeRabbitContext` type keeps `invocation` optional for compatibility with code written before invocation context was added. Use `ResolvedCodeRabbitContext` when explicitly annotating a helper that requires `ctx.invocation`.

## Compose configuration with `mergeConfig`

`mergeConfig` deep-merges configuration fragments left to right, so you can layer overrides onto a base:

```ts .coderabbit.config.ts theme={null}
import {
  defineConfig,
  mergeConfig,
  type CodeRabbitConfig,
  type CodeRabbitContext,
} from "@coderabbitai/config"

const base = {
  reviews: {
    profile: "chill",
    tools: { gitleaks: { enabled: true } },
  },
} satisfies CodeRabbitConfig

const targetsRelease = (ctx: CodeRabbitContext) =>
  /^(main|release\/.*)$/.test(ctx.pr?.baseBranch ?? "")

export default defineConfig((ctx) =>
  mergeConfig(
    base,
    targetsRelease(ctx)
      ? {
          reviews: {
            profile: "assertive",
            request_changes_workflow: true,
            assess_linked_issues: true,
          },
        }
      : {},
  ),
)
```

### Merge rules

| Type             | Behavior                                                                                                                                              |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Objects**      | Merged recursively. Setting one nested key does not wipe its siblings — adding `reviews.tools.osv_scanner` keeps an existing `reviews.tools.gitleaks` |
| **Arrays**       | **Concatenated.** List fields such as `path_instructions` and `labeling_instructions` accumulate rather than replacing each other                     |
| **Scalars**      | The later fragment wins                                                                                                                               |
| **Omitted keys** | Never clobber an existing value, so an empty object contributes nothing and `condition ? fragment : {}` is safe                                       |

<Warning>
  Arrays concatenate in `mergeConfig`, which is **different** from how arrays behave in [configuration inheritance](/configuration/configuration-inheritance) and [global overrides](/guides/configuration-overview#global-overrides), where entries are merged by a stable key such as `path`. Two `path_instructions` entries for the same glob will both appear in the result of a `mergeConfig` call.
</Warning>

## Generate configuration programmatically

Because the file is code, repetitive configuration can be derived instead of hand-written:

```ts .coderabbit.config.ts theme={null}
import { defineConfig } from "@coderabbitai/config"

const teams = ["api", "web", "worker"]

export default defineConfig({
  reviews: {
    path_instructions: teams.map((team) => ({
      path: `packages/${team}/**`,
      instructions: `Follow the ${team} team's conventions.`,
    })),
  },
})
```

## Share configuration across files and repositories

### Local includes

Split a large configuration into multiple files in the same repository and pull them in with ordinary relative imports:

```ts .coderabbit.config.ts theme={null}
import { defineConfig, mergeConfig } from "@coderabbitai/config"
import security from "./coderabbit/security"
import pathRules from "./coderabbit/path-rules.yaml"

export default defineConfig(mergeConfig(security, pathRules, {
  reviews: { profile: "chill" },
}))
```

Local includes resolve against the importing file's path, in the repository and at the commit being reviewed. A few details:

* **YAML files can be imported.** A `.yaml` or `.yml` import becomes a module whose default export is the parsed object, so existing YAML fragments can be reused as-is.
* **Extensionless imports work.** CodeRabbit tries `.ts`, `.mts`, `.cts`, `.js`, `.mjs`, `.cjs`, `.yaml`, and `.yml`, then the same extensions under `<path>/index`, matching how your editor resolves the import.
* **Imports cannot escape the repository root.** A relative path that resolves outside the repository tree is rejected rather than silently clamped.

### Remote includes from your `coderabbit` repository

Use `includeRemote` to pull a shared fragment from your organization's central `coderabbit` repository — the same repository used for [central configuration](/configuration/central-configuration):

```ts .coderabbit.config.ts theme={null}
import { defineConfig, mergeConfig, includeRemote } from "@coderabbitai/config"

const base = includeRemote({ path: "base.ts" })
const security = includeRemote({ path: "security.ts" })
const hotfix = includeRemote({ path: "hotfix.ts" })

export default defineConfig((ctx) =>
  mergeConfig(
    base,
    security,
    { reviews: { poem: false } },
    ctx.pr?.labels.includes("hotfix") ? hotfix : {},
  ),
)
```

Pin a specific version with the optional `ref`, which accepts a branch, tag, or commit SHA:

```ts theme={null}
const base = includeRemote({ path: "base.ts", ref: "v2" })
```

Omit `ref` to track the `coderabbit` repository's default branch, so central edits propagate to every repository automatically.

<Warning>
  `includeRemote` is a **build-time directive**, not a runtime function. Its argument must be an inline object literal with string literal values. Computed arguments fail at bundle time with a clear error:

  ```ts theme={null}
  const wrong = includeRemote({ path: isHotfix ? "hotfix.ts" : "base.ts" })
  ```

  Calls can appear inside expressions, including conditionals, as long as each call uses an inline object literal with a string-literal `path` and optional string-literal `ref`:

  ```ts .coderabbit.config.ts theme={null}
  import { defineConfig, includeRemote } from "@coderabbitai/config"

  export default defineConfig((ctx) =>
    ctx.pr?.labels.includes("hotfix")
      ? includeRemote({ path: "hotfix.ts" })
      : includeRemote({ path: "base.ts" }),
  )
  ```

  Every `includeRemote` call is resolved during bundling, so both files are fetched even though the condition selects only one result at evaluation time. Defining the fragments at the top level, as in the larger example above, is also supported. Keep the number of remote includes reasonable, and use `mergeConfig` when you want the selected fragment layered onto shared defaults rather than replacing them.
</Warning>

<Info>
  The source repository is not configurable. Shared files are always read from `{owner}/coderabbit`, and passing a `repo` key is rejected. This keeps a configuration from reading arbitrary repositories in your organization: remote includes can only reach the one repository that is already the organization-wide configuration location. Files are fetched with CodeRabbit's existing read access, so the `coderabbit` repository can be private.
</Info>

## How evaluation works

Understanding the pipeline explains most of the constraints below:

<Steps>
  <Step title="Discovery">
    CodeRabbit looks for configuration files in the repository under review. `.coderabbit.config.ts` is checked last, so any YAML configuration wins.
  </Step>

  <Step title="Bundling">
    Your entry file, every file it includes (local and remote), and an implementation of `@coderabbitai/config` are bundled server-side into a single self-contained program. All file fetching happens here, outside the sandbox. Includes are modeled as imports, so recursion, deduplication, and cycles are handled by the module graph.
  </Step>

  <Step title="Sandboxed evaluation">
    The bundle runs in an isolated sandbox with **all outbound networking denied**, an empty environment, no secrets, and a hard timeout. Configuration evaluation legitimately needs none of those, so they are removed rather than restricted.
  </Step>

  <Step title="Validation">
    The resulting object is validated against the same schema a `.coderabbit.yaml` uses, and then flows through the same pipeline — including [configuration inheritance](/configuration/configuration-inheritance), UI settings priority, and [global overrides](/guides/configuration-overview#global-overrides).
  </Step>
</Steps>

Because validation and merging are shared with the YAML path, a TypeScript configuration occupies the same layer in the [configuration priority order](/guides/configuration-overview#understanding-configuration-priority) as a repository YAML file, and a `.coderabbit.config.ts` in your central `coderabbit` repository works as a central configuration too.

### Constraints and limits

| Constraint              | Value                                                                                                                                                                                             |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Allowed imports         | `@coderabbitai/config`, relative includes (`./`, `../`), and remote includes via `includeRemote`. Any other bare import (including npm packages and Node.js built-ins) is rejected at bundle time |
| Network access          | Denied. Your configuration cannot make requests                                                                                                                                                   |
| Secrets and environment | None injected. The environment is empty                                                                                                                                                           |
| Evaluation timeout      | 10 seconds                                                                                                                                                                                        |
| Include fetch budget    | 100 file fetch attempts per configuration                                                                                                                                                         |
| Total source size       | 2 MB across the entry file and all includes                                                                                                                                                       |
| Output size             | 5 MB                                                                                                                                                                                              |
| `remote_config`         | Not supported. Use local imports or `includeRemote` instead                                                                                                                                       |

<Info>
  The `remote_config` YAML redirect described in [shared configuration](/getting-started/yaml-configuration#shared-configuration) applies to YAML files only. In a TypeScript configuration, use relative imports and `includeRemote` for the same purpose.
</Info>

## Verify the resolved configuration

Run `@coderabbitai configuration` on any pull request to see the fully resolved configuration as YAML, annotated with the source that supplied each value. For TypeScript configurations, the annotations identify the specific file each value came from, so you can tell an organization default apart from a repository override in a composed configuration.

## Type-check your configuration in CI

With the SDK installed and `.coderabbit.config.ts` included in your TypeScript project, your project's TypeScript compiler validates the configuration file like any other TypeScript source. For example:

```bash theme={null}
tsc --noEmit
```

Unknown top-level keys, misspelled option names, and invalid enum values (for example `profile: "aggressive"`) are reported as type errors. Adding this to CI catches configuration mistakes before they reach a review.

## Troubleshooting

<AccordionGroup>
  <Accordion title="My TypeScript configuration is being ignored">
    A committed `.coderabbit.yaml` or `.coderabbit.yml` takes precedence over `.coderabbit.config.ts`. Delete the YAML file. Confirm with `@coderabbitai configuration` on a pull request, which reports the source of every resolved value.
  </Accordion>

  <Accordion title="Unsupported import">
    Only `@coderabbitai/config`, relative includes, and `includeRemote` are permitted. Configuration files cannot import npm packages or Node.js built-ins — the bundle has no access to your `node_modules`. Move any logic that requires a dependency out of your configuration.
  </Accordion>

  <Accordion title="includeRemote(...) requires an inline object literal">
    `includeRemote` is resolved before your configuration runs, so its argument cannot be computed. Conditionals can select between separate `includeRemote` calls with literal arguments, including inside `mergeConfig`. Each `includeRemote` argument must remain a literal `{ path: "..." }` object with an optional literal `ref`.
  </Accordion>

  <Accordion title="Cannot resolve include">
    The file does not exist at that path, or CodeRabbit cannot read it. Check the path, the `ref` if you pinned one, and — for remote includes — that the file is in the `coderabbit` repository under the same owner and that CodeRabbit has access to that repository.
  </Accordion>

  <Accordion title="Evaluation timed out">
    Configuration evaluation is capped at 10 seconds. Configuration files are meant to compute a configuration object, not to do heavy work. Remove long loops and expensive computation.
  </Accordion>

  <Accordion title="Configuration file must resolve to an object">
    The default export must resolve to a configuration object, or be a factory that returns one. `defineConfig` is recommended for type checking but is not required at evaluation time. Make sure the configuration is the **default** export.
  </Accordion>
</AccordionGroup>

## API reference

| Export                          | Description                                                                                                                        |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `defineConfig(config)`          | Typed identity function for your configuration. Accepts a configuration object, or a `(ctx) => config` factory that may be `async` |
| `mergeConfig(...fragments)`     | Deep-merges fragments left to right. Objects merge, arrays concatenate, later scalars win                                          |
| `includeRemote({ path, ref? })` | Build-time directive that includes a shared file from your organization's `coderabbit` repository                                  |
| `CodeRabbitConfig`              | Type of the configuration object — the `.coderabbit.yaml` surface expressed in TypeScript, with every key optional                 |
| `CodeRabbitContext`             | Backward-compatible context type. Its `invocation` field is optional                                                               |
| `ResolvedCodeRabbitContext`     | Context type passed to an inferred configuration factory. Its `invocation` field is required                                       |
| `CodeRabbitInvocationContext`   | Type containing the review invocation source                                                                                       |
| `CodeRabbitInvocationSource`    | Union of the supported invocation sources: `"cli" \| "review"`                                                                     |
| `RemoteInclude`                 | Type of the `includeRemote` argument                                                                                               |

## What's next

<CardGroup cols={1}>
  <Card title="Configuration reference" icon="book" href="/reference/configuration" horizontal>
    Every available option, with defaults and descriptions
  </Card>

  <Card title="Central configuration" icon="layers" href="/configuration/central-configuration" horizontal>
    Set up the `coderabbit` repository that `includeRemote` reads from
  </Card>

  <Card title="Configuration priority" icon="list-ordered" href="/guides/configuration-overview#understanding-configuration-priority" horizontal>
    How CodeRabbit resolves conflicting configuration sources
  </Card>
</CardGroup>
