Skip to main content

Claude Code CLI Agent Primer

AI-Optimized Primer | Production-ready patterns for Claude Code CLI agents and automation

Primer Metadata
  • Category: Development Tools
  • Difficulty: Intermediate to Advanced
  • Examples: 47 copy-paste code blocks
  • Tokens: 16,500+ comprehensive coverage
  • Last Updated: September 15, 2025
  • AI-Ready: Optimized for agent consumption

A condensed guide for building and deploying CLI AI agents with Claude Code

Table of Contents

  1. Core Architecture & Philosophy
  2. Installation & Authentication
  3. Essential CLI Usage Patterns
  4. Agent Architecture Framework
  5. Tool System & Permissions
  6. Model Context Protocol (MCP) Integration
  7. Configuration & Settings Hierarchy
  8. Subagent System
  9. Hooks & Automation
  10. SDK Integration Patterns
  11. Production Deployment
  12. Security & Best Practices

Core Architecture & Philosophy

Design Principles

Claude Code follows Unix philosophy with modern AI capabilities:

  • Composability: Works with pipes, scripts, and existing toolchains
  • Transparency: All actions are explicit and auditable
  • Stateful Context: Maintains conversation history and project awareness
  • Permission-based Security: Granular control over tool access
  • Extensibility: MCP servers, subagents, and hooks for customization

Architecture Overview

┌─────────────────┐    ┌──────────────┐    ┌─────────────────┐
│ User Input │───▶│ Claude Agent │───▶│ Tool System │
└─────────────────┘ └──────────────┘ └─────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ MCP Servers │ │ Permission Gate │
└──────────────────┘ └─────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ Subagents │ │ Hooks System │
└──────────────────┘ └─────────────────┘

Installation & Authentication

Installation Options

NPM Install (Recommended)

npm install -g @anthropic-ai/claude-code

Native Install (Beta)

# macOS, Linux, WSL
curl -fsSL https://claude.ai/install.sh | bash

# Windows PowerShell
irm https://claude.ai/install.ps1 | iex

Authentication Methods

Interactive Login

claude
# First run prompts for authentication
/login # Re-authenticate or switch accounts

API Key Authentication

export ANTHROPIC_API_KEY="your-api-key"
claude -p "query"

Third-party Providers

# Amazon Bedrock
export CLAUDE_CODE_USE_BEDROCK=1
# Configure AWS credentials separately

# Google Vertex AI
export CLAUDE_CODE_USE_VERTEX=1
# Configure Google Cloud credentials separately

Essential CLI Usage Patterns

Interactive Mode

# Start interactive session
claude

# With initial prompt
claude "explain this project structure"

# Continue most recent conversation
claude -c

# Resume specific conversation
claude -r

Headless Mode (SDK)

# Single query, then exit
claude -p "analyze this error log"

# With output formatting
claude -p "check for bugs" --output-format json

# Process piped content
cat error.log | claude -p "explain this error"

# Integration with scripts
claude -p "run tests and report failures" --max-turns 5

File and Directory References

# Reference specific files (includes full content)
claude -p "Explain the logic in @src/auth.js"

# Reference directories (shows structure)
claude -p "What's in @components directory?"

# Multiple references
claude -p "Compare @file1.js and @file2.js"

Permission Modes

# Start in plan mode (read-only analysis)
claude --permission-mode plan

# Start with auto-accept for edits
claude --permission-mode acceptEdits

# Dangerous: skip all permission prompts
claude --dangerously-skip-permissions

Agent Architecture Framework

Core Agent Loop

  1. Input Processing: Parse user intent and context
  2. Tool Selection: Choose appropriate tools based on task
  3. Permission Validation: Check tool usage against permission rules
  4. Execution: Run tools with proper error handling
  5. Result Integration: Synthesize outputs into coherent response
  6. Context Management: Update conversation state and memory

Session Management

# Session persistence
claude -c # Continue most recent
claude -r # Resume from picker

# Session with specific configuration
claude --model sonnet --verbose

# Background session management
claude -p "task" & # Run in background

Context Management

Claude Code automatically manages context through:

  • Conversation History: Full message threads with tool results
  • Project Awareness: Understands file structure and dependencies
  • Memory Files: CLAUDE.md files for persistent context
  • Automatic Compaction: Reduces context size while preserving key information

Tool System & Permissions

Core Tools Available

ToolDescriptionPermission Required
BashExecute shell commandsYes
EditTargeted file modificationsYes
MultiEditMultiple atomic edits per fileYes
ReadFile content accessNo
WriteCreate/overwrite filesYes
GlobPattern-based file searchNo
GrepContent search with regexNo
WebFetchHTTP content retrievalYes
WebSearchWeb search with filteringYes
TaskSubagent delegationNo
TodoWriteTask list managementNo

Permission Configuration

Allow specific tools

{
"permissions": {
"allow": [
"Bash(git diff:*)",
"Bash(npm run:*)",
"Read(~/.config/*)"
]
}
}

Deny sensitive operations

{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl:*)",
"WebFetch"
]
}
}

CLI Permission Flags

# Allow specific tools
claude --allowedTools "Bash(git:*)" "Read" "Edit"

# Block dangerous tools
claude --disallowedTools "WebFetch" "Bash(rm:*)"

Model Context Protocol (MCP) Integration

MCP Server Types

Local Stdio Servers

# Basic installation
claude mcp add airtable --env AIRTABLE_API_KEY=key \
-- npx -y airtable-mcp-server

# With custom timeout
MCP_TIMEOUT=10000 claude mcp add slow-server \
-- python slow_server.py

Remote HTTP Servers

# Standard HTTP MCP
claude mcp add notion --transport http https://mcp.notion.com/mcp

# With authentication headers
claude mcp add api --transport http https://api.company.com/mcp \
--header "Authorization: Bearer token"

Server-Sent Events (SSE)

# Real-time streaming servers
claude mcp add linear --transport sse https://mcp.linear.app/sse

# OAuth authentication handled via /mcp command

MCP Configuration Scopes

ScopeLocationSharingUse Case
localUser settingsPersonalDevelopment, testing
project.mcp.jsonTeam-wideShared integrations
user~/.claude/Cross-projectPersonal utilities

MCP Resource Usage

# Reference MCP resources with @
claude -p "Analyze @github:issue://123"

# Multiple resource references
claude -p "Compare @db:schema://users with @docs:spec://user-model"

# MCP prompts as slash commands
/mcp__github__create_issue "Bug in auth" high

Development & Testing

  • Sentry: Error monitoring and debugging
  • Socket: Security analysis for dependencies
  • Hugging Face: ML model and dataset access
  • Jam: Debug recordings with video/logs

Project Management

  • Linear, Asana, Monday: Issue tracking
  • Notion, Confluence: Documentation
  • Slack, Intercom: Communication

Data & Commerce

  • Stripe, PayPal, Square: Payment processing
  • Airtable, HubSpot: Database management
  • Figma, Canva: Design integration

Infrastructure

  • Cloudflare, Netlify, Vercel: Deployment
  • AWS, GCP integrations via respective CLIs

Configuration & Settings Hierarchy

Settings Precedence (Highest to Lowest)

  1. Enterprise Managed Policies (managed-settings.json)
  2. Command Line Arguments (session-specific)
  3. Local Project Settings (.claude/settings.local.json)
  4. Shared Project Settings (.claude/settings.json)
  5. User Settings (~/.claude/settings.json)

Configuration Structure

{
"model": "claude-3-5-sonnet-20241022",
"outputStyle": "Explanatory",
"permissions": {
"defaultMode": "plan",
"allow": ["Bash(git:*)", "Read", "Edit"],
"deny": ["WebFetch", "Read(./.env)"],
"additionalDirectories": ["../docs/"]
},
"env": {
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "50000",
"MCP_TIMEOUT": "15000"
},
"hooks": {
"PostToolUse": [{
"matcher": "Edit|MultiEdit|Write",
"hooks": [{"type": "command", "command": "prettier --write $file"}]
}]
},
"statusLine": {
"type": "command",
"command": "~/.claude/status.sh"
}
}

Environment Variables

Authentication

ANTHROPIC_API_KEY          # Direct API access
ANTHROPIC_AUTH_TOKEN # Custom bearer token
CLAUDE_CODE_USE_BEDROCK=1 # Amazon Bedrock
CLAUDE_CODE_USE_VERTEX=1 # Google Vertex AI

Behavior Control

CLAUDE_CODE_MAX_OUTPUT_TOKENS=50000    # Token limits
MAX_MCP_OUTPUT_TOKENS=25000 # MCP response limits
MCP_TIMEOUT=10000 # MCP startup timeout
BASH_DEFAULT_TIMEOUT_MS=120000 # Command timeouts
DISABLE_TELEMETRY=1 # Privacy control

Subagent System

Subagent Architecture

Subagents are specialized AI instances with:

  • Isolated Context: Separate conversation thread
  • Custom System Prompts: Task-specific instructions
  • Tool Restrictions: Limited access to specific tools
  • Automatic Delegation: Invoked based on task matching

Creating Subagents

File Structure

---
name: code-reviewer
description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
tools: Read, Grep, Glob, Bash
---

You are a senior code reviewer ensuring high standards of code quality and security.

When invoked:
1. Run git diff to see recent changes
2. Focus on modified files
3. Begin review immediately

Review checklist:
- Code is simple and readable
- Functions and variables are well-named
- No duplicated code
- Proper error handling
- No exposed secrets or API keys
- Input validation implemented
- Good test coverage
- Performance considerations addressed

Provide feedback organized by priority:
- Critical issues (must fix)
- Warnings (should fix)
- Suggestions (consider improving)

Include specific examples of how to fix issues.

Storage Locations

  • Project: .claude/agents/ (shared with team)
  • User: ~/.claude/agents/ (personal across projects)

Using Subagents

Automatic Delegation

# Claude automatically selects appropriate subagent
claude -p "review my recent code changes for security issues"
claude -p "run all tests and fix any failures"

Explicit Invocation

claude -p "use the code-reviewer subagent to check the auth module"
claude -p "have the debugger subagent investigate this error"

Management Interface

# Interactive subagent management
/agents

# Create new subagents
/agents # Select "Create New Agent"

Example Subagent Types

Development Specialists

  • code-reviewer: Quality, security, maintainability
  • debugger: Error diagnosis and resolution
  • test-runner: Automated testing and failure fixes
  • performance-auditor: Optimization analysis

Domain Experts

  • rust-expert: Ownership, lifetimes, systems programming
  • python-expert: Modern Python, libraries, architecture
  • data-scientist: SQL, BigQuery, data analysis

Workflow Automation

  • git-helper: Version control operations
  • deployment-manager: CI/CD and infrastructure
  • documentation-writer: API docs and guides

Hooks & Automation

Hook Event Types

EventTimingUse Cases
PreToolUseBefore tool executionValidation, blocking, logging
PostToolUseAfter tool completionFormatting, notifications, cleanup
UserPromptSubmitUser input receivedPreprocessing, context injection
NotificationClaude needs attentionCustom notifications
StopResponse completedFinal processing, reporting
SessionStart/EndSession lifecycleSetup, teardown, logging

Hook Implementation Patterns

Code Formatting

{
"hooks": {
"PostToolUse": [{
"matcher": "Edit|MultiEdit|Write",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read file; if echo \"$file\" | grep -q '\\.py$'; then black \"$file\"; fi; }"
}]
}]
}
}

Security Validation

{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/hooks/validate_command.py"
}]
}]
}
}

Custom Notifications

{
"hooks": {
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "osascript -e 'display notification \"Claude awaits input\" with title \"Claude Code\"'"
}]
}]
}
}

Advanced Hook Scripts

Python Hook Example

#!/usr/bin/env python3
import json
import sys
import os

def validate_bash_command():
"""Validate bash commands for safety"""
try:
data = json.load(sys.stdin)
command = data.get('tool_input', {}).get('command', '')

# Block dangerous commands
dangerous = ['rm -rf', 'sudo', 'chmod 777', 'curl | bash']
if any(danger in command for danger in dangerous):
print(f"BLOCKED: Dangerous command detected: {command}")
sys.exit(2) # Exit code 2 blocks execution

# Log all commands
with open(os.path.expanduser('~/.claude/command_log.txt'), 'a') as f:
f.write(f"{command}\n")

except Exception as e:
print(f"Hook error: {e}")
sys.exit(1)

if __name__ == "__main__":
validate_bash_command()

SDK Integration Patterns

SDK Modes

Headless Mode (CLI Scripts)

# Single query with structured output
result=$(claude -p "analyze this error" --output-format json)

# Pipe integration
cat logs.txt | claude -p "find errors" | jq '.messages[-1].content'

# Automation scripts
claude -p "run tests and commit if passing" --max-turns 10

Streaming Mode (Interactive Applications)

TypeScript SDK

import { Claude } from '@anthropic-ai/claude-code';

const claude = new Claude({
apiKey: process.env.ANTHROPIC_API_KEY,
workingDirectory: process.cwd()
});

// Streaming conversation
const stream = claude.query("Analyze this codebase for performance issues");
for await (const message of stream) {
if (message.type === 'assistant') {
console.log(message.content);
}
if (message.usage) {
console.log(`Tokens used: ${message.usage.input_tokens}`);
}
}

Python SDK

import anthropic_claude_code as claude

client = claude.Claude(
api_key=os.environ['ANTHROPIC_API_KEY'],
working_directory=os.getcwd()
)

# Async streaming
async for message in client.query("Optimize database queries"):
if message.type == 'assistant':
print(message.content)
if hasattr(message, 'usage'):
track_usage(message.usage)

Cost Tracking Implementation

// Message-level usage tracking
const usageTracker = new Map<string, Usage>();

for await (const message of stream) {
if (message.type === 'assistant' && message.usage) {
// Only count once per unique message ID
if (!usageTracker.has(message.id)) {
usageTracker.set(message.id, message.usage);
updateBilling(message.usage);
}
}
}

Session Management

# Resume sessions programmatically
session_id = await client.start_session()

# Process with interruption handling
try:
async for message in client.query("Long running task", session_id=session_id):
if should_interrupt():
await client.interrupt(session_id)
break
finally:
await client.save_session(session_id)

Production Deployment

CI/CD Integration

GitHub Actions Example

name: AI Code Review
on: [pull_request]

jobs:
ai-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: AI Code Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "Review this PR for security issues and code quality.
Focus on the changed files and provide specific recommendations." \
--output-format json > review.json
- name: Post Review
run: |
jq -r '.messages[-1].content' review.json > review.md
gh pr comment --body-file review.md

Docker Integration

FROM node:18-alpine

# Install Claude Code
RUN npm install -g @anthropic-ai/claude-code

# Copy MCP configurations
COPY .mcp.json /app/.mcp.json
COPY .claude/ /app/.claude/

WORKDIR /app

# Authentication via environment variables
ENV ANTHROPIC_API_KEY=""
ENV CLAUDE_CODE_USE_BEDROCK=1

# Disable interactive features for automation
ENV DISABLE_TELEMETRY=1
ENV DISABLE_AUTOUPDATER=1

CMD ["claude", "-p", "analyze this codebase", "--output-format", "json"]

Kubernetes Deployment

apiVersion: batch/v1
kind: CronJob
metadata:
name: code-analysis
spec:
schedule: "0 2 * * *" # Daily at 2 AM
jobTemplate:
spec:
template:
spec:
containers:
- name: claude-analyzer
image: your-repo/claude-code:latest
env:
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
name: claude-secrets
key: api-key
command:
- /bin/sh
- -c
- |
claude -p "Analyze codebase for technical debt and security issues.
Generate daily report with priorities." \
--output-format json > /reports/daily-$(date +%Y%m%d).json
volumeMounts:
- name: reports
mountPath: /reports
volumes:
- name: reports
persistentVolumeClaim:
claimName: analysis-reports
restartPolicy: OnFailure

Monitoring & Observability

# Enable comprehensive logging
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317

# Custom status line for monitoring
echo '#!/bin/bash
echo "Session: $CLAUDE_SESSION_ID | Model: $CLAUDE_MODEL | Tokens: $CLAUDE_USAGE_TOKENS"
' > ~/.claude/status.sh

Security & Best Practices

Permission Security Model

Principle of Least Privilege

{
"permissions": {
"allow": [
"Read(./src/**)",
"Edit(./src/**)",
"Bash(npm run test)",
"Bash(git diff:*)"
],
"deny": [
"Read(./.env*)",
"Read(./secrets/**)",
"Bash(curl:*)",
"Bash(wget:*)",
"WebFetch",
"Write(./package.json)"
]
}
}

Enterprise Security Policies

// /etc/claude-code/managed-settings.json
{
"permissions": {
"deny": [
"WebFetch",
"Bash(rm:*)",
"Bash(sudo:*)",
"Read(/etc/**)",
"Write(/var/**)"
],
"disableBypassPermissionsMode": "disable"
},
"forceLoginMethod": "console",
"forceLoginOrgUUID": "org-uuid-here"
}

Sensitive Data Protection

File Exclusion Patterns

{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(./config/credentials.*)",
"Read(./**/*key*)",
"Read(./**/*secret*)",
"Read(./**/*token*)"
]
}
}

Git Integration Security

# Prevent accidental commits of sensitive data
echo ".claude/settings.local.json" >> .gitignore
echo "*.log" >> .gitignore
echo ".env*" >> .gitignore

Hook Security

Safe Hook Implementation

#!/usr/bin/env python3
import json
import sys
import subprocess
import shlex

def secure_hook():
"""Secure hook implementation with input validation"""
try:
# Parse input safely
data = json.load(sys.stdin)

# Validate input structure
if 'tool_input' not in data:
sys.exit(0)

# Sanitize file paths
file_path = data['tool_input'].get('file_path', '')
if not file_path or '..' in file_path or file_path.startswith('/'):
print("Invalid file path")
sys.exit(1)

# Use safe command execution
cmd = ['prettier', '--write', file_path]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)

if result.returncode != 0:
print(f"Formatting failed: {result.stderr}")
sys.exit(1)

except Exception as e:
print(f"Hook error: {e}")
sys.exit(1)

if __name__ == "__main__":
secure_hook()

MCP Security

Server Validation

# Review MCP servers before installation
claude mcp get server-name

# Use project-scoped servers for team review
claude mcp add server --scope project

# Enable specific servers only
{
"enabledMcpjsonServers": ["approved-server-1", "approved-server-2"],
"disabledMcpjsonServers": ["untrusted-server"]
}

Audit & Compliance

Command Logging

{
"hooks": {
"PreToolUse": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/audit_logger.py"
}]
}]
}
}

Audit Logger Implementation

#!/usr/bin/env python3
import json
import sys
import datetime
import os

def audit_log():
"""Log all tool usage for compliance"""
try:
data = json.load(sys.stdin)

log_entry = {
"timestamp": datetime.datetime.utcnow().isoformat(),
"tool": data.get("tool_name"),
"input": data.get("tool_input", {}),
"user": os.environ.get("USER"),
"session": os.environ.get("CLAUDE_SESSION_ID")
}

with open("/var/log/claude-audit.log", "a") as f:
f.write(json.dumps(log_entry) + "\n")

except Exception as e:
print(f"Audit logging failed: {e}")
# Don't block execution for logging failures

if __name__ == "__main__":
audit_log()

Network Security

{
"env": {
"HTTP_PROXY": "http://proxy.company.com:8080",
"HTTPS_PROXY": "http://proxy.company.com:8080",
"NO_PROXY": "localhost,127.0.0.1,*.company.com"
},
"permissions": {
"deny": ["WebFetch", "WebSearch"]
}
}

Advanced Patterns & Best Practices

Multi-Agent Orchestration

# Chain specialized agents
claude -p "First use the code-analyzer to identify performance issues,
then use the optimizer to fix them,
finally use the test-runner to verify improvements"

Workflow Automation

# Git workflow integration
claude commit # Smart commit message generation

# Unix pipeline integration
find . -name "*.py" -exec claude -p "check {} for security issues" \;

# Continuous monitoring
tail -f application.log | claude -p "alert me to any anomalies"

Context Management

<!-- .claude/CLAUDE.md -->
# Project Context

This is a TypeScript/React project with:
- Authentication via JWT tokens
- PostgreSQL database with Prisma ORM
- Microservices architecture on AWS
- Jest for testing, ESLint for linting

## Coding Standards
- Use functional components with hooks
- Implement proper TypeScript types
- Follow security best practices for auth
- Write comprehensive tests for business logic

## Architecture Decisions
- API routes in /api directory
- Database models in /prisma/schema.prisma
- Custom hooks in /hooks directory
- Shared components in /components directory

This primer provides a comprehensive foundation for building production-grade CLI agents with Claude Code. The modular architecture, extensive tool system, and robust security model make it suitable for everything from personal development workflows to enterprise-scale automation systems.