Skip to content
ƒtsforgev0.52.0
19

tsforge.config.json

5 min read

You do not need this file to use tsforge. Stack detection works from package.json alone, and the default recommended profile keeps safety rules on while turning off noisy architecture opinions.

Add tsforge.config.json at your repo root when you want to override what tsforge detected: pick a stricter profile, force an Elysia stack, disable a pack you do not use, or downgrade a noisy rule to a warning.

FieldTypePurpose
profilestringRule preset: recommended (default), strict, security, opinionated
stackstringForce-enable a stack and its packs
packs.includestring[]Add packs after detection
packs.excludestring[]Remove packs after detection
rulesobjectPer-rule severity: "error", "warn", or "off" (overrides profile defaults)
conventionsobjectProject taste tsforge adapts to: interfaces, enums, tests, componentFolders (written by tsforge setup)
pluginsobject[]External modules providing extra rule packs (see below)
mcpServersobjectExternal MCP servers whose tools the agent can call
providers.memoryobjectOptional decision memory backend (kind: "http" | "mcp") for product/architecture choices across sessions
policyobjectPermission mode + deny/allow/ask rules for tool actions. See Permissions & policy
agents.concurrencynumberMultiagent cap, integer 1–16 (default 1 = sequential). Bounds how many subagents run at once: both delegated spawn_agent calls and tsforge review’s parallel find/verify passes (fresh provider per unit, live agents: progress). Leave at 1 for a local endpoint that serializes requests anyway

Resolution order: detect from the repo → apply profile (packs + default severities) → apply stack → apply include → apply exclude → add external plugin packs → dedupe → merge rules overrides (user wins).

If the file is missing, tsforge uses detection with the recommended profile. If JSON is invalid, tsforge warns on stderr and continues with an empty config.

Profiles control which extra packs load and which default severities apply. They do not replace stack detection; they layer on top.

ProfileWhat it adds
recommendedSafety + always-on packs + stack-detected framework packs. Architecture opinions off.
strictrecommended + typescript-core pack, CI/supply-chain meta-rules at error, optional type-aware async ESLint when tsconfig.json exists
securityrecommended + experimental authorization heuristics (mutating routes/actions without authz calls)
opinionatedFull house-style architecture rules (component folder structure, hooks layout, early returns at error)

Every rule in the Rule catalog is tagged by tier (safety, framework, architecture, experimental). Profiles are the ergonomic switch. You rarely need to tune individual rules.

{
"profile": "strict"
}

Bare names and tsforge/-prefixed names both work:

{
"no-direct-process-env": "error",
"tsforge/prefer-early-return": "warn",
"no-historical-comments": "off"
}

Meta-rules use the same rules map. Example: "workflow-permissions-explicit": "off".

{
"profile": "strict",
"stack": "elysia",
"packs": {
"include": ["structured-logging"],
"exclude": ["bullmq"]
},
"rules": {
"no-direct-process-env": "error",
"tsforge/prefer-early-return": "warn",
"no-historical-comments": "off"
}
}

This project uses the strict profile, is treated as Elysia, keeps structured-logging rules, skips BullMQ rules, and softens one comment rule.

Optional pane-console shortcuts under tui.keybindings in tsforge.config.json. Values are OS-agnostic logical chords (ctrl+g, ctrl+shift+g, f6, ?, …) — tsforge normalizes Kitty CSI-u, xterm modifyOtherKeys, and legacy ctrl bytes at runtime.

User-global overrides live in ~/.tsforge/config.json (same schema) and win over project entries for the same action.

Action idDefaultPurpose
pane.togglectrl+gshow/hide the right rail
pane.cycleSurfacef6, ctrl+shift+gTasks ↔ Gate
pane.focustabfocus rail when visible
pane.unfocusescapereturn to prompt
pane.moveUp / pane.moveDownup/k, down/jselection when rail focused
keymap.show?idle keymap overlay

Invalid chords warn on stderr and are dropped. Editor keys (Shift+Enter, @ picker, / palette) stay fixed in this release.

Ship your own rule packs without recompiling tsforge. Each plugins entry names a module (or a path relative to the repo root) and, optionally, which exported packs to use; omit packs to load every exported pack. An export must be a valid rule pack (id, description, rules, rulesConfig) or it is skipped with a warning. A pack id can never shadow a built-in, and a rule name that collides with a built-in fails the build.

{
"plugins": [
{ "path": "@acme/tsforge-pack" },
{ "path": "./tools/house-rules.ts", "packs": ["housePack"] }
]
}

A module that fails to import is reported on stderr and skipped. A broken plugin never blocks a run.

Stack detection · Rule packs · MCP servers · Environment variables