Skip to content

fix: load per-group CLAUDE.local.md by adding 'local' to settingSources#2598

Merged
gavrielc merged 1 commit into
nanocoai:mainfrom
jonnychesthair-crypto:fix/load-claude-local-settingsources
May 23, 2026
Merged

fix: load per-group CLAUDE.local.md by adding 'local' to settingSources#2598
gavrielc merged 1 commit into
nanocoai:mainfrom
jonnychesthair-crypto:fix/load-claude-local-settingsources

Conversation

@jonnychesthair-crypto
Copy link
Copy Markdown
Contributor

Type of Change

  • Feature skill - adds a channel or integration (source code changes + SKILL.md)
  • Utility skill - adds a standalone tool (code files in .claude/skills/<name>/, no source changes)
  • Operational/container skill - adds a workflow or agent skill (SKILL.md only, no source changes)
  • Fix - bug fix or security fix to source code
  • Simplification - reduces or simplifies source code
  • Documentation - docs, README, or CONTRIBUTING changes only

Description

What — Add 'local' to the agent-runner's Agent SDK settingSources so each group's CLAUDE.local.md is loaded into the agent's context.

-        settingSources: ['project', 'user'],
+        settingSources: ['project', 'user', 'local'],

container/agent-runner/src/providers/claude.ts

Why — Per the Agent SDK docs, the three setting sources load different files:

Source What it loads
'project' Project CLAUDE.md, .claude/rules/*.md, skills, hooks, settings.json
'user' User CLAUDE.md, user settings
'local' CLAUDE.local.md, .claude/settings.local.json

Omitting settingSources is equivalent to ["user", "project", "local"].

The agent-runner passes settingSources: ['project', 'user'], which omits 'local'. Because CLAUDE.local.md is loaded only by the 'local' source ('project' loads CLAUDE.md, not CLAUDE.local.md), every group's CLAUDE.local.md is silently never read.

This breaks the convention the codebase tells agents to rely on. container/CLAUDE.md instructs every agent: "CLAUDE.local.md in your workspace is your per-group memory. Record things there that you'll want to remember in future sessions." Today those writes never load back, so per-group memory and persona edits are dropped.

Reported in #2185. An import-based alternative was explored in #2567; this takes the settingSources route the docs point to, so no composer/@import change is needed.

How it works — Including 'local' restores the SDK's documented default set (['user', 'project', 'local']) for the one file the agent already writes to. One line, no other changes.

How tested — Verified against the SDK docs table above: 'local' is the source that loads CLAUDE.local.md, and an explicit settingSources array excludes any source not listed. Reviewer repro (from #2185): add Always reply with the word PINEAPPLE first. to a group's CLAUDE.local.md, then message the agent — ignored before this change, obeyed after.

Closes #2185.

The agent-runner runs the Agent SDK with settingSources: ['project', 'user'], which omits 'local'. Per the SDK docs the 'local' source is what loads CLAUDE.local.md (the 'project' source loads CLAUDE.md). So every group's CLAUDE.local.md is silently never read, even though container/CLAUDE.md tells each agent to use it as per-group memory.

Closes nanocoai#2185.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@jonnychesthair-crypto
Copy link
Copy Markdown
Contributor Author

Empirical confirmation (controlled A/B).

I ran the Agent SDK directly (@anthropic-ai/claude-agent-sdk 0.2.138, claude-code 2.1.128) against a workspace holding a CLAUDE.md and a CLAUDE.local.md whose only instruction was "begin every reply with the word PINEAPPLE." Same prompt, same cwd, same systemPrompt preset — the only variable is settingSources:

settingSources = ["project", "user"]
  REPLY: "Hello! Happy to help — what would you like to work on in the pineapple test workspace today?"
  starts_with_PINEAPPLE: false        <- CLAUDE.local.md rule NOT applied

settingSources = ["project", "user", "local"]
  REPLY: "PINEAPPLE Hello, glad to be working with you today!"
  starts_with_PINEAPPLE: true         <- CLAUDE.local.md rule applied

Note the first reply still references "pineapple test workspace" — that phrase is in CLAUDE.md, which the project source does load. So project loads CLAUDE.md but not CLAUDE.local.md; only adding local loads the latter, matching the settingSources docs table ('local'CLAUDE.local.md; omitting settingSources defaults to ["user","project","local"]).

This confirms the bug behaviorally: with the current settingSources: ['project', 'user'], per-group CLAUDE.local.md is silently never read. Adding 'local' fixes it.

jonnychesthair-crypto added a commit to jonnychesthair-crypto/nanoclaw that referenced this pull request May 23, 2026
… local settingSource

- Wire createOchsnerEmailBlockHook into ClaudeProvider PreToolUse (matcher mcp gmail send_email/draft_email) to deny ochsner.org recipients.
- Add local to settingSources so per-group CLAUDE.local.md loads (mirrors upstream PR nanocoai#2598); document explicit-import behavior in claude-md-compose.ts.
- New file: ochsner-email-block.ts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@gavrielc gavrielc merged commit 136cb4d into nanocoai:main May 23, 2026
1 of 2 checks passed
@gavrielc
Copy link
Copy Markdown
Collaborator

@jonnychesthair-crypto Thank you for the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: Fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

claude-md-compose.ts builds CLAUDE.md without importing CLAUDE.local.md — per-group memory never loaded by the SDK

2 participants