You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add an optional settingSources field to the @deepseek-ai/dsh-subagent-claude-code provider config so a profile can control which SDK settings sources Claude Code loads.
Fork PRs are disabled on this repo, so I'm posting the full patch here instead of a PR. A clean view of the diff is also on the fork: ThomasNil@ca5e88c
Behavior
Omitted (default) — the option is not passed to the SDK, so Claude Code keeps its native behavior: loads the host's user, project, and local settings relative to the parent Session cwd. No change from today.
Configured (['user'], ['project'], ['user','project','local'], …) — passes the array through to the SDK, restricting which settings files load.
[] — isolates a run from all settings files.
Implementation note
schemastery's z.array carries an implicit default of [] (unlike z.string/z.number), which would make the field silently resolve to [] instead of undefined when absent. The schema overrides it with .default(undefined as unknown as SettingSource[]), matching the existing optional-array idiom in core/system-prompt. Both the spec construction and claudeQueryOptions only forward the value when it is defined, so the default path emits an options object byte-identical to before.
Testing
packages/subagent/subagent-claude-code: 46 tests pass (adds a unit case asserting a configured settingSources: ['user'] reaches the SDK options; the existing default-case "absent" assertion is unchanged).
docs/config-catalog.md regenerated (pnpm run gen-config-catalog) and verified fresh.
No version bump — left to the maintainer.
Patch
diff --git a/docs/config-catalog.md b/docs/config-catalog.md
index 7e4e4b6..cb86dd3 100644
--- a/docs/config-catalog.md
+++ b/docs/config-catalog.md
@@ -2392,6 +2392,12 @@ export interface Config {
* `bypassPermissions` explicitly skips permission checks.
*/
permissionMode?: ClaudeCodePermissionMode
+ /**
+ * SDK settings sources fixed for this Provider instance; omitted to let
+ * the SDK load the host's user, project, and local settings. An explicit
+ * `[]` isolates a run from all settings files.
+ */
+ settingSources?: SettingSource[]
/** Grace in milliseconds for Claude Code process-tree termination. */
disposeGraceMs?: number
}
@@ -2400,7 +2406,9 @@ export interface Config {
export type ClaudeCodePermissionMode = typeof CLAUDE_CODE_PERMISSION_MODES[number]
diff --git a/packages/subagent/subagent-claude-code/README.md b/packages/subagent/subagent-claude-code/README.md
index 9fcce15..f6f847f 100644
--- a/packages/subagent/subagent-claude-code/README.md
+++ b/packages/subagent/subagent-claude-code/README.md
@@ -47,6 +47,7 @@ Removing the package withdraws the provider and its private runtime closure on t
| model | native Claude settings | Optional non-empty model name fixed for every run from this provider instance; omission sends no SDK override |
| env | {} | Explicit SDK/CLI environment layered over the credential-scrubbed parent environment |
| permissionMode | dontAsk | Native non-interactive permission policy fixed for every run from this provider instance |
+| settingSources | unset (SDK default: all sources) | Optional array of "user", "project", and/or "local" restricting which SDK settings sources load; unset lets the SDK load the host's user, project, and local settings, while an explicit [] isolates a run from all settings files |
| disposeGraceMs | 3000 | Grace between the shared process-tree owner's termination tiers |
| permissionMode value | Native behavior |
@@ -57,7 +58,7 @@ Removing the package withdraws the provider and its private runtime closure on t
| plan | Run in native planning mode, deny execution approval, and return the completed plan as the final answer |
| bypassPermissions | Explicitly set the SDK's dangerous confirmation and bypass permission checks |
-The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc. A configured model passes unchanged to every query from that provider instance; omission leaves native model selection in force. Credential-shaped ambient variables are removed before the explicit env overlay, so an API key intended for the child must be supplied there. The provider omits the SDK settingSources option, so Claude Code reads the host's normal user, project, and local settings relative to the parent Session cwd. It does not copy or filter those files, create or modify login state, inspect PATH, or fall back to a host claude executable.
+The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc. A configured model passes unchanged to every query from that provider instance; omission leaves native model selection in force. Credential-shaped ambient variables are removed before the explicit env overlay, so an API key intended for the child must be supplied there. By default the provider omits the SDK settingSources option, so Claude Code reads the host's normal user, project, and local settings relative to the parent Session cwd; configuring settingSources restricts that to the named sources, or replaces it entirely with an explicit [] that isolates the run from all settings files. It does not copy or filter those files, create or modify login state, inspect PATH, or fall back to a host claude executable.
Exposing the tool
@@ -100,7 +101,7 @@ This section explains how the provider drives a real Claude Code CLI and where t
Design concept
One fresh query per run. Every run has an independent SDK query, cancellation controller, CLI process, and non-persisted product session; there is no continuation, resume, or pooling.
-- Native settings are authoritative. The provider deliberately omits the SDK settingSources option, so Claude Code reads the host's normal user, project, and local settings; an optional model and the required permissionMode are the only query-level overrides.
+- Native settings are authoritative by default. The provider omits the SDK settingSources option unless a Profile row configures it, so Claude Code reads the host's normal user, project, and local settings; an optional model, the required permissionMode, and an optional settingSources are the only query-level overrides.
Unattended by design.AskUserQuestion is disabled and permission prompts are denied except in bypass mode, so the query never waits for a user interface.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Proposal
Add an optional
settingSourcesfield to the@deepseek-ai/dsh-subagent-claude-codeprovider config so a profile can control which SDK settings sources Claude Code loads.Fork PRs are disabled on this repo, so I'm posting the full patch here instead of a PR. A clean view of the diff is also on the fork: ThomasNil@ca5e88c
Behavior
['user'],['project'],['user','project','local'], …) — passes the array through to the SDK, restricting which settings files load.[]— isolates a run from all settings files.Implementation note
schemastery'sz.arraycarries an implicit default of[](unlikez.string/z.number), which would make the field silently resolve to[]instead ofundefinedwhen absent. The schema overrides it with.default(undefined as unknown as SettingSource[]), matching the existing optional-array idiom incore/system-prompt. Both the spec construction andclaudeQueryOptionsonly forward the value when it is defined, so the default path emits an options object byte-identical to before.Testing
packages/subagent/subagent-claude-code: 46 tests pass (adds a unit case asserting a configuredsettingSources: ['user']reaches the SDK options; the existing default-case "absent" assertion is unchanged).docs/config-catalog.mdregenerated (pnpm run gen-config-catalog) and verified fresh.No version bump — left to the maintainer.
Patch
-Source:
packages/subagent/subagent-claude-code/src/index.ts:38+Depends on:
SettingSource(@anthropic-ai/claude-agent-sdk)+
+Source:
packages/subagent/subagent-claude-code/src/index.ts:39diff --git a/packages/subagent/subagent-claude-code/README.md b/packages/subagent/subagent-claude-code/README.md
index 9fcce15..f6f847f 100644
--- a/packages/subagent/subagent-claude-code/README.md
+++ b/packages/subagent/subagent-claude-code/README.md
@@ -47,6 +47,7 @@ Removing the package withdraws the provider and its private runtime closure on t
|
model| native Claude settings | Optional non-empty model name fixed for every run from this provider instance; omission sends no SDK override ||
env|{}| Explicit SDK/CLI environment layered over the credential-scrubbed parent environment ||
permissionMode|dontAsk| Native non-interactive permission policy fixed for every run from this provider instance |+|
settingSources| unset (SDK default: all sources) | Optional array of"user","project", and/or"local"restricting which SDK settings sources load; unset lets the SDK load the host's user, project, and local settings, while an explicit[]isolates a run from all settings files ||
disposeGraceMs|3000| Grace between the shared process-tree owner's termination tiers ||
permissionModevalue | Native behavior |@@ -57,7 +58,7 @@ Removing the package withdraws the provider and its private runtime closure on t
|
plan| Run in native planning mode, deny execution approval, and return the completed plan as the final answer ||
bypassPermissions| Explicitly set the SDK's dangerous confirmation and bypass permission checks |-The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc. A configured
modelpasses unchanged to every query from that provider instance; omission leaves native model selection in force. Credential-shaped ambient variables are removed before the explicitenvoverlay, so an API key intended for the child must be supplied there. The provider omits the SDKsettingSourcesoption, so Claude Code reads the host's normal user, project, and local settings relative to the parent Session cwd. It does not copy or filter those files, create or modify login state, inspectPATH, or fall back to a hostclaudeexecutable.+The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc. A configured
modelpasses unchanged to every query from that provider instance; omission leaves native model selection in force. Credential-shaped ambient variables are removed before the explicitenvoverlay, so an API key intended for the child must be supplied there. By default the provider omits the SDKsettingSourcesoption, so Claude Code reads the host's normal user, project, and local settings relative to the parent Session cwd; configuringsettingSourcesrestricts that to the named sources, or replaces it entirely with an explicit[]that isolates the run from all settings files. It does not copy or filter those files, create or modify login state, inspectPATH, or fall back to a hostclaudeexecutable.Exposing the tool
@@ -100,7 +101,7 @@ This section explains how the provider drives a real Claude Code CLI and where t
Design concept
-- Native settings are authoritative. The provider deliberately omits the SDK
settingSourcesoption, so Claude Code reads the host's normal user, project, and local settings; an optionalmodeland the requiredpermissionModeare the only query-level overrides.+- Native settings are authoritative by default. The provider omits the SDK
settingSourcesoption unless a Profile row configures it, so Claude Code reads the host's normal user, project, and local settings; an optionalmodel, the requiredpermissionMode, and an optionalsettingSourcesare the only query-level overrides.AskUserQuestionis disabled and permission prompts are denied except in bypass mode, so the query never waits for a user interface.Source map
diff --git a/packages/subagent/subagent-claude-code/src/index.ts b/packages/subagent/subagent-claude-code/src/index.ts
index c853fc6..f406542 100644
--- a/packages/subagent/subagent-claude-code/src/index.ts
+++ b/packages/subagent/subagent-claude-code/src/index.ts
@@ -6,6 +6,7 @@
*/
+import type { SettingSource } from '@anthropic-ai/claude-agent-sdk'
import type { Context } from '@deepseek-ai/cordis'
import z from '@deepseek-ai/schemastery'
import { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'
@@ -52,6 +53,12 @@ export interface Config {
*
bypassPermissionsexplicitly skips permission checks.*/
permissionMode?: ClaudeCodePermissionMode
[]isolates a run from all settings files./** Grace in milliseconds for Claude Code process-tree termination. */
disposeGraceMs?: number
}
@@ -62,10 +69,12 @@ export const Config: z = z.object({
env: z.dict(z.string()).default({}),
permissionMode: z.union([...CLAUDE_CODE_PERMISSION_MODES])
.default(DEFAULT_CLAUDE_CODE_PERMISSION_MODE),
disposeGraceMs: z.number().default(DEFAULT_DISPOSE_GRACE_MS),
})
-type ResolvedConfig = Omit<Required, 'model'> & Pick<Config, 'model'>
+type ResolvedConfig = Omit<Required, 'model' | 'settingSources'> & Pick<Config, 'model' | 'settingSources'>
/* jscpd:ignore-end */
/* jscpd:ignore-start -- Cordis registration and shared-seam plumbing mirror
@@ -111,6 +120,7 @@ class ClaudeCodeProvider implements SubagentProvider {
cwd,
...this.config.model === undefined ? {} : { model: this.config.model },
permissionMode: this.config.permissionMode,
@@ -128,7 +138,8 @@ class ClaudeCodeProvider implements SubagentProvider {
/**
*/
export function apply(ctx: Context, config: Config): void {
const resolved: ResolvedConfig = {
@@ -136,6 +147,7 @@ export function apply(ctx: Context, config: Config): void {
...config.model === undefined ? {} : { model: config.model },
env: config.env as Record<string, string>,
permissionMode: config.permissionMode ?? DEFAULT_CLAUDE_CODE_PERMISSION_MODE,
...config.settingSources === undefined ? {} : { settingSources: config.settingSources },
disposeGraceMs: config.disposeGraceMs as number,
}
assertPositiveFinite(
diff --git a/packages/subagent/subagent-claude-code/src/run.ts b/packages/subagent/subagent-claude-code/src/run.ts
index ca50fe4..bd52f45 100644
--- a/packages/subagent/subagent-claude-code/src/run.ts
+++ b/packages/subagent/subagent-claude-code/src/run.ts
@@ -13,6 +13,7 @@ import {
type Query,
type SDKMessage,
type SDKResultMessage,
type SettingSource,
type SpawnOptions,
} from '@anthropic-ai/claude-agent-sdk'
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
@@ -153,6 +154,8 @@ export interface ClaudeCodeRunSpec {
readonly model?: string
/** Profile-selected native non-interactive permission mode. */
readonly permissionMode: ClaudeCodePermissionMode
/** Profile-selected SDK settings sources; omitted to preserve host settings. */
readonly settingSources?: SettingSource[]
/** Explicit deployment/test environment layered after shared scrubbing. /
readonly env: Record<string, string>
/* Subprocess termination grace passed to the shared process-tree owner. */
@@ -326,6 +329,7 @@ export function claudeQueryOptions(
? ['AskUserQuestion', 'ExitPlanMode']
: ['AskUserQuestion'],
permissionMode: spec.permissionMode,
...spec.settingSources === undefined ? {} : { settingSources: spec.settingSources },
...spec.permissionMode === 'bypassPermissions'
? { allowDangerouslySkipPermissions: true }
: {
diff --git a/packages/subagent/subagent-claude-code/tests/subagent-claude-code.spec.ts b/packages/subagent/subagent-claude-code/tests/subagent-claude-code.spec.ts
index 650ce6b..64ba26b 100644
--- a/packages/subagent/subagent-claude-code/tests/subagent-claude-code.spec.ts
+++ b/packages/subagent/subagent-claude-code/tests/subagent-claude-code.spec.ts
@@ -975,6 +975,21 @@ describe('query options and result mapping', () => {
},
)
it('threads a configured settingSources onto the SDK options', () => {
const child = fakeChild()
const options = claudeQueryOptions({
}, new AbortController(), () => {}, () => {})
expect(options).toMatchObject({
})
})
it('disallows ExitPlanMode before native plan-mode allow rules', () => {
const child = fakeChild()
const options = claudeQueryOptions({
All reactions