obsidian/wiki/agent-sdk/claude-code-features-in-sdk.md
2026-04-17 13:22:20 +01:00

128 lines
5.6 KiB
Markdown

---
title: "Use Claude Code Features in the SDK"
aliases: [setting-sources, sdk-claude-md, sdk-skills-hooks]
tags: [agent-sdk, settings, skills, hooks, claude-md, configuration]
sources: [raw/Use Claude Code features in the SDK.md]
created: 2026-04-17
updated: 2026-04-17
---
# Use Claude Code Features in the SDK
SDK agents share the same filesystem-based feature layer as the Claude Code CLI: `CLAUDE.md` instructions, skills, hooks, and settings. The `settingSources` option controls which of these load.
## settingSources
Controls which filesystem locations the SDK reads at startup.
| Source | Loads from | Contents |
|--------|-----------|----------|
| `"project"` | `<cwd>/.claude/` and parent dirs | CLAUDE.md, `.claude/rules/*.md`, project skills, project hooks, `settings.json` |
| `"user"` | `~/.claude/` | User CLAUDE.md, `~/.claude/rules/*.md`, user skills, user settings |
| `"local"` | `<cwd>/` | `CLAUDE.local.md` (gitignored), `settings.local.json` |
- Omitting `settingSources` → equivalent to `["user", "project", "local"]`
- Pass `settingSources: []` to disable all three (programmatic-only mode)
```python
options=ClaudeAgentOptions(
setting_sources=["user", "project"],
allowed_tools=["Read", "Edit", "Bash"],
)
```
### What settingSources does NOT control
These load regardless:
| Input | To disable |
|-------|-----------|
| Managed policy settings | Remove the managed settings file |
| `~/.claude.json` global config | Relocate with `CLAUDE_CONFIG_DIR` in `env` |
| Auto memory (`~/.claude/projects/<project>/memory/`) | `autoMemoryEnabled: false` or `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` |
**Multi-tenant isolation:** use separate filesystems per tenant + `settingSources: []` + `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1`. See [[wiki/agent-sdk/secure-deployment|secure-deployment]].
## Project Instructions (CLAUDE.md and rules)
- Loaded when `settingSources` includes `"project"`
- All levels are **additive** — project + user CLAUDE.md both load, no hard precedence
- Child-dir `CLAUDE.md` files load on demand when agent reads a file in that subtree
| Level | Location |
|-------|---------|
| Project root | `<cwd>/CLAUDE.md` or `<cwd>/.claude/CLAUDE.md` |
| Project rules | `<cwd>/.claude/rules/*.md` |
| Parent dirs | CLAUDE.md in any ancestor of `cwd` |
| Child dirs | CLAUDE.md in subdirs (loaded on demand) |
| Local (gitignored) | `<cwd>/CLAUDE.local.md` |
| User | `~/.claude/CLAUDE.md`, `~/.claude/rules/*.md` |
If instructions conflict, state precedence explicitly in the more specific file. Alternatively inject context via `systemPrompt` — see [[wiki/agent-sdk/modifying-system-prompts|modifying-system-prompts]].
## Skills
- Discovered from `.claude/skills/` via `settingSources`
- Descriptions loaded at startup; full content loads on demand
- `"Skill"` tool is enabled by default unless you use an `allowedTools` allowlist (then add it explicitly)
```python
options=ClaudeAgentOptions(
setting_sources=["user", "project"],
allowed_tools=["Skill", "Read", "Grep", "Glob"],
)
```
Skills are filesystem artifacts (`SKILL.md`) — no programmatic registration API. See [[wiki/agent-sdk/skills-in-sdk|skills-in-sdk]].
## Hooks
Two types run side by side:
| Type | Best for | Scope |
|------|---------|-------|
| **Filesystem** (`settings.json`) | Shared CLI + SDK hooks; supports `command`, `http`, `prompt`, `agent` types | Main agent + all subagents |
| **Programmatic** (callbacks in `query()`) | App-specific logic, structured decisions, in-process integration | Main session only |
```python
async def audit_bash(input_data, tool_use_id, context):
if "rm -rf" in input_data.get("tool_input", {}).get("command", ""):
return {"decision": "block", "reason": "Destructive command blocked"}
return {} # empty dict = allow
options=ClaudeAgentOptions(
setting_sources=["project"], # loads hooks from .claude/settings.json
hooks={
"PreToolUse": [HookMatcher(matcher="Bash", hooks=[audit_bash])]
},
)
```
TypeScript SDK adds extra events: `SessionStart`, `SessionEnd`, `TeammateIdle`, `TaskCompleted`. See [[wiki/agent-sdk/sdk-hooks|sdk-hooks]].
## Feature Selection Guide
| Goal | Feature | SDK surface |
|------|---------|-------------|
| Project conventions always present | CLAUDE.md | `settingSources: ["project"]` |
| Reference material loaded when relevant | Skills | `settingSources` + `allowedTools: ["Skill"]` |
| Reusable workflow (deploy, review) | User-invocable skills | same as above |
| Isolated subtask, fresh context | Subagents | `agents` param + `allowedTools: ["Agent"]` |
| Coordinate multiple Claude Code instances | Agent teams (CLI feature) | not SDK-configurable |
| Deterministic logic on tool calls | Hooks | `hooks` callbacks or `settings.json` |
| External service with structured tools | MCP | `mcpServers` parameter |
**Context cost reminder:** every enabled feature adds to the context window. See the features-overview cost analysis.
## Key Takeaways
- `settingSources` selects which filesystem locations load — omit it for full parity with the CLI, pass `[]` for programmatic-only
- Three inputs always load regardless of `settingSources`: managed policy, `~/.claude.json`, auto memory
- CLAUDE.md levels are additive; write non-conflicting rules or state precedence explicitly
- Skills load descriptions at startup, full content on demand — include `"Skill"` in `allowedTools` when using an allowlist
- Filesystem hooks and programmatic hooks coexist; filesystem hooks propagate to subagents, programmatic do not
- For multi-tenant deployments: isolated filesystem + `settingSources: []` + disable auto memory
## Sources
- `raw/Use Claude Code features in the SDK.md`