Skip to content

Claude Code features in the SDK

Load CLAUDE.md, rules, skills, hooks and other filesystem configuration into Agent SDK sessions, and control exactly which sources an agent reads.

An SDK agent sits on the same foundation as Claude Code, so it can pick up the same filesystem configuration: CLAUDE.md and rules files, skills, hooks, subagents, commands and settings. That is powerful when you want an agent to follow the conventions your team already wrote down for the CLI, and a liability when you want a deployed agent to behave identically everywhere. This page is about controlling which of those inputs load.

The default: same as the CLI

Leave settingSources unset and query() reads exactly what the CLI would: user, project and local settings, CLAUDE.md files, and the skills, agents and commands under .claude/. Pass an empty list and the agent gets only what you configure in code.

A handful of inputs are read regardless; they are listed under what settingSources does not cover.

Choosing sources with settingSources

settingSources (TypeScript) or setting_sources (Python) takes a list of any of "user", "project" and "local". Leaving it out is the same as passing all three.

Here is an agent for a client project that should follow the repository's own CLAUDE.md and hooks, but not my personal preferences from ~/.claude:

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const msg of query({
  prompt: "Add pagination to the /orders endpoint, following our API conventions",
  options: {
    cwd: "/work/clients/ridgeway-api",
    settingSources: ["project"],
    allowedTools: ["Read", "Edit", "Glob", "Grep", "Bash"],
  },
})) {
  if (msg.type === "result" && msg.subtype === "success") console.log(msg.result);
}
opts = ClaudeAgentOptions(
    cwd="/work/clients/ridgeway-api",
    setting_sources=["project"],
    allowed_tools=["Read", "Edit", "Glob", "Grep", "Bash"],
)

What each source loads

<cwd> below means the cwd option, or the process's current directory if you did not set one.

"project"

  • settings.json and its hooks from <cwd>/.claude/ only. There is no fallback to parent directories for these.
  • CLAUDE.md and .claude/rules/*.md from <cwd> and every parent directory.
  • Skills, commands and subagents from .claude/skills/, .claude/commands/ and .claude/agents/ in <cwd> and each parent up to the repository root.
  • The same three folders inside any directory you add with additionalDirectories / add_dirs (which the SDK passes to Claude Code as --add-dir).

"user"

  • ~/.claude/settings.json, ~/.claude/CLAUDE.md and ~/.claude/rules/*.md.
  • Skills, commands and subagents from ~/.claude/skills/, ~/.claude/commands/ and ~/.claude/agents/.

"local"

  • <cwd>/.claude/settings.local.json.
  • CLAUDE.local.md in <cwd> and every parent directory.

What settingSources does not cover

These are read whatever you pass, which matters if you are relying on settingSources: [] for isolation.

InputWhen it loadsHow to switch it off
Managed policy settingsEndpoint policy (MDM plist, registry policy or managed settings file) loads from the host. Server-managed settings are fetched on eligible setups when the session authenticates with a qualifying credential: an organisation OAuth login, a directly configured API key, or a user_oauth Anthropic profile.Endpoint policy: remove it from the host. Server-managed settings: controlled by an Owner in your Claude organisation; you cannot turn them off from the SDK.
~/.claude.json global configAlwaysPoint CLAUDE_CONFIG_DIR elsewhere through env
Auto memory in ~/.claude/projects/<project>/memory/Added to the system prompt at session start. The agent saves new memories using the ordinary Write and Edit tools, so those must be enabled for saving to work.autoMemoryEnabled: false in settings, or CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 in env
claude.ai MCP connectorsWhen the session authenticates with a claude.ai login. Not when CLAUDE_CODE_OAUTH_TOKEN holds a claude setup-token token, which can only make model requests. Passing mcpServers: {} does not stop them.strictMcpConfig: true, disableClaudeAiConnectors: true in settings, or ENABLE_CLAUDEAI_MCP_SERVERS=false in env
sandbox.credentials deny entries and file mask entries in ~/.claude/settings.jsonApplied whenever the command sandbox runs, even if user settings are excluded. They only ever narrow what sandboxed commands can reach.Remove them from ~/.claude/settings.json

Warning: Default options are not a multi-tenant isolation boundary. Because of the inputs above, an SDK process can absorb host-level configuration and per-directory memory. For multi-tenant services, give each tenant its own filesystem, pass settingSources: [] and set CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 in env. Server-managed settings still arrive if the process authenticates with an organisation credential. Secure deployment covers the rest.

CLAUDE.md and rules

CLAUDE.md and .claude/rules/*.md files give the agent standing context: build commands, naming conventions, architecture decisions, things never to touch. Load the right source and the agent follows them without being told in every prompt.

WhereFilesNeeds sourceLoaded
Project root<cwd>/CLAUDE.md or <cwd>/.claude/CLAUDE.md"project"Session start
Project rules.claude/rules/*.md in <cwd> and every parent"project"Session start
Parent foldersCLAUDE.md above <cwd>"project"Session start
SubfoldersCLAUDE.md below <cwd>"project"On demand, when Claude works in that folder
LocalCLAUDE.local.md in <cwd> and every parent"local"Session start
User~/.claude/CLAUDE.md"user"Session start
User rules~/.claude/rules/*.md"user"Session start

Everything is additive. If a user file and a project file disagree, there is no formal winner: Claude reads both and interprets them. Avoid conflicts, or say explicitly in the more specific file which one wins, for example "Where these project rules disagree with personal defaults, follow these."

If you do not need the same instructions shared with interactive sessions, you can skip CLAUDE.md and put context straight into the system prompt; see modifying system prompts. For writing good CLAUDE.md files, see memory.

Skills

Skills are Markdown files with specialist knowledge or a repeatable workflow. Unlike CLAUDE.md, they are not loaded in full every session: the agent sees a short description at startup and pulls in the body only when it is relevant.

Skills are found on disk through settingSources. The skills option then controls which are enabled:

skills valueEffect
omittedDiscovered user and project skills are on, and the Skill tool is available (same as the CLI)
"all"Every discovered skill is on
["release-notes", "pr-review"]Only the named skills are on
[]All skills off

When you set skills, the SDK adds Skill to allowedTools for you. If you also give an explicit tools list, include "Skill" in it, or Claude cannot call skills.

opts = ClaudeAgentOptions(
    setting_sources=["project"],
    skills=["release-notes"],
    allowed_tools=["Read", "Grep", "Bash"],
)

Note: There is no API for registering a skill in code. A skill is always a file at .claude/skills/<name>/SKILL.md. SDK skills has the details.

Hooks

You can define hooks in two ways, and both run together:

  • Filesystem hooks in settings.json, loaded through settingSources. These are the same hooks you would write for the CLI; see the hooks guide.
  • Programmatic hooks: callback functions passed in the hooks option. They run in your process and return structured decisions; see SDK hooks.

A callback that returns an empty object lets the tool proceed. To stop it, return hookSpecificOutput with permissionDecision: "deny" and a permissionDecisionReason, which Claude receives as the tool result.

A Python example that keeps an agent out of production config, alongside whatever hooks the project already defines:

from claude_agent_sdk import ClaudeAgentOptions, HookMatcher

async def guard_prod_config(input_data, tool_use_id, context):
    path = input_data.get("tool_input", {}).get("file_path", "")
    if "/config/production" in path:
        return {
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason": "Production config is managed by the platform team.",
            }
        }
    return {}

opts = ClaudeAgentOptions(
    setting_sources=["project"],
    hooks={"PreToolUse": [HookMatcher(matcher="Edit|Write", hooks=[guard_prod_config])]},
)

The same in TypeScript, narrowing on the event name to get the right input type:

import type { HookInput, HookJSONOutput } from "@anthropic-ai/claude-agent-sdk";

const guardProdConfig = async (input: HookInput): Promise<HookJSONOutput> => {
  if (input.hook_event_name !== "PreToolUse") return {};
  const { file_path } = input.tool_input as { file_path?: string };
  if (file_path?.includes("/config/production")) {
    return {
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "deny",
        permissionDecisionReason: "Production config is managed by the platform team.",
      },
    };
  }
  return {};
};

Filesystem or programmatic?

KindGood forNotes
Filesystem (settings.json)Hooks shared between CLI users and SDK agentsTypes: command, http, mcp_tool, prompt and agent. Fire in the main agent and its subagents.
Programmatic (callbacks)Application logic and in-process integrationAlso fire inside subagents. The input includes agent_id and agent_type so you can tell which agent triggered it.

TypeScript supports some events Python does not yet have, including SessionStart, SessionEnd, TeammateIdle and TaskCompleted. The hooks reference documents the filesystem syntax.

Picking the right feature

You want toUseHow in the SDK
Apply project conventions on every runCLAUDE.mdsettingSources: ["project"]
Give reference material Claude reads when relevantSkillssettingSources plus skills
Package a repeatable workflow (release, review, deploy)User-invocable skillssettingSources plus skills
Send a self-contained subtask to a fresh contextSubagentsagents option, with Agent allowed
Coordinate several Claude Code instances with shared tasks and messagingAgent teamsNot an SDK option; a CLI feature where one session leads
Run deterministic checks on tool callsHookshooks callbacks, or shell hooks via settingSources
Give structured access to an external serviceMCPmcpServers

Everything you switch on takes up some context. The features overview breaks down the cost of each.