@coderabbitai/config
Typed, programmatic authoring for CodeRabbit
configuration — write your .coderabbit.config.ts in TypeScript instead of
.coderabbit.yaml, with editor autocomplete and author-time type-checking.
A committed .coderabbit.yaml always takes precedence over
.coderabbit.config.ts.
Install
npm install --save-dev @coderabbitai/config
Usage
Create a .coderabbit.config.ts at the root of your repository:
import { defineConfig } from "@coderabbitai/config"
export default defineConfig({
language: "en-US",
reviews: { profile: "chill" },
})
defineConfig also accepts a factory that receives repository / organization /
pull-request and invocation context, so your config can adapt to where, what,
and how it runs — something a static YAML file cannot do:
import { defineConfig } from "@coderabbitai/config"
export default defineConfig(ctx => ({
reviews: {
// Keep local CLI reviews focused; use normal policy in the repository.
profile: ctx.invocation.source === "cli" ? "chill" : "assertive",
},
}))
ctx.invocation.source is "cli" for a local coderabbit review and
"review" for reviews initiated through an SCM provider or another review
client.
For pull requests and merge requests, ctx.pr.authorGroups exposes the
author's provider groups without putting provider-specific objects in your
config:
import { defineConfig } from "@coderabbitai/config"
export default defineConfig(ctx => {
const groups =
ctx.pr?.authorGroups.status === "resolved" ? ctx.pr.authorGroups.groups : []
const isUsaPlatform = groups.some(
group => group.fullPath === "acme/platform-usa",
)
return {
language: isUsaPlatform ? "en-US" : "ko-KR",
}
})
Each group has a provider-stable id, a short slug, and a provider-qualified
fullPath. status is:
"resolved": the provider returned the complete visible membership list;groupsmay be empty."unavailable": permissions, timeout, provider failure, or a safety bound prevented a complete lookup.groupsis empty and must not be treated as proof that the author belongs to no groups."unsupported": the current provider or invocation has no author-group resolver. Local CLI reviews currently use this status."stale": reserved for a future cached membership result.
GitHub and GitHub Enterprise resolve organization teams. GitLab.com and self-managed GitLab resolve direct group memberships visible to CodeRabbit; GitLab's membership API does not include inherited or shared group membership.
Repository topics and GitHub custom properties are available under ctx.repo:
import { defineConfig } from "@coderabbitai/config"
export default defineConfig(ctx => {
const topics =
ctx.repo.topics.status === "resolved" ? ctx.repo.topics.names : []
const properties =
ctx.repo.customProperties.status === "resolved"
? ctx.repo.customProperties.values
: {}
const isCriticalService =
topics.includes("critical") && properties.repo_type === "service"
return {
reviews: {
profile: isCriticalService ? "assertive" : "chill",
},
}
})
topics.names is a sorted list. customProperties.values is keyed by the
property name; each value is a string, a string array, or null. Both objects
use the same resolved, unavailable, unsupported, and reserved stale
statuses as author groups. A resolved collection may be empty. An unavailable
collection is unknown and must not be treated as authoritatively empty.
GitHub supplies topics and custom properties. Other providers and local CLI
reviews currently report unsupported; GitHub failures and unsupported GitHub
Enterprise versions report unavailable. These lookups use the installation's
existing metadata read permission and run only when a TypeScript config is
evaluated.
ctx.pr.changedFiles exposes the complete set of repository-relative paths in
the pull request or merge request diff. This makes it possible to select review
policy based on the areas a change touches:
import { defineConfig } from "@coderabbitai/config"
export default defineConfig(ctx => {
const paths =
ctx.pr?.changedFiles.status === "resolved" ? ctx.pr.changedFiles.paths : []
const touchesInfrastructure = paths.some(
path => path.startsWith("terraform/") || path.endsWith(".tf"),
)
return {
reviews: {
profile: touchesInfrastructure ? "assertive" : "chill",
},
}
})
The status is "resolved" only when CodeRabbit has the complete path list.
Provider errors, timeouts, revision changes, or safety limits produce
"unavailable" with an empty list; platforms without a complete inventory
produce "unsupported". Never interpret either status as proof that no files
changed. Renames include both the previous and current path so policies can
detect files moving into or out of a protected area.
Composing configs
mergeConfig deep-merges fragments (objects merge, arrays concatenate, later
scalars win), and includeRemote pulls a shared fragment from your
organization's coderabbit repository by default:
import { defineConfig, mergeConfig, includeRemote } from "@coderabbitai/config"
const orgBase = includeRemote({ path: "base.ts" })
const platformBase = includeRemote({
repo: "acme/platform-config",
path: "reviews/base.ts",
ref: "v1",
})
export default defineConfig(
mergeConfig(orgBase, platformBase, { reviews: { profile: "assertive" } }),
)
How it works
Your config is evaluated by CodeRabbit in an isolated, network-free sandbox and
validated against the same schema a .coderabbit.yaml uses. This package is
author-time only — it gives you types and autocomplete; the actual
evaluation happens server-side, so your config works whether or not the package
is installed. Installing it just makes your editor and CI aware of the config
shape.
API
defineConfig(config | (ctx) => config)— typed identity for your config.mergeConfig(...fragments)— deep-merge fragments (arrays concatenate).includeRemote({ repo?, path, ref? })— include a shared file.repouses the provider-native repository format and defaults to your org'scoderabbitrepository.- Types:
CodeRabbitConfig,CodeRabbitContext,CodeRabbitAuthorGroup,CodeRabbitAuthorGroupsContext,CodeRabbitAuthorGroupsStatus,CodeRabbitContextResolutionStatus,CodeRabbitChangedFilesContext,CodeRabbitChangedFilesStatus,CodeRabbitRepositoryContext,CodeRabbitRepositoryTopicsContext,CodeRabbitRepositoryCustomPropertiesContext,CodeRabbitRepositoryCustomPropertyValue,CodeRabbitPullRequestContext,CodeRabbitInvocationContext,CodeRabbitInvocationSource,ResolvedCodeRabbitContext,RemoteInclude.
Internal V3 preview
V2 remains the public configuration contract and the CodeRabbitConfig type.
CodeRabbitConfigV3 and the defineConfig / mergeConfig overloads support an
explicit version: 3 for the authenticated internal GitHub Cloud preview only.
Types do not grant runtime access: customer, self-hosted and central V3 entry
configurations remain unsupported. YAML still takes precedence over TypeScript.
import { defineConfig, mergeConfig } from "@coderabbitai/config"
export default defineConfig(ctx =>
mergeConfig(
{ version: 3, reviews: { behavior: { profile: "chill" } } },
{ fun: { in_progress_fortune: ctx.invocation.source === "review" } },
),
)
Start each V3 mergeConfig call with a V3 base, including nested calls:
mergeConfig({ version: 3 }, canonical, legacy). A call with only versionless
fragments retains the V2 contract; an enclosing V3 merge cannot change how an
inner call has already combined its fragments.
For an admitted primary repository, directory documents are loaded from the
same immutable repository revision as .coderabbit.config.ts. Imported fragments
do not create additional directory discovery roots. Use
includeRemote<CodeRabbitConfigV3Fragment>({ path: "base.ts" }) to type a remote
V3 fragment; calls without a type argument retain their V2 return type. The
offline V2 migration CLI
still reads explicit YAML inputs; it does not execute TypeScript factories or
attest their inherited source graph.
Building the SDK
From the repository root, run pnpm build --filter=@coderabbitai/config.
This uses the repository's shared CPU-budget launcher for the scoped build.
The build explicitly uses stable TypeScript 7 through the package-local
typescript-native alias. TypeScript 6 remains installed as typescript for
dts-bundle-generator's JavaScript compiler API; a bare tsc could select that
older compiler instead. Keep the compiler and declaration-generation dependencies
inside this package, not in the root workspace.