Files
ruvnet--ruflo/v3/implementation/adrs/ADR-019-headless-runtime-package.md
wehub-resource-sync 23f7624596
ADR-166 MCP Bridge Security Lock / Static-source security lock (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / Compose default binds loopback + Mongo has auth (push) Failing after 2s
CodeQL Advanced / Analyze (rust) (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / plugin-agent-federation bindHost default (push) Failing after 1s
ADR-166 MCP Bridge Security Lock / Runtime behavior — 401 + terminal gate + fail-closed (push) Failing after 4s
business-pods-smoke / smoke (push) Failing after 1s
all-plugins-smoke / smoke-all (push) Failing after 2s
CI/CD Pipeline / Security & Code Quality (push) Failing after 1s
CI/CD Pipeline / Test Suite (ubuntu-latest) (push) Failing after 1s
CI/CD Pipeline / Build & Package (macos-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (ubuntu-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (windows-latest) (push) Has been skipped
CI/CD Pipeline / Documentation & Examples (push) Failing after 1s
Clone Tracker (14-day rolling) / Snapshot clones for ruflo ecosystem (push) Failing after 1s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
federation-peer-rust / stable-noop (push) Failing after 1s
metaharness-ci / score (push) Failing after 1s
metaharness-ci / router-compat (push) Failing after 0s
metaharness-ci / similarity-tests (push) Failing after 0s
no-agentbbs-smoke / smoke-without-agentbbs (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (windows-latest) (push) Has been skipped
codex-integration-audit / Codex integration audit (push) Failing after 1s
helpers-manifest-guard / guard (push) Failing after 1s
🔗 Cross-Agent Integration Tests / 🤝 Agent Coordination Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🧠 Memory Sharing Integration (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🛡️ Fault Tolerance Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / ⚡ Performance Integration Tests (push) Has been skipped
metaharness-ci / mcp-scan (push) Failing after 1s
metaharness-ci / eject-dryrun (push) Failing after 1s
metaharness-ci / metaharness-real-data (push) Failing after 0s
no-cli-optdep-bloat-2561 / guard (push) Failing after 1s
no-metaharness-smoke / smoke-without-metaharness (push) Failing after 1s
no-phantom-agentic-flow-subpath / guard (push) Failing after 1s
🔄 Automated Rollback Manager / 🚨 Failure Detection (push) Failing after 1s
V3 CI/CD Pipeline / Plugin hooks smoke / ubuntu-latest / Node 22 (push) Failing after 1s
V3 CI/CD Pipeline / ruflo-graph-intelligence build + test smoke (#2044, ADR-123) (push) Failing after 1s
CVE Audit Gate / Audit root (critical-blocking) (push) Failing after 2s
cost-tracker-smoke / smoke (push) Failing after 3s
oia-audit-weekly / audit (push) Failing after 2s
ruflo-agent-smoke / ruflo-agent structural smoke (push) Failing after 1s
📊 Status Badges Update / 📊 Update Status Badges (push) Failing after 1s
V3 CI/CD Pipeline / Static regression guards (#2267 YAML + (push) Failing after 1s
V3 CI/CD Pipeline / Test V3 Packages (push) Failing after 0s
V3 CI/CD Pipeline / agent_execute provider routing smoke (#2042) (push) Failing after 0s
CVE Audit Gate / Audit v3 (critical-blocking) (push) Failing after 1s
federation-peer-rust / stable-native (push) Failing after 2s
🔗 Cross-Agent Integration Tests / 🚀 Integration Test Setup (push) Failing after 2s
neural-trader-smoke / runtime-smoke (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (macos-latest) (push) Has been skipped
V3 CI/CD Pipeline / Build V3 (ubuntu-latest) (push) Has been skipped
V3 CI/CD Pipeline / Type Check V3 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 24 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 22 (push) Failing after 2s
V3 CI/CD Pipeline / browser rvf create flag smoke (#2015) (push) Failing after 0s
V3 CI/CD Pipeline / Dependency review (#2046) (push) Has been skipped
V3 CI/CD Pipeline / Supply-chain audit (#2046) (push) Failing after 0s
V3 CI/CD Pipeline / witness marker drift smoke (#2021) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader backtest signing smoke (#2068, ADR-126 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / kg-extract type-import classification smoke (#2049) (push) Failing after 0s
V3 CI/CD Pipeline / witness verify precondition smoke (#1880) (push) Failing after 2s
V3 CI/CD Pipeline / neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5) (push) Failing after 0s
V3 CI/CD Pipeline / neural-trader feature attribution smoke (#2068, ADR-126 Phase 6) (push) Failing after 0s
V3 CI/CD Pipeline / plugin-registry signature verification smoke (#1922, CWE-347) (push) Failing after 4s
V3 CI/CD Pipeline / memory stats legacy-DB smoke (#2120) (push) Failing after 4s
V3 CI/CD Pipeline / github deprecated actions smoke (#2089, ADR-127 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / graph query + pathfinder smoke (ADR-130 P2+P5) (push) Has been skipped
V3 CI/CD Pipeline / graph trajectory hooks smoke (ADR-130 P3) (push) Has been skipped
V3 CI/CD Pipeline / graph plugin adapter smoke (ADR-130 P4) (push) Has been skipped
V3 CI/CD Pipeline / graph benchmark (ADR-130 P6) (push) Has been skipped
V3 CI/CD Pipeline / statusline generator delegation smoke (#2195) (push) Failing after 1s
V3 CI/CD Pipeline / wizard init regression guard (#2206 (push) Failing after 1s
V3 CI/CD Pipeline / memory no-stray-db smoke (ADR-125 P7) (push) Failing after 1s
V3 CI/CD Pipeline / github-safe injection smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github actions pin smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github attribution opt-in smoke (#2089, ADR-127 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / pre-bash hook safety smoke (#2017) (push) Failing after 1s
V3 CI/CD Pipeline / Memory import smoke / ubuntu-latest (push) Failing after 0s
V3 CI/CD Pipeline / MCP protocol smoke / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / ruvllm WASM auto-init smoke (#2086) (push) Failing after 4s
V3 CI/CD Pipeline / MCP paired-tool round-trip smoke (#1889) (push) Failing after 1s
V3 CI/CD Pipeline / Plugin package install-safety (#1902/#1903/#1904) (push) Failing after 1s
V3 CI/CD Pipeline / Tool description discoverability (ADR-112) (push) Failing after 3s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (22) (push) Failing after 1s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (24) (push) Failing after 1s
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Vector-index dimension audit (#1947) (push) Failing after 0s
V3 CI/CD Pipeline / Hook-command install safety (#1921) (push) Failing after 1s
V3 CI/CD Pipeline / ToolOutputGuardrail smoke (ADR-131, (push) Failing after 1s
V3 CI/CD Pipeline / init-bundle invariants smoke (#2095, ADR-128 Phase 5) (push) Failing after 1s
V3 CI/CD Pipeline / wasm provider bridge smoke (ADR-129 P1) (push) Failing after 2s
V3 CI/CD Pipeline / wasm gallery CRUD smoke (ADR-129 P3) (push) Failing after 1s
V3 CI/CD Pipeline / wasm plugin bridge smoke (ADR-129 P4) (push) Failing after 0s
V3 CI/CD Pipeline / wasm compose smoke (ADR-129 P2) (push) Failing after 4s
V3 CI/CD Pipeline / graph schema smoke (ADR-130 P1) (push) Failing after 0s
Validate Marketplace / validate (push) Failing after 1s
🔍 Verification Pipeline / 🚀 Setup Verification (push) Failing after 1s
🔍 Verification Pipeline / 🛡️ Security Verification (push) Has been skipped
🔍 Verification Pipeline / 📝 Code Quality (push) Has been skipped
🔍 Verification Pipeline / 🧪 Test Verification (${{ matrix.os }}, Node ${{ matrix.node }}) (push) Has been skipped
🔍 Verification Pipeline / 🏗️ Build Verification (push) Has been skipped
🔍 Verification Pipeline / 📚 Documentation Verification (push) Has been skipped
CVE Audit Gate / High-severity report (warn only) (push) Has been cancelled
🔄 Automated Rollback Manager / 🔄 Execute Rollback (push) Has been cancelled
🔄 Automated Rollback Manager / ✅ Post-Rollback Verification (push) Has been cancelled
🔄 Automated Rollback Manager / 📊 Rollback Monitoring (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / windows-latest (push) Has been cancelled
🔄 Automated Rollback Manager / ⏳ Manual Rollback Approval (push) Has been cancelled
V3 CI/CD Pipeline / MCP protocol smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Memory import smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / ubuntu-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Publish to npm (alpha) (push) Has been cancelled
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / macos-latest / Node 22 (push) Has been cancelled
V3 CI/CD Pipeline / Plugin hooks smoke / macos-latest / Node 22 (push) Has been cancelled
CI/CD Pipeline / Deploy & Release (push) Has been cancelled
CI/CD Pipeline / CI Status (push) Has been cancelled
🔗 Cross-Agent Integration Tests / 📊 Integration Test Report (push) Has been cancelled
🔄 Automated Rollback Manager / 🔍 Pre-Rollback Validation (push) Has been cancelled
🔍 Verification Pipeline / ⚡ Performance Verification (push) Has been cancelled
🔍 Verification Pipeline / 📊 Verification Report (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:02:19 +08:00

20 KiB

ADR-019: @claude-flow/headless Runtime Package

Status: Proposed Date: 2026-01-07 Author: System Architecture Designer Version: 1.0.0

Context

The undocumented CLAUDE_CODE_HEADLESS and CLAUDE_CODE_SANDBOX_MODE environment variables in Claude Code enable programmatic, non-interactive execution. This creates opportunities for:

  1. CI/CD Integration - Automated code review, generation, and testing
  2. Batch Processing - Queue-based task execution without user interaction
  3. Distributed Agents - Remote Claude Code instances in swarm topology
  4. API Gateway - REST/WebSocket interface to Claude Code capabilities
  5. Container Orchestration - Docker/K8s-native Claude Code execution

Decision

Create @claude-flow/headless package providing:

  • Programmatic Claude Code invocation with environment control
  • Sandbox-aware execution contexts
  • Batch task queue with persistence
  • HTTP/WebSocket API server
  • Docker-native execution support

Package Architecture

@claude-flow/headless/
├── src/
│   ├── index.ts                 # Main exports
│   ├── executor/
│   │   ├── headless-executor.ts # Core execution engine
│   │   ├── sandbox-manager.ts   # Sandbox mode control
│   │   ├── process-pool.ts      # Process pooling
│   │   └── timeout-controller.ts # Execution timeouts
│   ├── queue/
│   │   ├── task-queue.ts        # Persistent task queue
│   │   ├── priority-scheduler.ts # Priority-based scheduling
│   │   └── dead-letter.ts       # Failed task handling
│   ├── api/
│   │   ├── server.ts            # HTTP/WS API server
│   │   ├── routes.ts            # REST endpoints
│   │   └── websocket.ts         # Real-time streaming
│   ├── docker/
│   │   ├── container-executor.ts # Docker execution
│   │   ├── image-manager.ts     # Image lifecycle
│   │   └── volume-manager.ts    # Workspace volumes
│   ├── monitoring/
│   │   ├── metrics.ts           # Prometheus metrics
│   │   ├── health.ts            # Health checks
│   │   └── logging.ts           # Structured logging
│   └── types.ts                 # TypeScript definitions
├── Dockerfile                   # Container image
├── docker-compose.yml           # Development stack
└── package.json

Core Interfaces

1. Headless Executor

// src/executor/headless-executor.ts

export interface HeadlessConfig {
  // Claude Code path (auto-detected if not provided)
  claudeCodePath?: string;

  // Sandbox configuration
  sandbox: {
    mode: 'strict' | 'permissive' | 'disabled' | 'auto';
    allowedPaths?: string[];
    deniedPaths?: string[];
    networkPolicy?: 'allow' | 'deny' | 'local-only';
  };

  // Execution limits
  limits: {
    maxConcurrent: number;      // Max parallel executions
    timeoutMs: number;          // Default timeout (max 10min)
    maxOutputSize: number;      // Max output bytes
    maxContextTokens?: number;  // Token limit
  };

  // Model configuration
  model?: 'sonnet' | 'opus' | 'haiku';

  // API key (falls back to ANTHROPIC_API_KEY)
  apiKey?: string;
}

export interface ExecutionRequest {
  id: string;
  prompt: string;
  workingDirectory?: string;

  // Optional context files to include
  contextFiles?: string[];

  // Environment variables for this execution
  env?: Record<string, string>;

  // Sandbox override for this request
  sandboxMode?: 'strict' | 'permissive' | 'disabled';

  // Callback for streaming output
  onOutput?: (chunk: string) => void;

  // Priority (higher = sooner)
  priority?: number;

  // Tags for filtering/grouping
  tags?: string[];
}

export interface ExecutionResult {
  id: string;
  success: boolean;

  // Full output (stdout + formatted)
  output: string;

  // Structured data if extractable
  data?: {
    filesCreated?: string[];
    filesModified?: string[];
    commands?: string[];
    errors?: string[];
  };

  // Execution metadata
  metadata: {
    startTime: Date;
    endTime: Date;
    durationMs: number;
    tokensUsed?: number;
    model: string;
    exitCode: number;
  };

  // Error details if failed
  error?: {
    code: string;
    message: string;
    stack?: string;
  };
}

export class HeadlessExecutor {
  constructor(config: HeadlessConfig);

  /**
   * Execute a single prompt headlessly
   */
  async execute(request: ExecutionRequest): Promise<ExecutionResult>;

  /**
   * Execute multiple prompts in batch
   */
  async executeBatch(
    requests: ExecutionRequest[],
    options?: { parallel?: number; stopOnError?: boolean }
  ): Promise<ExecutionResult[]>;

  /**
   * Execute with streaming output
   */
  executeStream(request: ExecutionRequest): AsyncIterable<string>;

  /**
   * Cancel a running execution
   */
  async cancel(id: string): Promise<boolean>;

  /**
   * Get execution status
   */
  getStatus(id: string): ExecutionStatus | undefined;

  /**
   * Graceful shutdown
   */
  async shutdown(): Promise<void>;
}

2. Sandbox Manager

// src/executor/sandbox-manager.ts

export interface SandboxProfile {
  name: string;
  mode: 'strict' | 'permissive' | 'disabled';

  // Filesystem restrictions
  filesystem: {
    readOnly?: string[];       // Read-only paths
    readWrite?: string[];      // Read-write paths
    denied?: string[];         // Completely blocked
    tempDir?: string;          // Temp directory location
  };

  // Network restrictions
  network: {
    policy: 'allow' | 'deny' | 'allowlist';
    allowedHosts?: string[];   // For allowlist mode
    allowedPorts?: number[];
  };

  // Process restrictions
  process: {
    allowShell: boolean;
    allowedCommands?: string[];
    deniedCommands?: string[];
    maxProcesses?: number;
  };

  // Resource limits
  resources: {
    maxMemoryMb?: number;
    maxCpuPercent?: number;
    maxDiskMb?: number;
  };
}

export class SandboxManager {
  /**
   * Create sandbox environment variables
   */
  createEnvironment(profile: SandboxProfile): Record<string, string>;

  /**
   * Get predefined profiles
   */
  getProfile(name: 'ci' | 'development' | 'production' | 'testing'): SandboxProfile;

  /**
   * Validate sandbox configuration
   */
  validate(profile: SandboxProfile): ValidationResult;

  /**
   * Apply sandbox to working directory
   */
  async prepareSandbox(workDir: string, profile: SandboxProfile): Promise<SandboxContext>;

  /**
   * Clean up sandbox artifacts
   */
  async cleanup(context: SandboxContext): Promise<void>;
}

// Predefined profiles
export const SANDBOX_PROFILES = {
  ci: {
    name: 'ci',
    mode: 'strict' as const,
    filesystem: {
      readWrite: ['${WORKSPACE}'],
      denied: ['/etc', '/root', '~/.ssh', '~/.aws'],
      tempDir: '/tmp/claude-ci'
    },
    network: {
      policy: 'allowlist' as const,
      allowedHosts: ['api.anthropic.com', 'registry.npmjs.org', 'github.com'],
      allowedPorts: [443, 80]
    },
    process: {
      allowShell: true,
      deniedCommands: ['rm -rf /', 'sudo', 'chmod 777', 'curl | bash'],
      maxProcesses: 10
    },
    resources: {
      maxMemoryMb: 4096,
      maxCpuPercent: 80
    }
  },

  development: {
    name: 'development',
    mode: 'permissive' as const,
    filesystem: {
      readWrite: ['${WORKSPACE}', '${HOME}/.npm', '${HOME}/.cache'],
      denied: ['~/.ssh/id_*', '~/.aws/credentials']
    },
    network: { policy: 'allow' as const },
    process: {
      allowShell: true,
      deniedCommands: ['rm -rf /'],
      maxProcesses: 50
    },
    resources: {
      maxMemoryMb: 8192
    }
  },

  production: {
    name: 'production',
    mode: 'strict' as const,
    filesystem: {
      readOnly: ['${WORKSPACE}'],
      readWrite: ['/tmp/claude-prod'],
      denied: ['**/.env*', '**/secrets/**', '**/*.pem']
    },
    network: {
      policy: 'allowlist' as const,
      allowedHosts: ['api.anthropic.com'],
      allowedPorts: [443]
    },
    process: {
      allowShell: false,
      allowedCommands: ['node', 'npm', 'git'],
      maxProcesses: 5
    },
    resources: {
      maxMemoryMb: 2048,
      maxCpuPercent: 50,
      maxDiskMb: 1024
    }
  },

  testing: {
    name: 'testing',
    mode: 'disabled' as const,
    filesystem: { readWrite: ['**'] },
    network: { policy: 'allow' as const },
    process: { allowShell: true, maxProcesses: 100 },
    resources: {}
  }
};

3. Task Queue

// src/queue/task-queue.ts

export interface QueuedTask {
  id: string;
  request: ExecutionRequest;
  status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
  priority: number;
  createdAt: Date;
  startedAt?: Date;
  completedAt?: Date;
  result?: ExecutionResult;
  retryCount: number;
  maxRetries: number;
}

export interface QueueConfig {
  // Persistence backend
  persistence: 'memory' | 'sqlite' | 'redis';
  persistencePath?: string;

  // Queue behavior
  maxSize: number;
  defaultPriority: number;
  maxRetries: number;
  retryDelayMs: number;

  // Processing
  concurrency: number;
  processingTimeoutMs: number;
}

export class TaskQueue {
  constructor(config: QueueConfig, executor: HeadlessExecutor);

  /**
   * Add task to queue
   */
  async enqueue(request: ExecutionRequest): Promise<string>;

  /**
   * Add multiple tasks
   */
  async enqueueBatch(requests: ExecutionRequest[]): Promise<string[]>;

  /**
   * Get task by ID
   */
  async getTask(id: string): Promise<QueuedTask | null>;

  /**
   * Cancel a pending/running task
   */
  async cancel(id: string): Promise<boolean>;

  /**
   * Get queue statistics
   */
  getStats(): QueueStats;

  /**
   * Start processing queue
   */
  start(): void;

  /**
   * Stop processing (wait for current tasks)
   */
  async stop(): Promise<void>;

  /**
   * Drain queue (cancel all pending)
   */
  async drain(): Promise<void>;

  /**
   * Subscribe to task events
   */
  on(event: 'taskStarted' | 'taskCompleted' | 'taskFailed', handler: (task: QueuedTask) => void): void;
}

4. HTTP/WebSocket API

// src/api/server.ts

export interface APIServerConfig {
  port: number;
  host: string;

  // Authentication
  auth: {
    type: 'none' | 'api-key' | 'jwt';
    apiKeys?: string[];
    jwtSecret?: string;
  };

  // Rate limiting
  rateLimit: {
    windowMs: number;
    maxRequests: number;
  };

  // CORS
  cors: {
    enabled: boolean;
    origins: string[];
  };
}

export class APIServer {
  constructor(
    config: APIServerConfig,
    executor: HeadlessExecutor,
    queue: TaskQueue
  );

  /**
   * Start the API server
   */
  async start(): Promise<void>;

  /**
   * Stop the server
   */
  async stop(): Promise<void>;

  /**
   * Get server status
   */
  getStatus(): ServerStatus;
}

// REST API Endpoints
//
// POST   /api/v1/execute           - Execute prompt (sync)
// POST   /api/v1/execute/stream    - Execute with SSE streaming
// POST   /api/v1/queue             - Add to queue (async)
// GET    /api/v1/queue/:id         - Get queued task
// DELETE /api/v1/queue/:id         - Cancel task
// GET    /api/v1/queue             - List queue
// GET    /api/v1/stats             - Get statistics
// GET    /api/v1/health            - Health check
//
// WebSocket /ws/v1/execute         - Real-time execution
// WebSocket /ws/v1/queue           - Queue events stream

5. Docker Executor

// src/docker/container-executor.ts

export interface DockerConfig {
  // Base image with Claude Code pre-installed
  image: string;  // e.g., 'ghcr.io/ruvnet/claude-flow-headless:latest'

  // Container resources
  resources: {
    cpus: number;
    memoryMb: number;
    diskMb: number;
  };

  // Network configuration
  network: {
    mode: 'bridge' | 'host' | 'none';
    exposePorts?: number[];
  };

  // Volume mounts
  volumes: {
    workspace: string;     // Host path for workspace
    cache?: string;        // Host path for cache
  };

  // Environment variables to pass through
  envPassthrough: string[];

  // Auto-cleanup containers
  autoRemove: boolean;

  // Pool configuration
  pool: {
    minContainers: number;
    maxContainers: number;
    idleTimeoutMs: number;
  };
}

export class ContainerExecutor {
  constructor(config: DockerConfig);

  /**
   * Initialize container pool
   */
  async initialize(): Promise<void>;

  /**
   * Execute in container
   */
  async execute(request: ExecutionRequest): Promise<ExecutionResult>;

  /**
   * Execute in isolated container (no pooling)
   */
  async executeIsolated(request: ExecutionRequest): Promise<ExecutionResult>;

  /**
   * Get container pool stats
   */
  getPoolStats(): PoolStats;

  /**
   * Scale pool
   */
  async scale(targetSize: number): Promise<void>;

  /**
   * Cleanup all containers
   */
  async cleanup(): Promise<void>;
}

CLI Commands

# Start headless server
npx @claude-flow/headless serve --port 3001 --sandbox strict

# Execute single prompt
npx @claude-flow/headless exec "Fix the bug in auth.ts" --cwd ./project

# Execute from file
npx @claude-flow/headless exec --file tasks.txt --parallel 3

# Queue management
npx @claude-flow/headless queue add "Refactor utils" --priority high
npx @claude-flow/headless queue list
npx @claude-flow/headless queue cancel <id>

# Docker mode
npx @claude-flow/headless docker start --containers 3
npx @claude-flow/headless docker exec "Run tests" --isolated
npx @claude-flow/headless docker scale 5

# Monitoring
npx @claude-flow/headless status
npx @claude-flow/headless metrics --prometheus

Use Cases

1. CI/CD Code Review

# .github/workflows/claude-review.yml
name: Claude Code Review
on: [pull_request]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Claude Review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          CLAUDE_CODE_HEADLESS: "true"
          CLAUDE_CODE_SANDBOX_MODE: "strict"
        run: |
          npx @claude-flow/headless exec \
            "Review this PR for bugs, security issues, and code quality. \
             Provide actionable feedback." \
            --output review.md

      - name: Post Review Comment
        uses: actions/github-script@v7
        with:
          script: |
            const review = require('fs').readFileSync('review.md', 'utf8');
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: review
            });

2. Batch Test Generation

import { HeadlessExecutor, TaskQueue } from '@claude-flow/headless';

const executor = new HeadlessExecutor({
  sandbox: { mode: 'permissive' },
  limits: { maxConcurrent: 3, timeoutMs: 300000 }
});

const queue = new TaskQueue(
  { persistence: 'sqlite', concurrency: 3 },
  executor
);

// Find all source files without tests
const files = glob.sync('src/**/*.ts').filter(f => !f.includes('.test.'));

// Queue test generation for each
for (const file of files) {
  await queue.enqueue({
    id: `test-${path.basename(file)}`,
    prompt: `Generate comprehensive unit tests for ${file}.
             Use Vitest. Follow TDD London School (mock dependencies).
             Achieve 80%+ coverage.`,
    workingDirectory: process.cwd(),
    priority: 1,
    tags: ['test-generation', path.dirname(file)]
  });
}

queue.start();

// Wait for completion
queue.on('taskCompleted', (task) => {
  console.log(`✓ Generated tests for ${task.id}`);
});

3. Kubernetes Job Orchestration

# claude-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: claude-migration
spec:
  template:
    spec:
      containers:
      - name: claude
        image: ghcr.io/ruvnet/claude-flow-headless:latest
        env:
        - name: ANTHROPIC_API_KEY
          valueFrom:
            secretKeyRef:
              name: anthropic-credentials
              key: api-key
        - name: CLAUDE_CODE_HEADLESS
          value: "true"
        - name: CLAUDE_CODE_SANDBOX_MODE
          value: "strict"
        command:
        - npx
        - "@claude-flow/headless"
        - exec
        - "Migrate database schema from v2 to v3"
        volumeMounts:
        - name: workspace
          mountPath: /workspace
      volumes:
      - name: workspace
        persistentVolumeClaim:
          claimName: project-workspace
      restartPolicy: Never

4. Distributed Swarm Execution

import { ContainerExecutor } from '@claude-flow/headless';

const executor = new ContainerExecutor({
  image: 'ghcr.io/ruvnet/claude-flow-headless:latest',
  resources: { cpus: 2, memoryMb: 4096, diskMb: 10240 },
  pool: { minContainers: 5, maxContainers: 20, idleTimeoutMs: 60000 }
});

await executor.initialize();

// Parallel execution across containers
const tasks = [
  'Implement authentication module',
  'Build REST API endpoints',
  'Create database migrations',
  'Write integration tests',
  'Generate API documentation'
];

const results = await Promise.all(
  tasks.map((task, i) => executor.execute({
    id: `task-${i}`,
    prompt: task,
    workingDirectory: '/workspace'
  }))
);

console.log(`Completed ${results.filter(r => r.success).length}/${tasks.length} tasks`);

Security Considerations

1. API Key Protection

// Never expose API keys in logs or responses
const sanitizeOutput = (output: string): string => {
  return output
    .replace(/sk-ant-[a-zA-Z0-9-_]+/g, '[REDACTED_API_KEY]')
    .replace(/ANTHROPIC_API_KEY=[^\s]+/g, 'ANTHROPIC_API_KEY=[REDACTED]');
};

2. Sandbox Enforcement

// Validate sandbox mode before execution
if (config.sandbox.mode === 'disabled' && !process.env.ALLOW_UNSAFE) {
  throw new Error(
    'Sandbox mode "disabled" requires ALLOW_UNSAFE=true environment variable'
  );
}

3. Resource Limits

// Enforce hard limits
const HARD_LIMITS = {
  maxTimeoutMs: 600000,      // 10 minutes
  maxOutputBytes: 10485760,  // 10MB
  maxConcurrent: 50,
  maxQueueSize: 1000
};

Implementation Phases

Phase 1: Core Executor (Week 1)

  • HeadlessExecutor with basic execution
  • SandboxManager with predefined profiles
  • Environment variable handling
  • Basic CLI commands

Phase 2: Task Queue (Week 2)

  • Persistent task queue (SQLite)
  • Priority scheduling
  • Retry logic with dead-letter handling
  • Queue CLI commands

Phase 3: API Server (Week 3)

  • REST API endpoints
  • WebSocket streaming
  • Authentication (API key, JWT)
  • Rate limiting

Phase 4: Docker Integration (Week 4)

  • Container executor
  • Pool management
  • Dockerfile and compose
  • Kubernetes examples

Phase 5: Monitoring & Polish (Week 5)

  • Prometheus metrics
  • Health checks
  • Documentation
  • Integration tests

Dependencies

{
  "name": "@claude-flow/headless",
  "version": "3.0.0-alpha.1",
  "dependencies": {
    "@claude-flow/shared": "^3.0.0-alpha.1",
    "better-sqlite3": "^9.0.0",
    "express": "^4.18.2",
    "ws": "^8.14.2",
    "dockerode": "^4.0.0",
    "prom-client": "^15.0.0",
    "winston": "^3.11.0",
    "zod": "^3.22.0"
  },
  "peerDependencies": {
    "@anthropic-ai/claude-code": ">=2.0.0"
  },
  "peerDependenciesMeta": {
    "@anthropic-ai/claude-code": {
      "optional": true
    }
  }
}

Consequences

Positive

  1. CI/CD Native - First-class support for automated workflows
  2. Scalable - Container pooling enables high throughput
  3. Secure - Multiple sandbox profiles for different contexts
  4. Observable - Prometheus metrics, structured logging

Negative

  1. Complexity - Another package to maintain
  2. Dependencies - Docker, SQLite add requirements
  3. Undocumented APIs - Claude Code env vars may change

Neutral

  1. Optional - Users who don't need headless can skip it
  2. Standalone - Can be used without other claude-flow packages

References

  • ADR-018: Claude Code Deep Integration
  • ADR-017: RuVector Integration Architecture
  • Claude Code Environment Variables (undocumented)
  • Docker Best Practices for CI/CD

Status: Proposed Next Steps: Await approval, then begin Phase 1 implementation