Skip to content

Configuration Reference

This document uses src/config/load-config.ts as canonical source, with supplementary reference from src/shared/types.ts, src/modules/web/providers/*, src/modules/lsp/schemas.ts, and related tests. If README or old docs conflict with this document, the defaults and normalize logic in src/config/load-config.ts take precedence.

Configuration file location

Default configuration file:

text
~/.pi/agent/extensions/devkit-pi/config.json

devkit-pi uses namespace-based configuration and does not support legacy flat configuration fields. When the config file is missing or unreadable, the default config {} merged with DEFAULT_CONFIG is used.

Configuration follows the architecture consistency policy: similar modules use namespace-based config objects, aligned enabled switches, default/normalize behavior, and matching source/test/documentation coverage. Legacy flat fields are not retained when they conflict with this structure.

Complete default configuration example

Source: DEFAULT_CONFIG, DEFAULT_SUBAGENTS_CONFIG, DEFAULT_WEB_CONFIG, DEFAULT_CONVERT_CONTENT_CONFIG in src/config/load-config.ts.

json
{
  "enabled": true,
  "subagents": {
    "enabled": true,
    "maxDepth": 1,
    "timeoutMs": 900000,
    "idleTimeoutMs": 180000,
    "allowWrite": false,
    "allowLspTools": true,
    "allowedLspActions": [
      "definition",
      "references",
      "hover",
      "signature",
      "symbols",
      "diagnostics",
      "workspace-diagnostics",
      "servers"
    ],
    "injectDelegationPolicy": true,
    "retry": {
      "enabled": true,
      "maxAttempts": 2
    }
  },
  "web": {
    "enabled": true,
    "provider": "ddgs",
    "providerPriority": ["tavily", "serper", "brave", "openserp", "searxng", "ddgs"],
    "timeoutMs": 10000,
    "maxResponseBytes": 1048576,
    "maxContentChars": 30000,
    "maxResults": 5,
    "enableJinaFallback": false,
    "jinaTimeoutMs": 8000,
    "maxStoredResults": 100,
    "maxStoredContentChars": 200000,
    "allowPrivateNetwork": false,
    "jinaTriggers": ["short-html", "js-heavy-html"],
    "debug": false,
    "cache": {
      "enabled": false,
      "maxEntries": 50,
      "ttlMs": 300000
    },
    "concurrency": {
      "maxConcurrent": 3,
      "maxQueueSize": 10
    },
    "connectionPool": {
      "maxSockets": 10,
      "maxFreeSockets": 5,
      "timeout": 60000
    },
    "openserp": {
      "enabled": false,
      "baseUrl": "https://api.openserp.com/search",
      "apiKeyEnv": "OPENSERP_API_KEY"
    },
    "searxng": {
      "enabled": false,
      "baseUrl": "",
      "defaultEngine": "google"
    },
    "brave": {
      "enabled": false,
      "baseUrl": "https://api.search.brave.com/res/v1/web/search",
      "apiKeyEnv": "BRAVE_SEARCH_API_KEY"
    },
    "tavily": {
      "enabled": false,
      "baseUrl": "https://api.tavily.com/search",
      "apiKeyEnv": "TAVILY_API_KEY"
    },
    "serper": {
      "enabled": false,
      "baseUrl": "https://google.serper.dev/search",
      "apiKeyEnv": "SERPER_API_KEY"
    }
  },
  "convertContent": {
    "enabled": true,
    "provider": "markitdown",
    "command": "markitdown",
    "timeoutMs": 30000,
    "maxResponseBytes": 10485760,
    "maxContentChars": 50000,
    "allowPrivateNetwork": false
  },
  "lsp": {
    "enabled": true,
    "tool": {
      "enabled": true,
      "allowMutatingActions": false
    },
    "hook": {
      "enabled": true,
      "mode": "agent_end"
    }
  },
  "commands": {
    "enabled": true
  },
  "guards": {
    "enabled": true,
    "gitContextNotice": true,
    "firstWriteReminder": true,
    "verificationReminder": true
  }
}

All fields are optional; unconfigured or type-non-conforming values fall back to defaults per normalize rules.

Normalize rules summary

Source: src/config/load-config.ts.

RuleApplicable fieldsBehavior
booleanValueboolean fieldsOnly boolean takes effect, otherwise uses default
positiveIntegerTimeouts, sizes, counts, queue positive integersMust be > 0 integer, otherwise uses default
nonNegativeIntegersubagents.maxDepthMust be >= 0 integer, otherwise uses default
normalizeProviderweb.providerOnly accepts auto, brave, ddgs, openserp, searxng, tavily, serper
normalizeProviderPriorityweb.providerPriorityFilters invalid providers, deduplicates; empty or invalid array falls back to default
normalizeDebugLevelweb.debugAccepts false, minimal, verbose; true becomes minimal
normalizeJinaTriggersweb.jinaTriggersAccepts non-empty string array and deduplicates; non-array falls back to default; empty array can be retained as empty
normalizeLspReadonlyActionssubagents.allowedLspActionsOnly retains readonly-safe LSP actions and deduplicates
normalizeLspHookModelsp.hook.modeOnly accepts agent_end, edit_write, disabled
nonEmptyStringExternal command / provider URLs / env var namesTrimmed non-empty strings take effect, otherwise uses default

Top-level configuration

Source: DEFAULT_CONFIG, mergeConfig().

KeyTypeDefaultRequiredPurposeRelated source
enabledbooleantrueNoWhether to enable entire devkit-pi extension; when false, main entry returns immediatelysrc/index.ts, src/config/load-config.ts
subagentsobjectSee belowNoSubagent tool, built-in agents, delegation policy, subagent LSP exposuresrc/modules/subagents/*
webobjectSee belowNoweb_search / fetch_content / get_search_contentsrc/modules/web/*
lspobjectSee belowNolsp tool and automatic diagnostics hooksrc/modules/lsp/*
convertContentobjectSee belowNoconvert_content document conversion tool configuration. Local path and remote url conversion use MarkItDown provider after safe source handlingsrc/modules/convert/*
commandsobjectSee belowNoUnified /toolkit developer commandsrc/modules/commands/register.ts
guardsobjectSee belowNoLightweight user-visible session notices; soft reminders only, no hard gatessrc/modules/guards/*

Example: disable entire extension.

json
{
  "enabled": false
}

Subagents configuration

Public overview, tool API, agent definition, and result schema: subagents.md, subagent-tool.md, agent-definition.md, result-schema.md.

Source: DEFAULT_SUBAGENTS_CONFIG, normalizeSubagentsConfig(), src/modules/subagents/register.ts, src/modules/subagents/executor.ts.

KeyTypeDefaultRequiredPurposeRelated source
subagents.enabledbooleantrueNoWhether to register subagent toolsrc/modules/subagents/register.ts
subagents.maxDepthnumber1NoMaximum subagent depth; default prohibits nested subagents. Accepts non-negative integersrc/shared/types.ts, src/modules/subagents/register.ts
subagents.timeoutMsnumber900000NoSingle child execution hard cap in ms; starts when the child process is spawned and does not reset on activitysrc/modules/subagents/executor.ts
subagents.idleTimeoutMsnumber180000NoMaximum idle time in ms since the last valid structured child activity event; plain stdout text does not reset this timersrc/modules/subagents/executor.ts, src/modules/subagents/collect-output.ts
subagents.allowWritebooleanfalseNoExperimental/advanced/unsafe switch. Relaxes non-readonly custom agent tool filtering policy; does not imply complete permission sandbox, audit log, automatic rollback, or stable write-capability contractsrc/config/load-config.ts, src/modules/subagents/*
subagents.allowLspToolsbooleantrueNoWhether to allow subagents to use readonly LSP tool; also constrained by lsp.enabled and lsp.tool.enabledsrc/index.ts, src/modules/subagents/*
subagents.allowedLspActionsstring[]See belowNoSubagent LSP action allowlist; invalid values are discardedsrc/config/load-config.ts
subagents.injectDelegationPolicybooleantrueNoWhether to inject delegation policy and few-shot examples into main agent system promptsrc/shared/delegation-policy.ts, src/modules/subagents/register.ts
subagents.retry.enabledbooleantrueNoWhether to enable subagent retrysrc/config/load-config.ts, src/modules/subagents/executor.ts
subagents.retry.maxAttemptsnumber2NoMaximum attempt count, must be positive integersrc/config/load-config.ts, src/modules/subagents/executor.ts

Default subagents.allowedLspActions:

json
[
  "definition",
  "references",
  "hover",
  "signature",
  "symbols",
  "diagnostics",
  "workspace-diagnostics",
  "servers"
]

Example: disable delegation policy injection and disable subagent LSP.

json
{
  "subagents": {
    "injectDelegationPolicy": false,
    "allowLspTools": false
  }
}

Example: only allow subagents to use LSP symbols and diagnostics.

json
{
  "subagents": {
    "allowedLspActions": ["symbols", "diagnostics", "servers"]
  }
}

subagents.allowWrite boundary

Writable custom subagents are currently an experimental capability. The default and recommended mode is readonly. subagents.allowWrite=true only indicates relaxed delegation policy; it does not imply a complete permission sandbox, audit logging, automatic rollback mechanism, or stable write-capability contract. Use only in trusted repositories, and all changes must be human-reviewed.

Current constraints:

  • Built-in agents continue to be designed as readonly-first.
  • Subagent's actual tool availability depends on child pi runtime, current tool registration, execution environment, and configuration.
  • Subagent processes do not register subagent or /toolkit.
  • LSP privileged actions are always disabled in subagents.
  • Web tools can be used for research and reading information.
  • File writing, command execution, project modification, and other write-like behaviors have no stable automatic rollback guarantee.

To enable writable behavior, use Git workspaces, pre-commit diffs, human review, and test commands as safety nets. If formally supporting writable custom subagents in the future, permission strategy, audit logging, rollback recommendations, and test coverage should be supplemented first.

LSP configuration

Public API, action input/output, language server behavior, and failure semantics: lsp-tools.md.

Source: DEFAULT_CONFIG.lsp, normalizeLspConfig(), src/modules/lsp/register.ts, src/modules/lsp/tool.ts, src/modules/lsp/hook.ts, src/modules/lsp/schemas.ts.

KeyTypeDefaultRequiredPurposeRelated source
lsp.enabledbooleantrueNoWhether to enable entire LSP modulesrc/modules/lsp/register.ts
lsp.tool.enabledbooleantrueNoWhether to register explicit lsp toolsrc/modules/lsp/register.ts, src/modules/lsp/tool.ts
lsp.tool.allowMutatingActionsbooleanfalseNoWhether to allow main agent process to call rename, codeAction, restart; subagent processes always disabledsrc/modules/lsp/tool.ts
lsp.hook.enabledbooleantrueNoWhether to enable automatic diagnostics hook; only registered in main agent processsrc/modules/lsp/register.ts, src/modules/lsp/hook.ts
lsp.hook.modeagent_end / edit_write / disabledagent_endNoHook trigger timing. disabled resolves to hook.enabled=false, hook.mode="disabled"src/config/load-config.ts, src/modules/lsp/hook.ts

lsp tool actions from src/modules/lsp/schemas.ts:

text
definition, references, hover, symbols, diagnostics, workspace-diagnostics,
signature, rename, codeAction, restart, servers

Readonly-safe actions (can be exposed to subagents via subagents.allowedLspActions):

text
definition, references, hover, signature, symbols, diagnostics, workspace-diagnostics, servers

Privileged actions:

text
rename, codeAction, restart

Example: disable LSP hook but retain explicit lsp tool.

json
{
  "lsp": {
    "hook": {
      "enabled": false
    }
  }
}

Example: allow main agent to use mutating actions (subagents still disabled).

json
{
  "lsp": {
    "tool": {
      "allowMutatingActions": true
    }
  }
}

Web base configuration

Source: DEFAULT_WEB_CONFIG, normalizeWebConfig(), src/modules/web/register.ts, src/modules/web/search.ts, src/modules/web/fetch.ts, src/modules/web/storage.ts.

KeyTypeDefaultRequiredPurposeRelated source
web.enabledbooleantrueNoWhether to register web_search, fetch_content, get_search_contentsrc/modules/web/register.ts
web.providerstringddgsNoSearch provider: auto / brave / ddgs / openserp / searxng / tavily / serpersrc/config/load-config.ts, src/modules/web/providers/select-provider.ts
web.providerPrioritystring[]['tavily','serper','brave','openserp','searxng','ddgs']NoCandidate order for provider="auto". Source code applies this priority after layering by commercial / self-host-or-open / zero-configsrc/modules/web/providers/select-provider.ts
web.timeoutMsnumber10000Noweb/provider/fetch request timeout in mssrc/modules/web/abort.ts, providers
web.maxResponseBytesnumber1048576NoMax response body bytes for fetch_content downloads and search provider responsessrc/modules/web/fetch.ts, src/modules/web/read-limited.ts
web.maxContentCharsnumber30000NoMax tool return content characterssrc/modules/web/fetch.ts, src/modules/web/storage.ts
web.maxResultsnumber5NoDefault search result countsrc/modules/web/search.ts
web.maxStoredResultsnumber100NoMax responseId storage retained result entriessrc/modules/web/storage.ts, src/modules/web/register.ts
web.maxStoredContentCharsnumber200000NoMax single stored content characterssrc/modules/web/storage.ts, src/modules/web/register.ts
web.allowPrivateNetworkbooleanfalseNoWhether to allow fetch_content to access localhost / private IP / .local / .internalsrc/modules/web/security.ts, src/modules/web/fetch.ts
web.debugfalse / minimal / verbosefalseNoWeb observability debug output level; configuring true normalizes to minimalsrc/modules/web/observability.ts

Example: use auto provider selection and increase result count.

json
{
  "web": {
    "provider": "auto",
    "maxResults": 8
  }
}

Example: allow fetching local development server.

json
{
  "web": {
    "allowPrivateNetwork": true
  }
}

Web providers configuration

Provider names from WebSearchProviderName in src/shared/types.ts and src/modules/web/providers/registry.ts. Provider selection logic in src/modules/web/providers/select-provider.ts.

ddgs

KeyTypeDefaultRequiredPurposeRelated source
No namespace config---Default zero-config provider, uses DuckDuckGo Lite fallbacksrc/modules/web/providers/ddgs.ts

brave

KeyTypeDefaultRequiredPurposeRelated source
web.brave.enabledbooleanfalseNoSelection enabled gate for explicit and auto modessrc/modules/web/providers/select-provider.ts
web.brave.baseUrlstringhttps://api.search.brave.com/res/v1/web/searchNoBrave Search API endpointsrc/modules/web/providers/brave.ts
web.brave.apiKeyEnvstringBRAVE_SEARCH_API_KEYNoWhich environment variable to read API key fromsrc/modules/web/providers/brave.ts

openserp

KeyTypeDefaultRequiredPurposeRelated source
web.openserp.enabledbooleanfalseNoSelection enabled gate for explicit and auto modessrc/modules/web/providers/select-provider.ts
web.openserp.baseUrlstringhttps://api.openserp.com/searchNoOpenSERP endpointsrc/config/load-config.ts
web.openserp.apiKeyEnvstringOPENSERP_API_KEYNoWhich environment variable to read API key fromsrc/modules/web/providers/openserp.ts

searxng

KeyTypeDefaultRequiredPurposeRelated source
web.searxng.enabledbooleanfalseNoSelection enabled gate for explicit and auto modessrc/modules/web/providers/select-provider.ts
web.searxng.baseUrlstring""NoSearXNG base URL; must be valid http/https URL to be availablesrc/modules/web/providers/searxng.ts
web.searxng.defaultEnginestringgoogleNoDefault value for request parameter enginessrc/modules/web/providers/searxng.ts

tavily

KeyTypeDefaultRequiredPurposeRelated source
web.tavily.enabledbooleanfalseNoSelection enabled gate for explicit and auto modessrc/modules/web/providers/select-provider.ts
web.tavily.baseUrlstringhttps://api.tavily.com/searchNoTavily endpointsrc/modules/web/providers/tavily.ts
web.tavily.apiKeyEnvstringTAVILY_API_KEYNoWhich environment variable to read API key fromsrc/modules/web/providers/tavily.ts

serper

KeyTypeDefaultRequiredPurposeRelated source
web.serper.enabledbooleanfalseNoSelection enabled gate for explicit and auto modessrc/modules/web/providers/select-provider.ts
web.serper.baseUrlstringhttps://google.serper.dev/searchNoSerper endpointsrc/modules/web/providers/serper.ts
web.serper.apiKeyEnvstringSERPER_API_KEYNoWhich environment variable to read API key fromsrc/modules/web/providers/serper.ts

provider="auto" behavior

Auto mode filters providers by the same enabled gate and technical availability checks used by explicit mode, then applies providerPriority. Current source code divides candidate providers into three tiers:

  1. commercial: tavily, serper, brave
  2. self-host-or-open: openserp, searxng
  3. zero-config: ddgs

Final order is sorted by providerPriority within each tier, then concatenated. Default configuration equivalent to:

text
tavily → serper → brave → openserp → searxng → ddgs

Selection availability combines provider enabled gates with adapter-level technical checks. For example, brave requires web.brave.enabled=true, a valid baseUrl, and an API key from web.brave.apiKeyEnv; searxng requires web.searxng.enabled=true and a valid http/https baseUrl.

Web cache configuration

Source: src/modules/web/cache.ts, src/modules/web/register.ts.

KeyTypeDefaultRequiredPurposeRelated source
web.cache.enabledbooleanfalseNoWhether to enable search result cachesrc/modules/web/cache.ts
web.cache.maxEntriesnumber50NoMax cache entriessrc/modules/web/cache.ts
web.cache.ttlMsnumber300000NoCache TTL in mssrc/modules/web/cache.ts

Example:

json
{
  "web": {
    "cache": {
      "enabled": true,
      "maxEntries": 100,
      "ttlMs": 600000
    }
  }
}

Web concurrency configuration

Source: src/modules/web/concurrency.ts, src/modules/web/register.ts.

KeyTypeDefaultRequiredPurposeRelated source
web.concurrency.maxConcurrentnumber3NoMax simultaneously executing web requestssrc/modules/web/concurrency.ts
web.concurrency.maxQueueSizenumber10NoMax waiting queue lengthsrc/modules/web/concurrency.ts

Example:

json
{
  "web": {
    "concurrency": {
      "maxConcurrent": 2,
      "maxQueueSize": 20
    }
  }
}

Web connection pool configuration

Source: src/modules/web/http-pool.ts, src/modules/web/register.ts.

KeyTypeDefaultRequiredPurposeRelated source
web.connectionPool.maxSocketsnumber10NoHTTP/HTTPS agent max socketssrc/modules/web/http-pool.ts
web.connectionPool.maxFreeSocketsnumber5NoKeep-alive idle socket limitsrc/modules/web/http-pool.ts
web.connectionPool.timeoutnumber60000NoSocket timeout in mssrc/modules/web/http-pool.ts

Example:

json
{
  "web": {
    "connectionPool": {
      "maxSockets": 20,
      "maxFreeSockets": 10,
      "timeout": 60000
    }
  }
}

Jina Reader configuration

Source: DEFAULT_WEB_CONFIG, src/modules/web/fetch.ts, src/modules/web/security.ts, src/modules/web/schemas.ts.

KeyTypeDefaultRequiredPurposeRelated source
web.enableJinaFallbackbooleanfalseNoWhether to enable Jina Reader fallback. When not enabled, preferReader also won't trigger Jinasrc/modules/web/fetch.ts
web.jinaTimeoutMsnumber8000NoJina request timeout in mssrc/modules/web/fetch.ts
web.jinaTriggersstring[]["short-html", "js-heavy-html"]NoAuto-trigger Jina conditions; empty array means no auto-trigger, but preferReader still works when fallback enabledsrc/modules/web/fetch.ts

fetch_content tool schema also has parameter:

json
{
  "preferReader": true
}

It is not a config item, but a single tool call parameter. Private network URLs are not sent to Jina to avoid leaking localhost/private network addresses.

Example: enable Jina fallback.

json
{
  "web": {
    "enableJinaFallback": true,
    "jinaTimeoutMs": 8000,
    "jinaTriggers": ["short-html", "js-heavy-html"]
  }
}

Convert content configuration

convert_content is an optional document conversion tool. The current public tool supports local path conversion and remote url conversion through the configured MarkItDown CLI provider. Remote URLs are safely downloaded to a temporary file before conversion. TUI renderers and toolkit-level activity integration are implemented. The MarkItDown provider uses shared external command infrastructure for command resolution/execution while keeping convert-specific validation and error mapping in src/modules/convert/provider.ts.

Source: DEFAULT_CONVERT_CONTENT_CONFIG, normalizeConvertContentConfig(), src/modules/convert/index.ts, src/modules/convert/schemas.ts, src/modules/convert/errors.ts, src/modules/convert/provider.ts, src/modules/convert/renderers.ts, src/modules/convert/observability.ts.

KeyTypeDefaultRequiredPurposeRelated source
convertContent.enabledbooleantrueNoWhether to register the convert_content toolsrc/modules/convert/index.ts
convertContent.providermarkitdownmarkitdownNoConversion provider name. Current config normalizes all values to markitdownsrc/config/load-config.ts
convertContent.commandstringmarkitdownNoExternal MarkItDown CLI command/path used by the internal MarkItDown provider; resolved/executed through shared external command infrastructuresrc/config/load-config.ts, src/modules/convert/provider.ts, src/shared/external-command.ts
convertContent.timeoutMsnumber30000NoTimeout in ms for remote download and MarkItDown provider execution; must be positive integersrc/config/load-config.ts, src/modules/convert/security.ts, src/modules/convert/provider.ts
convertContent.maxResponseBytesnumber10485760NoMax local/remote source bytes for conversion execution; must be positive integersrc/config/load-config.ts, src/modules/convert/security.ts, src/modules/convert/provider.ts
convertContent.maxContentCharsnumber50000NoMax returned Markdown characters; provider output beyond this limit is truncated with truncated=truesrc/config/load-config.ts, src/modules/convert/provider.ts
convertContent.allowPrivateNetworkbooleanfalseNoWhether URL download may access private-network targets; defaults to blocked. Every redirect hop is revalidated with this policysrc/config/load-config.ts, src/modules/convert/security.ts

Current tool schema fields:

json
{
  "path": "./document.pdf",
  "url": "https://example.com/document.pdf",
  "maxContentChars": 50000,
  "timeoutMs": 30000
}

path and url are mutually exclusive at execution time; providing both or neither returns INVALID_INPUT. path converts an existing local file inside the active workspace (process.cwd() for the extension process) through MarkItDown; paths outside the workspace return INVALID_INPUT. url is validated, safely downloaded to a temporary file, size-limited by maxResponseBytes, converted through MarkItDown, and then cleaned up. URL redirects are followed manually and each hop reruns private-network validation.

Example: disable convert_content registration.

json
{
  "convertContent": {
    "enabled": false
  }
}

Example: configure MarkItDown command path.

json
{
  "convertContent": {
    "command": "/usr/local/bin/markitdown"
  }
}

Commands configuration

Public command list, parameters, output, and failure semantics: toolkit-commands.md.

Source: DEFAULT_CONFIG.commands, normalizeCommandsConfig(), src/modules/commands/register.ts.

KeyTypeDefaultRequiredPurposeRelated source
commands.enabledbooleantrueNoWhether to enable unified /toolkit developer command. Subagent processes never register this commandsrc/modules/commands/register.ts

Current /toolkit subcommands:

text
doctor, modules, logs, agents, lsp, activity, help

Example:

json
{
  "commands": {
    "enabled": false
  }
}

Guards configuration

Source: DEFAULT_CONFIG.guards, normalizeGuardsConfig(), src/modules/guards/*.

Guards are lightweight session notices. They use UI notification/status channels when available, do not block tool calls, and do not trigger follow-up agent turns.

KeyTypeDefaultRequiredPurposeRelated source
guards.enabledbooleantrueNoWhether to register lightweight session guard notices in the main agent processsrc/modules/guards/index.ts
guards.gitContextNoticebooleantrueNoAfter the first tool result in a session, show repo/branch/worktree context once when the current cwd is inside a git worktreesrc/modules/guards/git-context.ts
guards.firstWriteReminderbooleantrueNoBefore the first likely write tool call in a session, show current branch/worktree context oncesrc/modules/guards/index.ts, src/modules/guards/tool-classifier.ts
guards.verificationReminderbooleantrueNoAt agent end, if the current turn appears to have modified files but no verification command was detected, show a soft remindersrc/modules/guards/index.ts, src/modules/guards/command-classifier.ts

Current behavior: gitContextNotice, firstWriteReminder, and verificationReminder are implemented. Git commands use a short timeout and silently degrade when git is unavailable, the cwd is not a git repo, or git commands fail. Write classification is conservative: explicit file-editing tools are treated as writes, and bash/shell are only treated as writes for obvious mutating commands such as redirection, rm, mv, cp, sed -i, tee, apply_patch, selected git mutating commands, or package installs. Verification classification is also conservative and recognizes common test/lint/typecheck/build commands such as pnpm test, npm run lint, tsc --noEmit, cargo test, pytest, go test, cmake --build, ctest, and biome check. Subagent child processes do not register guards.

Example:

json
{
  "guards": {
    "gitContextNotice": false
  }
}

Common combination examples

Minimal: only enable subagents

json
{
  "web": { "enabled": false },
  "lsp": { "enabled": false },
  "commands": { "enabled": false },
  "subagents": { "enabled": true }
}

Enable web auto provider with cache

json
{
  "web": {
    "provider": "auto",
    "cache": {
      "enabled": true,
      "maxEntries": 50,
      "ttlMs": 300000
    }
  }
}

Disable LSP hook but retain subagent readonly LSP

json
{
  "lsp": {
    "tool": { "enabled": true },
    "hook": { "enabled": false }
  },
  "subagents": {
    "allowLspTools": true,
    "allowedLspActions": ["definition", "references", "hover", "symbols", "diagnostics", "servers"]
  }
}

Known environment / future notes

  1. subagents.allowWrite is not a stable write-capability contract

    • Configuration item exists, defaults to false.
    • Currently recorded as experimental/advanced/unsafe switch; default and recommended mode is still readonly.
    • If formally supporting writable custom subagents in the future, permission strategy, audit logging, rollback recommendations, and test coverage should be supplemented separately.
  2. LSP language server availability depends on local environment

    • Configuration only controls whether devkit-pi registers tools/hooks, not automatic language server installation.