Skip to content

About

Run Claude Code as an HTTP API inside a Unikraft unikernel

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Claude Code on Unikraft

Run Claude Code (Anthropic's agentic coding tool) as an HTTP API inside a Unikraft unikernel — a lightweight, single-address-space VM that boots in milliseconds.

What This Is

A minimal Node.js HTTP server that wraps claude -p (Claude Code's programmatic/pipe mode) and exposes it as an async job API. The server runs inside a Unikraft unikernel on Unikraft Cloud.

Architecture:

Client → HTTPS → Unikraft Gateway → HTTP :8080 → server.js → claude -p → Anthropic API

Quick Start

Prerequisites

  • kraft CLI (brew install unikraft/cli/kraftkit)
  • Unikraft Cloud account + token
  • Anthropic API key

Deploy

export UKC_TOKEN="your-unikraft-token"
export ANTHROPIC_API_KEY="your-anthropic-key"

kraft cloud deploy \
  --metro dal \
  -p 443:8080 \
  -M 2048 \
  --name claude-sandbox \
  -e "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" \
  .

Use

# Health check
curl https://your-instance.dal.unikraft.app/health

# Submit a prompt (returns immediately with job ID)
curl -X POST https://your-instance.dal.unikraft.app/prompt \
  -H "Content-Type: application/json" \
  -d '{"prompt": "What is 2+2?", "max_turns": 1}'

# Poll for results
curl https://your-instance.dal.unikraft.app/job/<job-id>

# List all jobs
curl https://your-instance.dal.unikraft.app/jobs

API

Method Path Description
GET /health Health check, returns {"status": "ok", "runtime": "unikraft"}
POST /prompt Submit a prompt. Body: {"prompt": "...", "max_turns": N}. Returns 202 with job_id
GET /job/:id Get job status and output
GET /jobs List all jobs with summary

Job Response

{
  "id": "uuid",
  "status": "completed",
  "exit_code": 0,
  "duration_ms": 1376,
  "output": "{\"type\":\"result\",\"result\":\"4\", ...}",
  "stderr": ""
}

The output field contains Claude Code's JSON output (when using --output-format json), which includes the result text, token usage, cost, and session metadata.

What We Learned

This project was an exploration of running Claude Code in a unikernel environment. Here's what we discovered through ~12 deployment iterations:

Key Findings

  1. It works. Claude Code runs successfully inside a Unikraft unikernel with full tool use (file read/write, bash execution). Response times are comparable to running locally (~1-7 seconds for simple prompts).

  2. IS_SANDBOX=1 is required. Claude Code refuses --dangerously-skip-permissions when running as root (which Unikraft always does). Setting IS_SANDBOX=1 in the environment bypasses this check — it's the same mechanism Anthropic's own sandbox infrastructure uses.

  3. stdin must be /dev/null. Using spawn() with stdio: ["ignore", "pipe", "pipe"] is critical. Without explicitly closing stdin, Claude Code hangs indefinitely after initialization (gets stuck after "Policy limits: Fetched successfully" in the debug log).

  4. Alpine base works, slim doesn't. node:22-alpine produces a ~350MB image that fits in Unikraft's memory. node:22-slim was ~544MB and OOM'd even with 2GB RAM (initramfs unpacking requires roughly 2x image size).

  5. Unikraft ignores Dockerfile USER directives. Everything runs as root. The USER instruction in the Dockerfile has no effect.

  6. HOME must be set explicitly. Unikraft overrides HOME to / regardless of the Dockerfile ENV directive. Must set HOME=/root in the spawn environment.

  7. ToS must be pre-accepted. Claude Code requires onboarding acceptance. Pre-writing {"hasCompletedOnboarding":true,"hasAcknowledgedMdmPolicy":true} to ~/.claude.json in the Dockerfile handles this.

  8. Gateway timeout is ~60s. Unikraft's HTTP gateway times out long-running requests, requiring the async job pattern (POST returns job ID, poll for results).

  9. 2048MB RAM is the sweet spot. 1024MB OOMs during initramfs unpacking. 2048MB works reliably.

What Doesn't Work

  • No SSH/exec access. All debugging must happen via HTTP endpoints or kraft cloud instance logs.
  • No persistent storage. Each instance boots fresh. Files written during a session are lost on restart.
  • Cold start penalty. First Claude Code invocation initializes Statsig, fetches policy settings, etc. (~2s overhead). Subsequent calls use cached config.
  • Scale-to-zero breaks long jobs. If the instance scales to zero mid-job, the job is lost. Use scale_to_zero.policy: "off" in the Kraftfile.
  • Storage quota is tight. 1GB image storage quota means you need to delete old images before deploying new ones.

Comparison with Other Sandbox Platforms

Platform Boot Time I/O Speed Claude Code? Price
Unikraft ~30ms Native Yes (this project) ~$0.06/hr
E2B ~200ms (warm) tmpfs fast, rootfs slow Untested $0.014/hr
Vercel 1-5s Very slow (EROFS) Broken (I/O) $0.18/hr
Docker ~500ms Native Yes Varies

Unikraft's advantage is the unikernel architecture — minimal attack surface, millisecond boot times, and near-native I/O performance since there's no overlay filesystem.

Files

File Description
server.js HTTP server wrapping Claude Code with async job management
Dockerfile Alpine-based image with Claude Code pre-installed and ToS pre-accepted
Kraftfile Unikraft Cloud deployment configuration

Environment Variables

Variable Required Description
ANTHROPIC_API_KEY Yes Anthropic API key for Claude

These are set automatically by the server:

Variable Value Why
IS_SANDBOX 1 Bypasses root check for --dangerously-skip-permissions
HOME /root Unikraft overrides HOME to /; Claude Code needs a real home dir

What's Next

  • Authentication. The API is currently unauthenticated — add API key validation or mTLS.
  • Job cleanup. Jobs accumulate in memory indefinitely. Add TTL-based eviction.
  • Streaming. Support Server-Sent Events for real-time output streaming.
  • Multi-instance. Use Unikraft's auto-scaling for parallel job execution.
  • Persistent workspaces. Mount Unikraft volumes for project files that survive restarts.
  • MCP server support. Configure Claude Code with MCP servers for extended tool access.

About

Run Claude Code as an HTTP API inside a Unikraft unikernel

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages