Skip to content

savitharaghunathan/zupp

Repository files navigation

Zupp

Zupp is a secure, runtime-agnostic agent execution platform for Kubernetes. It runs any AI agent runtime — Claude Code, OpenCode, or Goose — with any skill in an isolated sandbox on any K8s cluster, from a local kind cluster to production OpenShift.

zupp run skill code-review:v1.0.0 --runtime claude:v1.0.0 --model anthropic/claude-sonnet-4-6

Why Zupp

Unlike platforms that provide their own agent runtime, Zupp runs the actual agent runtime as a process in a sandbox. The agent reasons, plans, and acts as it would on a developer's laptop, but with cluster-grade isolation, supply chain trust, and audit.

  • Runtime-agnostic — bring Claude Code, OpenCode, or Goose (more coming)
  • OCI all the way — skills, runtimes, and base images are OCI artifacts stored in Quay, signed with cosign
  • Secure by default — read-only filesystem, non-root containers, NetworkPolicy isolation, RBAC scoping
  • Warm pool support — pre-warmed sandboxes via agent-sandbox for sub-5s startup

Architecture

┌──────────────────────────────────────────────────────┐
│                    User / CI / Agent                 │
│                         │                            │
│                    zupp CLI                          │
│                         │                            │
├─────────────────────────┼────────────────────────────┤
│              Zupp Controller (HA)                    │
│                         │                            │
│  ┌──────────┐  ┌───────┴────────┐  ┌──────────────┐  │
│  │ Resolver │  │ Sandbox        │  │ Observability│  │
│  │ + Cosign │  │ Manager        │  │ + Metrics    │  │
│  └──────────┘  └───────┬────────┘  └──────────────┘  │
│                        │                             │
├────────────────────────┼───────────────────────────-─┤
│              agent-sandbox CRDs                      │
│       Sandbox · SandboxClaim · SandboxWarmPool       │
│                         │                            │
├─────────────────────────┼────────────────────────────┤
│              Kubernetes Cluster                      │
│  Namespace │ Pod │ RBAC │ NetworkPolicy │ PSS        │
└──────────────────────────────────────────────────────┘

External: Quay (OCI artifacts) · cosign (signatures) · cert-manager (webhook TLS)

Supported Runtimes

Runtime Headless Mode Tool Scoping Skill Discovery Image Variants
Claude Code claude -p --disallowed-tools .claude/skills/ base, go
OpenCode opencode run N/A (sandbox isolation) .claude/skills/ base, go
Goose goose run -i N/A (extension config) .agents/skills/ base, go

Image variants are selected automatically when a skill declares runtime dependencies in its zupp.yaml (e.g., requirements.runtimes: [go]). The controller resolves rt-opencode:1.17.9rt-opencode-go:1.17.9.

Quick Start

Prerequisites

  • Kubernetes 1.31+ (or OpenShift 4.20+)
  • cert-manager
  • agent-sandbox controller (>= v0.5.0)

Install

# Create a kind cluster with Calico CNI
make kind-create

# Install Zupp
zupp install --kind

# Verify
zupp preflight

Configure

Create a llm-keys secret with credentials for your LLM provider:

# Anthropic
kubectl create secret generic llm-keys -n zupp-system \
  --from-literal=anthropic-api-key=sk-ant-...

# Vertex AI (GCP)
kubectl create secret generic llm-keys -n zupp-system \
  --from-literal=vertex-project-id=my-project \
  --from-literal=vertex-region=global \
  --from-file=vertex-credentials=$HOME/.config/gcloud/application_default_credentials.json

# OpenAI
kubectl create secret generic llm-keys -n zupp-system \
  --from-literal=openai-api-key=sk-...

# Gemini
kubectl create secret generic llm-keys -n zupp-system \
  --from-literal=gemini-api-key=...

Supported providers: Anthropic, Vertex AI, OpenAI, Gemini, Azure OpenAI. The adapters detect which keys are present and inject the appropriate environment variables.

# Set defaults
zupp config model anthropic/claude-sonnet-4-6
zupp config namespace default

Import a Runtime

zupp import runtime claude:v1.0.0 \
  --source ghcr.io/anthropics/claude-code:latest \
  --key cosign.key

Run a Skill

# Skill-scoped execution
zupp run skill code-review:v1.0.0 \
  --runtime claude:v1.0.0 \
  --repo https://github.com/org/repo \
  --ref feature-branch

# Goal-directed agent
zupp run agent \
  --goal "Review the PR for security issues and run the test suite" \
  --runtime claude:v1.0.0 \
  --skills code-review,testing

Monitor

zupp status <run-id>          # Show phase, conditions, token usage
zupp logs <run-id>             # Stream agent output
zupp list runs                 # List all runs
zupp diagnose <run-id>         # Automated troubleshooting

CLI Reference

zupp
├── run skill/agent            Run a skill or agent in a sandbox
├── status/logs                Show status or stream logs
├── stop/delete                Lifecycle management
├── list runs/runtimes/skills  List resources
├── inspect run/runtime/skill  Detailed views
├── import runtime/skill       Import OCI artifacts
├── config                     Persistent settings (~/.zupp/config.yaml)
├── auth set                   Credential management
├── dev skill                  Local development mode
├── output/workspace           Artifact retrieval
├── diagnose                   Automated troubleshooting
├── preflight                  Cluster readiness checks
├── install                    Install Zupp on a cluster
└── runtime rescan             Trigger vulnerability rescan

CRDs

CRD Scope Purpose
ZuppAgentRun Namespaced Execution resource — drives a skill or agent run through its lifecycle
ZuppRuntime Cluster Tracks imported runtimes — version, digest, scan status
ZuppPolicy Namespaced Permission caps, resource limits, allowed runtimes per namespace

Security Model

  • Isolation — each sandbox gets a dedicated ServiceAccount, Role, RoleBinding, and NetworkPolicy
  • Least privilege — skills declare required permissions in zupp.yaml, capped by ZuppPolicy
  • Network — deny-all ingress, egress limited to DNS + HTTPS (LLM APIs)
  • Supply chain — cosign-verified OCI artifacts, vulnerability scanning via Quay Clair
  • Pod securityrunAsNonRoot, readOnlyRootFilesystem, drop all capabilities, seccomp RuntimeDefault
  • Admission — validating webhook enforces mode discriminator and required fields

Skill Manifest

Skills declare their requirements in a zupp.yaml file, which is included in the skill's ConfigMap alongside SKILL.md. The controller reads this manifest to select the right runtime image variant and validate permissions.

apiVersion: zupp.io/v1alpha1
type: standard
requirements:
  runtimes: [go]           # go, python, java, node
  packages: [git]
  tools: [go, git]
inputs:
  - name: app
    type: string
    required: true
permissions:
  - apiGroup: ""
    resources: [pods]
    verbs: [get, list]
egress:
  - host: github.com
    ports: [443]
limits:
  timeout: 30m
  cpu: "2"
  memory: 4Gi

When requirements.runtimes is set, the controller selects a variant image with those runtimes pre-installed (e.g., rt-opencode-go:1.17.9 instead of rt-opencode:1.17.9). This is necessary because sandbox containers run with readOnlyRootFilesystem: true — packages cannot be installed at runtime.

If no zupp.yaml is present in the skill ConfigMap, the base image is used (backward compatible).

Development

# Build
make build                     # CLI + controller binaries
make container-build           # Controller container image (podman)

# Runtime images
make runtime-build-opencode    # Base opencode image
make runtime-build-opencode-go # Go variant
make runtime-build-claude      # Base claude image
make runtime-build-claude-go   # Go variant
make runtime-build-all         # All base + variant images

# Test
make test                      # Unit + integration tests
make e2e-test                  # E2E tests (requires kind cluster)
make contract-test             # Agent-sandbox contract tests

# Generate
make generate                  # Deepcopy methods
make manifests                 # CRD YAML

License

Apache 2.0

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages