Advanced System Prompt Augmentation Patterns for Claude Code

Overview

This guide explores advanced scenarios and patterns for appending to system prompts in Claude Code, covering dynamic context injection, runtime prompt modification, and sophisticated prompt engineering techniques. These patterns enable Claude Code to adapt its behavior based on project context, runtime conditions, and complex multi-stage workflows.

Core Concepts

System Prompt Architecture

Claude Code’s system prompt architecture consists of multiple layers:

  1. Base System Prompt - Core instructions from Claude
  2. Global User Context - ~/.claude/CLAUDE.md
  3. Project Context - ./CLAUDE.md and hierarchical imports
  4. Runtime Augmentation - Dynamic additions via CLI, hooks, and tools
  5. Event-Driven Context - Hook-based prompt modifications

Context Injection Methods

graph TD
    A[Base System Prompt] --> B[CLAUDE.md Files]
    B --> C[Import Directives]
    C --> D[Hook Injections]
    D --> E[Runtime Arguments]
    E --> F[Tool-Based Context]
    F --> G[Final Augmented Prompt]

Pattern Library

1. Hierarchical Context Composition

Pattern: Layer context from global to specific using CLAUDE.md hierarchy

# ~/.claude/CLAUDE.md (Global)
- Always use TypeScript
- Prefer functional programming
- Use Bun for scripts
 
# ./CLAUDE.md (Project)
@~/.claude/CLAUDE.md
- Project: E-commerce Platform
- Framework: Next.js 14
- Database: PostgreSQL
 
# ./apps/web/CLAUDE.md (Module)
@../../CLAUDE.md
- Component library: Radix UI
- State management: Zustand
- Styling: Tailwind CSS

Benefits:

  • Consistent global preferences
  • Project-specific overrides
  • Module-level specialization
  • DRY principle for configuration

2. Dynamic Import Patterns

Pattern: Conditionally load context based on file patterns or project state

# Advanced Import Syntax
@./docs/setup.md                     # Always loaded
@./docs/api/*.md                     # Glob pattern support
@{./config/dev.md,./config/prod.md} # Multiple file options
 
# Conditional Loading (Conceptual)
@./docs/testing.md #test
@./docs/performance.md #prod
@./docs/debugging.md #dev
 
# Feature-Based Loading
@./features/*/README.md              # All feature docs
@./features/payment/api.md #payment  # Specific feature context

3. Hook-Based Runtime Injection

Pattern: Use hooks to dynamically modify prompts based on events

{
  "hooks": {
    "UserPromptSubmit": [{
      "matcher": "^(test|spec)",
      "hooks": [{
        "type": "command",
        "command": "./hooks/inject-test-context.sh"
      }]
    }],
    "PreToolUse": [{
      "matcher": ".*",
      "hooks": [{
        "type": "command",
        "command": "./hooks/add-tool-context.sh"
      }]
    }]
  }
}

Hook Script Example:

#!/bin/bash
# inject-test-context.sh
 
# Detect test framework
if [ -f "jest.config.js" ]; then
  echo "CONTEXT: Using Jest for testing"
  echo "- Run tests with: npm test"
  echo "- Coverage with: npm run test:coverage"
  echo "- Watch mode: npm run test:watch"
elif [ -f "vitest.config.ts" ]; then
  echo "CONTEXT: Using Vitest for testing"
  echo "- Run tests with: vitest"
  echo "- UI mode: vitest --ui"
fi

4. CLI-Based Prompt Augmentation

Pattern: Append to system prompt via command-line arguments

# Basic augmentation
claude --append-system-prompt "Focus on performance optimization"
 
# File-based augmentation
claude --append-system-prompt @./prompts/security-audit.md
 
# Multi-stage augmentation
claude --append-system-prompt "Project: API Migration" \
       --append-system-prompt @./migration/context.md \
       --append-system-prompt "Priority: Database schema updates"

5. Self-Improving Prompt Systems

Pattern: Automatically evolve prompts based on performance

# .claude/hooks/capture-intent.sh
#!/bin/bash
echo "$1" >> .claude/logs/intents.log
 
# .claude/hooks/analyze-performance.sh
#!/bin/bash
# Analyze tool usage patterns
grep "Tool:" .claude/logs/session.log | sort | uniq -c > .claude/metrics/tool-usage.txt
 
# Generate optimized context
if grep -q "grep.*100+" .claude/metrics/tool-usage.txt; then
  echo "OPTIMIZATION: Use ripgrep (rg) for better performance" >> .claude/context/learned.md
fi
 
# .claude/hooks/apply-learnings.sh
#!/bin/bash
if [ -f .claude/context/learned.md ]; then
  cat .claude/context/learned.md
fi

6. GitHub Actions Context Injection

Pattern: Dynamically construct prompts with GitHub event data

- name: Create Dynamic Prompt
  run: |
    cat > /tmp/prompt.txt << 'EOF'
    You are reviewing PR #${{ github.event.pull_request.number }}
    
    Repository: ${{ github.repository }}
    Branch: ${{ github.head_ref }} -> ${{ github.base_ref }}
    Author: ${{ github.event.pull_request.user.login }}
    
    Files changed: ${{ github.event.pull_request.changed_files }}
    
    Use these MCP tools to gather context:
    - mcp__github__get_pull_request_files
    - mcp__github__get_pull_request_diff
    - mcp__github__list_pull_request_comments
    
    Focus on:
    1. Security vulnerabilities
    2. Performance regressions
    3. Breaking changes
    EOF
    
- name: Run Claude with Dynamic Context
  run: |
    claude --no-interactive \
           --mcp-server github=mcp-server-github \
           --append-system-prompt @/tmp/prompt.txt \
           -p "Review this pull request"

7. Multi-Stage Prompt Chaining

Pattern: Build complex prompts through sequential augmentation

// claude-orchestrator.ts
import { ClaudeSDK } from '@anthropic/claude-code-sdk';
 
async function multiStageAnalysis(projectPath: string) {
  const claude = new ClaudeSDK();
  
  // Stage 1: Project Analysis
  const projectContext = await claude.run({
    prompt: "Analyze project structure and identify key components",
    appendSystemPrompt: `Project root: ${projectPath}`
  });
  
  // Stage 2: Dependency Analysis
  const depContext = await claude.run({
    prompt: "Analyze dependencies and security vulnerabilities",
    appendSystemPrompt: [
      projectContext.summary,
      "Focus on: outdated packages, security advisories"
    ].join('\n')
  });
  
  // Stage 3: Performance Audit
  const perfContext = await claude.run({
    prompt: "Conduct performance audit",
    appendSystemPrompt: [
      projectContext.summary,
      depContext.findings,
      "Metrics: bundle size, runtime performance, memory usage"
    ].join('\n')
  });
  
  return { projectContext, depContext, perfContext };
}

8. Context Window Optimization

Pattern: Dynamically manage context to stay within limits

# Performance-Optimized CLAUDE.md
# Context Budget Management
MAX_CONTEXT_TOKENS: 50000
PRIORITY_LEVELS:
  - CRITICAL: Security, core architecture
  - HIGH: Current feature context
  - MEDIUM: Related features
  - LOW: Historical decisions
 
# Smart Loading
@./docs/critical/*.md                    # Always load
@./docs/current-sprint.md                # Current context
@./docs/archive/*.md #if-tokens-available # Load if space
 
# Compression Strategies
- Use bullet points over paragraphs
- Reference external docs by URL
- Summarize instead of quoting
- Use code signatures over full implementations

9. Role-Based Context Switching

Pattern: Adapt system prompt based on current role/task

#!/bin/bash
# role-switcher.sh
 
case "$1" in
  "architect")
    cat << EOF
You are a senior software architect focused on:
- System design and scalability
- Technology selection
- Performance optimization
- Security architecture
EOF
    ;;
  "reviewer")
    cat << EOF
You are a thorough code reviewer checking for:
- Logic errors and edge cases
- Security vulnerabilities
- Performance issues
- Code style compliance
EOF
    ;;
  "debugger")
    cat << EOF
You are a debugging specialist who:
- Analyzes error messages systematically
- Uses scientific method for hypothesis testing
- Documents reproduction steps
- Suggests multiple solution approaches
EOF
    ;;
esac

10. Project State Detection

Pattern: Automatically detect and adapt to project state

// detect-project-state.ts
import { glob } from 'glob';
import fs from 'fs/promises';
 
async function detectProjectState() {
  const contexts = [];
  
  // Framework detection
  if (await fs.access('next.config.js').catch(() => false)) {
    contexts.push('@./contexts/nextjs.md');
  }
  
  // Test framework detection
  if (await fs.access('jest.config.js').catch(() => false)) {
    contexts.push('@./contexts/jest-testing.md');
  }
  
  // CI/CD detection
  if (await fs.access('.github/workflows').catch(() => false)) {
    contexts.push('@./contexts/github-actions.md');
  }
  
  // Database detection
  if (await fs.access('prisma/schema.prisma').catch(() => false)) {
    contexts.push('@./contexts/prisma-db.md');
  }
  
  return contexts;
}
 
// Write dynamic CLAUDE.md
const contexts = await detectProjectState();
await fs.writeFile('.claude/dynamic-context.md', contexts.join('\n'));

Practical Use-Cases: Matching Patterns to Problems

The patterns above are powerful but can be abstract. Use this section to identify which pattern to apply to common development challenges.

If you need to…Then use this pattern…Why?
Ensure consistent coding standards across all projectsIt allows you to set global standards in ~/.claude/CLAUDE.md that are inherited by all projects, ensuring consistency.
Provide special instructions when writing testsA UserPromptSubmit hook can detect when you’re asking to create a test (e.g., claude -p "write a test for...") and automatically inject context about the project’s testing framework.
Perform a one-time security auditUsing --append-system-prompt @./prompts/security-audit.md is perfect for temporary, high-priority contexts without modifying project files.
Review a GitHub Pull RequestThis is the most robust way to provide Claude with the full context of a PR, including changed files, author, and branch, directly within your CI/CD pipeline.
Switch between being a “debugger” and a “code reviewer”A simple shell script can load different “persona” prompts, fundamentally changing Claude’s behavior to suit the task at hand.
Automatically provide context about the project’s framework (e.g., React, Next.js)A script can detect key files like next.config.js or jest.config.ts and dynamically load the appropriate context files, making the AI “framework-aware”.

Advanced Implementation Examples

Example 1: Intelligent Code Review System

# .github/workflows/ai-code-review.yml
name: AI Code Review
on:
  pull_request:
    types: [opened, synchronize]
 
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - name: Generate Review Context
        run: |
          # Analyze PR characteristics
          CHANGED_FILES=${{ github.event.pull_request.changed_files }}
          
          # Build dynamic prompt based on changes
          if [[ $CHANGED_FILES -gt 50 ]]; then
            echo "CONTEXT: Large PR - focus on architecture" > /tmp/context.txt
          elif [[ "${{ github.event.pull_request.title }}" =~ "security" ]]; then
            echo "CONTEXT: Security-focused review required" > /tmp/context.txt
          else
            echo "CONTEXT: Standard code review" > /tmp/context.txt
          fi
          
          # Add file-specific contexts
          for file in ${{ steps.files.outputs.all }}; do
            case "$file" in
              *.sql) echo "@./contexts/database-review.md" >> /tmp/context.txt ;;
              *.tsx) echo "@./contexts/react-review.md" >> /tmp/context.txt ;;
              *.py)  echo "@./contexts/python-review.md" >> /tmp/context.txt ;;
            esac
          done
      
      - name: Run Claude Review
        run: |
          claude --no-interactive \
                 --append-system-prompt @/tmp/context.txt \
                 -p "Review PR #${{ github.event.pull_request.number }}"

Example 2: Adaptive Documentation Generator

// adaptive-docs.ts
import { ClaudeSDK } from '@anthropic/claude-code-sdk';
 
class AdaptiveDocumentationGenerator {
  private claude: ClaudeSDK;
  private contextHistory: string[] = [];
  
  async generateDocs(componentPath: string) {
    // Detect component type
    const componentType = await this.detectComponentType(componentPath);
    
    // Build layered context
    const contexts = [
      // Base documentation style
      '@./docs/style-guide.md',
      
      // Component-specific context
      this.getComponentContext(componentType),
      
      // Historical context from similar components
      ...this.findSimilarComponentDocs(componentPath),
      
      // Project-specific patterns
      '@./docs/component-patterns.md'
    ];
    
    // Dynamic prompt construction
    const prompt = this.buildAdaptivePrompt({
      componentPath,
      componentType,
      contexts,
      previousAttempts: this.contextHistory
    });
    
    return await this.claude.run({
      prompt: `Generate comprehensive documentation for ${componentPath}`,
      appendSystemPrompt: prompt
    });
  }
  
  private buildAdaptivePrompt(config: any): string {
    return `
You are generating documentation for a ${config.componentType} component.
 
Previous documentation attempts have shown these patterns:
${config.previousAttempts.slice(-3).join('\n')}
 
Apply these contexts:
${config.contexts.join('\n')}
 
Adapt your documentation style based on:
1. Component complexity (simple: concise, complex: detailed)
2. Public vs internal API (public: extensive examples)
3. Testing requirements (critical: include test examples)
    `.trim();
  }
}

Performance Considerations

Token Usage Optimization

# Token-Efficient Patterns
1. Use references instead of full content
   - Bad: Include entire file content
   - Good: "See auth implementation in /src/auth/handler.ts"
 
2. Compress repeated information
   - Bad: List each endpoint with full details
   - Good: "All endpoints follow RESTful pattern with JWT auth"
 
3. Use structured formats
   - Bad: Paragraph descriptions
   - Good: Bullet points, tables, lists

Context Window Management

// context-manager.ts
class ContextWindowManager {
  private maxTokens = 50000;
  private currentTokens = 0;
  
  async addContext(context: string, priority: number) {
    const tokens = this.estimateTokens(context);
    
    if (this.currentTokens + tokens > this.maxTokens) {
      // Remove lowest priority contexts
      await this.evictLowPriorityContexts(tokens);
    }
    
    this.contexts.push({ context, priority, tokens });
    this.currentTokens += tokens;
  }
  
  private async evictLowPriorityContexts(neededTokens: number) {
    const sorted = this.contexts.sort((a, b) => a.priority - b.priority);
    
    while (this.currentTokens + neededTokens > this.maxTokens) {
      const removed = sorted.shift();
      this.currentTokens -= removed.tokens;
    }
  }
}

Security Considerations

Prompt Injection Prevention

// secure-prompt-builder.ts
class SecurePromptBuilder {
  private readonly forbiddenPatterns = [
    /ignore previous instructions/i,
    /disregard safety/i,
    /unlimited access/i,
    /sudo/i,
    /bypass restrictions/i
  ];
  
  private readonly requiredSections = [
    'safety_instructions',
    'scope_limitations',
    'output_constraints'
  ];
  
  validatePrompt(prompt: string): boolean {
    // Check for forbidden patterns
    for (const pattern of this.forbiddenPatterns) {
      if (pattern.test(prompt)) {
        throw new Error(`Forbidden pattern detected: ${pattern}`);
      }
    }
    
    // Ensure required sections present
    for (const section of this.requiredSections) {
      if (!prompt.includes(section)) {
        throw new Error(`Missing required section: ${section}`);
      }
    }
    
    return true;
  }
  
  sanitizeUserInput(input: string): string {
    return input
      .replace(/[<>]/g, '') // Remove potential XML injection
      .replace(/\\/g, '\\\\') // Escape backslashes
      .substring(0, 10000); // Limit length
  }
}

Best Practices

1. Layered Context Architecture

  • Start with broad context, narrow to specifics
  • Use hierarchical imports for maintainability
  • Keep global preferences minimal

2. Dynamic Context Guidelines

  • Detect project state programmatically
  • Cache detection results for performance
  • Provide fallbacks for missing contexts

3. Performance Optimization

  • Monitor token usage continuously
  • Implement context eviction strategies
  • Use compression techniques

4. Security First

  • Validate all dynamic inputs
  • Prevent prompt injection attacks
  • Limit scope of injected contexts

5. Testing Strategies

  • Test each context layer independently
  • Verify prompt composition logic
  • Monitor for context conflicts

Troubleshooting

Common Issues and Solutions

# Issue: Context overflow
Solution: Implement token counting and priority-based eviction
 
# Issue: Conflicting instructions
Solution: Use explicit priority ordering in CLAUDE.md
 
# Issue: Slow prompt loading
Solution: Cache compiled contexts, use lazy loading
 
# Issue: Missing context at runtime
Solution: Implement fallback mechanisms and validation

Future Directions

Emerging Patterns

  1. AI-Driven Context Selection - Let Claude choose relevant contexts
  2. Predictive Context Loading - Pre-load based on usage patterns
  3. Distributed Context Systems - Share contexts across team/org
  4. Context Version Control - Track and rollback context changes

Resources