Building on Claude
Claude Code is extensible. You can build custom tools, integrate with your systems, and create workflows that go beyond the built-in capabilities.
Extension Points
Section titled “Extension Points”| Method | Use Case | Complexity |
|---|---|---|
| Custom slash commands | Team workflows, shortcuts | Low |
| MCP servers | Connect to external tools/data | Medium |
| Hooks | Enforce policies, add automation | Medium |
| SDK | Programmatic control | High |
Custom Slash Commands
Section titled “Custom Slash Commands”The simplest extension—markdown files that become commands.
Directory.claude/
Directorycommands/
- deploy.md
- review.md
- ticket.md
Example: Deployment Command
Section titled “Example: Deployment Command”Deploy the current branch to staging:
1. Run tests first: `npm test`2. Build: `npm run build`3. Deploy: `./scripts/deploy-staging.sh`4. Verify the deployment at https://staging.example.com5. Report any errors
Ask for confirmation before deploying.Usage:
> /deployExample: Ticket Context
Section titled “Example: Ticket Context”I'm working on ticket: $ARGUMENTS
1. Read the ticket from our issue tracker (if accessible)2. Understand the requirements3. Identify which files need changes4. Propose an implementation plan
Wait for approval before implementing.Usage:
> /ticket AUTH-123Custom MCP Servers
Section titled “Custom MCP Servers”MCP servers connect Claude to external tools and data sources.
When to Build an MCP Server
Section titled “When to Build an MCP Server”- Access internal APIs
- Query proprietary databases
- Integrate with internal tools
- Provide domain-specific context
Basic MCP Server Structure
Section titled “Basic MCP Server Structure”from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-company-tools")
@mcp.tool()def get_ticket(ticket_id: str) -> str: """Fetch a Jira ticket by ID.
Args: ticket_id: Ticket ID like PROJ-123 """ ticket = fetch_from_jira(ticket_id) return json.dumps(ticket)
if __name__ == "__main__": mcp.run()Registering Your Server
Section titled “Registering Your Server”claude mcp add my-tools -- python /path/to/my_mcp_server.pyMCP Server Ideas
Section titled “MCP Server Ideas”| Server | Purpose |
|---|---|
| Jira/Linear client | Fetch ticket context |
| Internal docs search | Query your wiki |
| Database explorer | Safe read-only queries |
| Deployment status | Check environments |
| Feature flags | Current flag states |
Hooks for Automation
Section titled “Hooks for Automation”Hooks run scripts at key points. See Hooks for full details.
Common Extension Patterns
Section titled “Common Extension Patterns”Auto-format on save:
{ "hooks": { "PostToolUse": [{ "matcher": { "tool": "Write" }, "hooks": [{ "type": "command", "command": "prettier --write $FILE_PATH" }] }] }}Notify on completion:
{ "hooks": { "Stop": [{ "hooks": [{ "type": "command", "command": "notify-send 'Claude finished'" }] }] }}Log all commands:
{ "hooks": { "PostToolUse": [{ "matcher": { "tool": "Bash" }, "hooks": [{ "type": "command", "command": "echo \"$(date): $COMMAND\" >> ~/.claude/command-log.txt" }] }] }}SDK for Programmatic Control
Section titled “SDK for Programmatic Control”The Claude Code SDK enables building tools on top of Claude.
Installation
Section titled “Installation”uv add claude-code-sdkBasic Usage
Section titled “Basic Usage”import asynciofrom claude_code_sdk import ClaudeCode
async def main(): claude = ClaudeCode()
# Run a task result = await claude.run( prompt="Add input validation to src/forms/user.py", working_directory="/path/to/project" )
print(result.output)
asyncio.run(main())Streaming Responses
Section titled “Streaming Responses”async def stream_example(): claude = ClaudeCode()
async for chunk in claude.stream(prompt="Explain this codebase"): print(chunk.text, end="")
asyncio.run(stream_example())Handling Tool Approvals
Section titled “Handling Tool Approvals”async def with_approval(): claude = ClaudeCode()
def on_tool_use(tool): # Custom approval logic if tool.name == "Bash" and "rm" in tool.command: return {"approved": False, "reason": "Destructive commands blocked"} return {"approved": True}
result = await claude.run( prompt="Run the test suite", on_tool_use=on_tool_use )
asyncio.run(with_approval())Building Wrappers
Section titled “Building Wrappers”Create specialized tools for your team:
Example: PR Review Tool
Section titled “Example: PR Review Tool”#!/usr/bin/env python3import subprocessimport sysimport asynciofrom claude_code_sdk import ClaudeCode
async def review_pr(pr_number: str): diff = subprocess.check_output(["gh", "pr", "diff", pr_number], text=True)
claude = ClaudeCode() result = await claude.run( prompt=f""" Review this PR diff for: - Security issues - Performance problems - Code quality
{diff} """, model="claude-sonnet-4-5" )
# Post as PR comment subprocess.run(["gh", "pr", "comment", pr_number, "--body", result.output])
if __name__ == "__main__": asyncio.run(review_pr(sys.argv[1]))Usage:
python scripts/review_pr.py 123Example: Batch Processor
Section titled “Example: Batch Processor”# Process multiple tasks in sequenceimport asynciofrom claude_code_sdk import ClaudeCode
async def batch_process(tasks: list[str]): claude = ClaudeCode()
for task in tasks: print(f"Processing: {task}") await claude.run(prompt=task)
asyncio.run(batch_process([ "Add docstrings to src/services/", "Add type hints to src/models/", "Update README with new API endpoints"]))When to Build vs. Use Vanilla
Section titled “When to Build vs. Use Vanilla”Build Custom Tooling When:
Section titled “Build Custom Tooling When:”- Same workflow repeated daily
- Team needs standardization
- Integration with internal systems required
- Automation in CI/CD needed
Use Vanilla Claude Code When:
Section titled “Use Vanilla Claude Code When:”- One-off tasks
- Exploratory work
- Tasks requiring human judgment
- Prototyping/experimentation
Architecture Patterns
Section titled “Architecture Patterns”The Wrapper Pattern
Section titled “The Wrapper Pattern”Your Script │ ├── Pre-processing (gather context) │ ├── Claude Code SDK call │ └── Post-processing (parse results, take action)The Pipeline Pattern
Section titled “The Pipeline Pattern”Task Definition │ ├── Claude: Planning │ ├── Claude: Implementation │ ├── Automated: Testing │ └── Claude: Review & FixThe Event-Driven Pattern
Section titled “The Event-Driven Pattern”Git Hook / CI Event │ └── Trigger Claude workflow │ └── Report results back to system