tsforge.config.json
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.
Fields
Section titled “Fields”| Field | Type | Purpose |
|---|---|---|
profile | string | Rule preset: recommended (default), strict, security, opinionated |
stack | string | Force-enable a stack and its packs |
packs.include | string[] | Add packs after detection |
packs.exclude | string[] | Remove packs after detection |
rules | object | Per-rule severity: "error", "warn", or "off" (overrides profile defaults) |
conventions | object | Project taste tsforge adapts to: interfaces, enums, tests, componentFolders (written by tsforge setup) |
plugins | object[] | External modules providing extra rule packs (see below) |
mcpServers | object | External MCP servers whose tools the agent can call |
providers.memory | object | Optional decision memory backend (kind: "http" | "mcp") for product/architecture choices across sessions |
policy | object | Permission mode + deny/allow/ask rules for tool actions. See Permissions & policy |
agents.concurrency | number | Multiagent 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
Section titled “Profiles”Profiles control which extra packs load and which default severities apply. They do not replace stack detection; they layer on top.
| Profile | What it adds |
|---|---|
recommended | Safety + always-on packs + stack-detected framework packs. Architecture opinions off. |
strict | recommended + typescript-core pack, CI/supply-chain meta-rules at error, optional type-aware async ESLint when tsconfig.json exists |
security | recommended + experimental authorization heuristics (mutating routes/actions without authz calls) |
opinionated | Full 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"}Rule names
Section titled “Rule names”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".
Example
Section titled “Example”{ "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.
TUI keybindings
Section titled “TUI keybindings”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 id | Default | Purpose |
|---|---|---|
pane.toggle | ctrl+g | show/hide the right rail |
pane.cycleSurface | f6, ctrl+shift+g | Tasks ↔ Gate |
pane.focus | tab | focus rail when visible |
pane.unfocus | escape | return to prompt |
pane.moveUp / pane.moveDown | up/k, down/j | selection 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.
External plugins
Section titled “External plugins”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