Settings Sources in the Claude Agent SDK
How to load project CLAUDE.md files, skills, and settings.json hooks into your agent. The three source layers and why most SDK agents only need the project source.
Why settings sources exist
Claude Code uses a layered configuration system. There are user-level settings (global across your machine), project-level settings (specific to the folder you are working in), and local settings (personal overrides). Files like CLAUDE.md, skills files, and settings.json live within this system.
When you build an agent with the SDK, it runs in isolation from those configuration files by default. It does not read your project's CLAUDE.md. It does not load your skills. It does not apply your settings.json hooks.
settingSources is the option that changes this. It tells the SDK which configuration layers to read.
The three setting source options
for await (const message of query(messages(), {
model: "claude-sonnet-4-5",
settingSources: ["user", "project", "local"],
permissionMode: "bypassPermissions",
dangerouslyAllowBypassPermissions: true,
})) {
// handle messages
}
| Source | What it loads |
|---|---|
"user" | Global settings — your personal ~/.claude/ folder with skills, MCP servers, global CLAUDE.md |
"project" | Project-level settings — the .claude/ folder in your current working directory |
"local" | Personal overrides — settings.local.json in the project directory |
You can pass any combination. Most SDK use cases only need "project".
A concrete example
Create a CLAUDE.md file in your project directory:
My name is Alex. Please refer to me as Alex throughout our conversation.
Without settingSources:
// settingSources not set — CLAUDE.md is ignored
for await (const message of query(messages(), {
model: "claude-sonnet-4-5",
permissionMode: "bypassPermissions",
dangerouslyAllowBypassPermissions: true,
})) { ... }
// Agent does not know the user's name
With settingSources: ["project"]:
for await (const message of query(messages(), {
model: "claude-sonnet-4-5",
settingSources: ["project"],
permissionMode: "bypassPermissions",
dangerouslyAllowBypassPermissions: true,
})) { ... }
// Agent reads CLAUDE.md, responds: "Hi Alex..."
When you need settingSources
Three features depend on it:
Skills. The skill tool reads skill files from .claude/skills/. Without settingSources: ["project"], the agent cannot find or use those files even if they exist.
Lifecycle hooks via settings.json. If you define a session_start hook in .claude/settings.json, it only fires when settingSources includes "project". The lifecycle hooks guide shows this in practice.
Project-level MCP servers. MCP servers configured in the project's settings.json are only available when the project source is loaded.
> The mistake most people make: They set up a .claude/settings.json with a hook, run their agent, and the hook does nothing. The cause is almost always a missing settingSources: ["project"]. This is worth adding to a checklist whenever you set up hooks or skills in a new project.
Running on a user's machine vs in the cloud
When the SDK runs on your machine during development, "user" settings pull in whatever you have configured globally — your personal Claude Code MCP servers, your global skills, your global CLAUDE.md. That can be useful for development but you probably do not want those in a production deployment.
In the cloud, there is no user-level configuration. The Docker container starts clean. "project" is the only relevant source, and it maps to whatever you deploy with the code.
This distinction matters when you test locally with "user" settings that include personal MCP servers and then deploy without them — the agent's capabilities change. Keep production-facing agents scoped to "project" only.
---
Author: FractionalSkill