SpyBara
Go Premium

agent-sdk/claude-code-features.md 2026-04-15 18:20 UTC to 2026-04-16 21:13 UTC

18 added, 6 removed.

2026
Wed 29 21:21 Tue 28 21:21 Mon 27 21:20 Sun 26 04:08 Sat 25 21:10 Fri 24 18:11 Thu 23 18:19 Wed 22 21:15 Tue 21 21:14 Mon 20 21:14 Sat 18 18:09 Fri 17 21:13 Thu 16 21:13 Wed 15 18:20 Tue 14 21:14 Mon 13 21:14 Sat 11 00:11 Fri 10 21:09 Thu 9 21:14 Wed 8 21:13 Tue 7 21:14 Sat 4 18:05 Fri 3 21:07 Thu 2 21:08 Wed 1 21:12

Use Claude Code features in the SDK

Load project instructions, skills, hooks, and other Claude Code features into your SDK agents.

The Agent SDK is built on the same foundation as Claude Code, which means your SDK agents have access to the same filesystem-based features: project instructions (CLAUDE.md and rules), skills, hooks, and more.

When you omit settingSources, query() reads the same filesystem settings as the Claude Code CLI: user, project, and local settings, CLAUDE.md files, and .claude/ skills, agents, and commands. To run without these, pass settingSources: [], which limits the agent to what you configure programmatically. Managed policy settings and the global ~/.claude.json config are read regardless of this option. See What settingSources does not control.

For a conceptual overview of what each feature does and when to use it, see Extend Claude Code.

Control filesystem settings with settingSources

The setting sources option (setting_sources in Python, settingSources in TypeScript) controls which filesystem-based settings the SDK loads. Pass an explicit list to opt in to specific sources, or pass an empty array to disable user, project, and local settings.

This example loads both user-level and project-level settings by setting settingSources to ["user", "project"]:

from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage

async for message in query(
prompt="Help me refactor the auth module",
options=ClaudeAgentOptions(
# "user" loads from ~/.claude/, "project" loads from ./.claude/ in cwd.
# Together they give the agent access to CLAUDE.md, skills, hooks, and
# permissions from both locations.
setting_sources=["user", "project"],
allowed_tools=["Read", "Edit", "Bash"],
),
):
if isinstance(message, AssistantMessage):
for block in message.content:
if hasattr(block, "text"):
print(block.text)
if isinstance(message, ResultMessage) and message.subtype == "success":
print(f"\nResult: {message.result}")

Each source loads settings from a specific location, where <cwd> is the working directory you pass via the cwd option (or the process's current directory if unset). For the full type definition, see SettingSource (TypeScript) or SettingSource (Python).

Source What it loads Location
"project" Project CLAUDE.md, .claude/rules/*.md, project skills, project hooks, project settings.json <cwd>/.claude/ and each parent directory up to the filesystem root (stopping when a .claude/ is found or no more parents exist)
"user" User CLAUDE.md, ~/.claude/rules/*.md, user skills, user settings ~/.claude/
"local" CLAUDE.local.md (gitignored), .claude/settings.local.json <cwd>/

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

The cwd option determines where the SDK looks for project settings. If neither cwd nor any of its parent directories contains a .claude/ folder, project-level features won't load.

What settingSources does not control

settingSources covers user, project, and local settings. A few inputs are read regardless of its value:

Input Behavior To disable
Managed policy settings Always loaded when present on the host Remove the managed settings file
~/.claude.json global config Always read Relocate with CLAUDE_CONFIG_DIR in env
Auto memory at ~/.claude/projects/<project>/memory/ Loaded by default into the system prompt Set autoMemoryEnabled: false in settings, or CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 in env

Project instructions (CLAUDE.md and rules)

CLAUDE.md files and .claude/rules/*.md files give your agent persistent context about your project: coding conventions, build commands, architecture decisions, and instructions. When settingSources includes "project" (as in the example above), the SDK loads these files into context at session start. The agent then follows your project conventions without you repeating them in every prompt.

CLAUDE.md load locations

Level Location When loaded
Project (root) <cwd>/CLAUDE.md or <cwd>/.claude/CLAUDE.md settingSources includes "project"
Project rules <cwd>/.claude/rules/*.md settingSources includes "project"
Project (parent dirs) CLAUDE.md files in directories above cwd settingSources includes "project", loaded at session start
Project (child dirs) CLAUDE.md files in subdirectories of cwd settingSources includes "project", loaded on demand when the agent reads a file in that subtree
Local (gitignored) <cwd>/CLAUDE.local.md settingSources includes "local"
User ~/.claude/CLAUDE.md settingSources includes "user"
User rules ~/.claude/rules/*.md settingSources includes "user"

All levels are additive: if both project and user CLAUDE.md files exist, the agent sees both. There is no hard precedence rule between levels; if instructions conflict, the outcome depends on how Claude interprets them. Write non-conflicting rules, or state precedence explicitly in the more specific file ("These project instructions override any conflicting user-level defaults").

For how to structure and organize CLAUDE.md content, see Manage Claude's memory.

Skills

Skills are markdown files that give your agent specialized knowledge and invocable workflows. Unlike CLAUDE.md (which loads every session), skills load on demand. The agent receives skill descriptions at startup and loads the full content when relevant.

Skills are discovered from the filesystem through settingSources. With default options, user and project skills load automatically. The Skill tool is enabled by default when you don't specify allowedTools. If you are using an allowedTools allowlist, include "Skill" explicitly.

from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

# Skills in .claude/skills/ are discovered automatically
# when settingSources includes "project"
async for message in query(
prompt="Review this PR using our code review checklist",
options=ClaudeAgentOptions(
setting_sources=["user", "project"],
allowed_tools=["Skill", "Read", "Grep", "Glob"],
),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)

For more on creating and using skills, see Agent Skills in the SDK.

Hooks

The SDK supports two ways to define hooks, and they run side by side:

  • Filesystem hooks: shell commands defined in settings.json, loaded when settingSources includes the relevant source. These are the same hooks you'd configure for interactive Claude Code sessions.
  • Programmatic hooks: callback functions passed directly to query(). These run in your application process and can return structured decisions. See Control execution with hooks.

Both types execute during the same hook lifecycle. If you already have hooks in your project's .claude/settings.json and you set settingSources: ["project"], those hooks run automatically in the SDK with no extra configuration.

Hook callbacks receive the tool input and return a decision dict. Returning {} (an empty dict) means allow the tool to proceed. Returning {"decision": "block", "reason": "..."} prevents execution and the reason is sent to Claude as the tool result. See the hooks guide for the full callback signature and return types.

from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, ResultMessage


# PreToolUse hook callback. Positional args:
#   input_data: HookInput dict with tool_name, tool_input, hook_event_name
#   tool_use_id: str | None, the ID of the tool call being intercepted
#   context: HookContext, carries session metadata
async def audit_bash(input_data, tool_use_id, context):
command = input_data.get("tool_input", {}).get("command", "")
if "rm -rf" in command:
return {"decision": "block", "reason": "Destructive command blocked"}
return {}  # Empty dict: allow the tool to proceed


# Filesystem hooks from .claude/settings.json run automatically
# when settingSources loads them. You can also add programmatic hooks:
async for message in query(
prompt="Refactor the auth module",
options=ClaudeAgentOptions(
setting_sources=["project"],  # Loads hooks from .claude/settings.json
hooks={
"PreToolUse": [
HookMatcher(matcher="Bash", hooks=[audit_bash]),
]
},
),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)

When to use which hook type

Hook type Best for
Filesystem (settings.json) Sharing hooks between CLI and SDK sessions. Supports "command" (shell scripts), "http" (POST to an endpoint), "prompt" (LLM evaluates a prompt), and "agent" (spawns a verifier agent). These fire in the main agent and any subagents it spawns.
Programmatic (callbacks in query()) Application-specific logic; returning structured decisions; in-process integration. Scoped to the main session only.

For full details on programmatic hooks, see Control execution with hooks. For filesystem hook syntax, see Hooks.

Choose the right feature

The Agent SDK gives you access to several ways to extend your agent's behavior. If you're unsure which to use, this table maps common goals to the right approach.

You want to... Use SDK surface
Set project conventions your agent always follows CLAUDE.md settingSources: ["project"] loads it automatically
Give the agent reference material it loads when relevant Skills settingSources + allowedTools: ["Skill"]
Run a reusable workflow (deploy, review, release) User-invocable skills settingSources + allowedTools: ["Skill"]
Delegate an isolated subtask to a fresh context (research, review) Subagents agents parameter + allowedTools: ["Agent"]
Coordinate multiple Claude Code instances with shared task lists and direct inter-agent messaging Agent teams Not directly configured via SDK options. Agent teams are a CLI feature where one session acts as the team lead, coordinating work across independent teammates
Run deterministic logic on tool calls (audit, block, transform) Hooks hooks parameter with callbacks, or shell scripts loaded via settingSources
Give Claude structured tool access to an external service MCP mcpServers parameter

Every feature you enable adds to your agent's context window. For per-feature costs and how these features layer together, see Extend Claude Code.

  • Extend Claude Code: Conceptual overview of all extension features, with comparison tables and context cost analysis
  • Skills in the SDK: Full guide to using skills programmatically
  • Subagents: Define and invoke subagents for isolated subtasks
  • Hooks: Intercept and control agent behavior at key execution points
  • Permissions: Control tool access with modes, rules, and callbacks
  • System prompts: Inject context without CLAUDE.md files