{"slug": "show-hn-pullrun-run-one-oci-image-as-a-container-firecracker-or-apple-vm", "title": "Show HN: Pullrun – Run One OCI Image as a Container, Firecracker, or Apple VM", "summary": "Pullrun, a new single-binary OCI runtime, launches as an open-source tool that runs the same OCI image as a container, Firecracker microVM, Apple Silicon VM, Kubernetes workload, or AI agent task without requiring a daemon or separate VM images. The 12 MB static binary uses a content-addressed DAG store and peer-to-peer image distribution, aiming to unify multiple execution engines across development, production, and AI workloads.", "body_md": "**Run the same OCI image as a container, Firecracker microVM, Apple Silicon VM, Kubernetes workload, or AI agent task. No daemon required. No overlayfs. No separate VM images.**\n\n[ ⚡ 30-Second Install](#-install) •\n\n[•](#-quick-start)\n\n**🚀 Quick Start**[•](#-architecture)\n\n**🏗️ Architecture**[•](#-why-pullrun)\n\n**🎯 Why Pullrun?**[•](#-features)\n\n**🗺️ Feature Map**[•](#-kubernetes)\n\n**☸️ Kubernetes**\n\n**🤖 AI Agents** Pullrun is a **single-binary OCI runtime** that runs the same image as a container or a VM. It stores layers in a content-addressed DAG (no overlayfs), syncs blocks peer-to-peer, and fits in 12 MB.\n\n**Why this matters:** Modern infrastructure uses too many execution engines — Docker for dev, containerd for production, Firecracker for isolation, CRI for Kubernetes, MCP agents for AI. Each has its own image format, storage, and operational model — even though they all run the same OCI images. Pullrun collapses these layers into one runtime.\n\n**Key differentiators:**\n\n**Containers and VMs from the same image**— no separate VM build step, no separate VM image format** Content-addressed DAG store**— zero-copy mmap reads, deduplicated by content hash, byte-identical across every node** P2P image distribution**— one registry pull per cluster, rest sync peer-to-peer at LAN speed** 12 MB static binary**— no daemon required by default, optional runtime daemon for background services\n\n**Also included:** Kubernetes CRI shim (beta), Docker Compose support, MCP server for AI agents, policy engine (Cosign, SBOM, seccomp), P2P sync layer, and AES-256-GCM encrypted secrets — all in the same binary.\n\n```\n# Apple Silicon VM (macOS default) — 3 s\npullrun run alpine:3.18 --cmd \"echo\" --cmd \"hello pullrun\" --attach -t\n\n# Firecracker microVM (Linux) — 400 ms\npullrun run alpine:3.18 --backend vm --cmd \"echo\" --cmd \"hello pullrun\" --attach -t\n\n# Container (Linux) — 400 ms\npullrun run alpine:3.18 --cmd \"echo\" --cmd \"hello pullrun\"\n\n# Windows WSL2 — same image, same command, same store\npullrun.exe run alpine:3.18 --cmd \"echo\" --cmd \"hello pullrun\"\n# One command, any platform\ncurl -fsSL https://github.com/pullrun/pullrun/raw/main/install.sh | bash\n```\n\n| Platform | What you get |\n|---|---|\nmacOS |\n`brew tap pullrun/tap && brew install pullrun` → native binary, no Xcode |\nLinux |\nAPT package or direct download, systemd service (requires `runc` for containers, `/dev/kvm` for VMs) |\nWindows |\n`pullrun.exe` + WSL2 auto-provisioning, runc + Firecracker |\n\n## Manual install options\n\n```\n# macOS (Homebrew — pre-built, no build deps)\nbrew tap pullrun/tap && brew install pullrun\n\n# From source\nmake build && export PATH=\"$PWD/bin:$PATH\"\n\n# Cross-compile Windows CLI\ncd cli/pullrun && GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o pullrun.exe .\n# ── Pull any OCI image ──────────────────────────────────────────\npullrun pull alpine:3.18     # 968 ms — ~2x faster than Docker\n\n# ── Run as a container (Linux) ─────────────────────────────────\npullrun run alpine:3.18 --cmd \"echo\" --cmd \"hello pullrun\"\n\n# ── Run as a microVM (macOS/Linux) ─────────────────────────────\npullrun run alpine:3.18 --backend vm --cmd \"echo\" --cmd \"hello\" --attach -t\n\n# ── Interactive shell with detach ──────────────────────────────\npullrun run alpine:3.18 --tty --attach --cmd /bin/sh\n#   Ctrl-P Ctrl-Q  → detach (workload keeps running)\n#   pullrun exec <id> -t /bin/sh → re-attach\n\n# ── Background workload ────────────────────────────────────────\npullrun run alpine:3.18 --cmd /bin/sleep --cmd 3600\n\n# ── Build & push (no Docker daemon needed) ─────────────────────\npullrun build ./Dockerfile . -t myapp:latest\npullrun build ./Dockerfile . -t myapp:latest --platform linux/amd64,linux/arm64\npullrun push <root-digest> ghcr.io/myorg/myimg:latest\n\n# ── Export/import for air-gapped ───────────────────────────────\npullrun save <digest> -o myimage.tar\npullrun load -i myimage.tar\n\n# ── Compose (separate binary) ────────────────────────────────\npullrun-compose up -f myapp/compose.yml               # containers (default on Linux)\npullrun-compose up -f myapp/compose.yml --backend vm   # same compose, VM isolation\npullrun-compose logs -f\npullrun-compose down\n\n# ── Lifecycle ──────────────────────────────────────────────────\npullrun list                  # all workloads (pending/running/exited)\npullrun stop <id>\npullrun exec <id> /bin/echo hello\n# Re-attach to a detached workload (allocates a fresh PTY)\npullrun exec <id> -t -- /bin/sh\n# Or, for bidirectional I/O streaming without a new shell:\npullrun workload run <id>\n\n# ── Image management ──────────────────────────────────────────\npullrun images                 # list pulled images in local DAG store\npullrun rmi alpine:3.18       # remove an image, cascade-delete unreachable layers\npullrun rmi sha256:abc...     # also works by digest\n\n# ── GC (DAG store garbage collection) ─────────────────────────\npullrun gc                    # dry-run — report what would be deleted\npullrun gc --apply            # actually delete unreachable nodes\npullrun gc --apply --force    # bypass 90% safety guard\n\n# ── Events & Stats ─────────────────────────────────────────────\npullrun events --types=WORKLOAD_STARTED,POLICY_DENIED\npullrun stats <id>\n\n# ── Network ────────────────────────────────────────────────────\npullrun network create my-net --subnet 10.43.1.0/24\npullrun run alpine:3.18 --net bridge\n\n# ── Secrets ────────────────────────────────────────────────────\npullrun secret create db_password -                     # from stdin\npullrun run myapp:latest --secret db_password\n\n# ── Configs ────────────────────────────────────────────────────\npullrun config create nginx.conf ./nginx.conf       # from file\npullrun config create nginx.conf -                   # from stdin\npullrun run nginx:latest --config nginx.conf\n\n# ── Diff & Inspect ─────────────────────────────────────────────\npullrun diff <id>\npullrun inspect <id>\npullrun commit <id> myapp:snapshot\n\n# ── Login ──────────────────────────────────────────────────────\npullrun login ghcr.io\npullrun logout\n\n# ── MCP (AI agents) ────────────────────────────────────────────\npullrun mcp                   # stdio mode (for opencode, Claude Code)\npullrun mcp --sse :8080       # SSE mode (for remote agents)\n\n# ── P2P sync ───────────────────────────────────────────────────\npullrun-runtime daemon --sync-addr 0.0.0.0:9500\n```\n\nDocker's overlayfs store is a filesystem overlay — CVEs in overlayfs (CVE-2023-0386, CVE-2023-32629) can let a container escape to the host. Pullrun's content-addressed DAG store stores layers **as-is**, verified by content hash. No overlayfs, no escape.\n\nPullrun also mitigates **shared-kernel cross-container risks** that aren't specific to any storage driver — for example, kernel page-cache bugs like CVE-2026-31431 (\"Copy Fail\") affect all containers sharing a host kernel, regardless of the storage backend. Per-VM kernel isolation (Firecracker, Apple Virtualization) fully contains these. The DAG store makes the VM path zero-cost: the same image, no separate VM build step.\n\nPullrun is also **rootless by default** — no `sudo`\n\nneeded, no daemon listening on a TCP socket, no attack surface from a central dockerd.\n\n| Backend | Isolation | Pullrun | Docker | Podman |\n|---|---|---|---|---|\n| Linux containers (runc) | Process | ✅ | ✅ | ✅ |\n| Firecracker microVMs | Per-VM kernel | ✅ | ❌ | ❌ |\n| Apple Silicon VMs | Per-VM kernel | ✅ | ❌ | ❌ |\n| Windows WSL2 containers | Process | ✅ | ✅ | ❌ |\n| Windows Firecracker VMs | Per-VM kernel | ✅ | ❌ | ❌ |\n\n**Same image, any isolation level.** No separate VM image build step. The OCI manifest IS the VM rootfs.\n\nPullrun's store is built on [rkyv](https://github.com/rkyv/rkyv) + [mmap](https://github.com/danburkert/memmap2). OCI layers are stored once, deduplicated by content hash, and `mmap()`\n\n'd directly — no tar extraction, no overlayfs, no `dockerd`\n\nprocess owning the data.\n\nA\n\n`sha256:`\n\ndigest is globally consistent. Every node that has pulled`alpine:3.18`\n\nstoresbyte-identicalfiles on disk. This makes P2P sync trivial: blocks are verified by content hash, transferred delta-only, and deduplicated across the entire cluster.\n\n| Metric | Pullrun | Docker |\n|---|---|---|\nFirst `alpine:3.18` pull |\n968 ms |\n~2 s |\n| Container run latency | ~400 ms |\n~800 ms |\n| Apple Virt VM boot | ~160 ms |\nN/A |\n| Firecracker VM cold boot | ~500 ms |\nN/A |\n| Firecracker VM warm pool | ~200 ms |\nN/A |\n| Idle daemon RSS | 24.6 MiB |\n~90 MiB |\n| Binary size | 12 MB |\n~75 MB |\n| Rootless by default | ✅ | ❌ (`dockerd` as root) |\n| Central daemon | Optional | Required |\n\nBenchmarks: single-node, cold cache, alpine:3.18 on Apple M3 (macOS 14) for Pullrun vs Docker Desktop 4.27. Container run latency measured from run command exit to workload PID alive. Apple VM boot measured to interactive exec prompt. Firecracker measurements on Linux x86_64 with KVM; warm pool configured with --vm-warm-pool-size 4. Pullrun daemon RSS measured after pullrun pull alpine:3.18 + pullrun run alpine:3.18 --tty --attach --cmd /bin/sh then detached. Docker RSS from docker run -d --name idle alpine:3.18 sleep 3600.\n\nBenchmarked with [ hyperfine](https://github.com/sharkdp/hyperfine) (≥10 iterations, mean ± stddev reported). The benchmark script lives at\n\n[— run it yourself to reproduce the numbers.](/pullrun/pullrun/blob/main/hack/bench.sh)\n\n`hack/bench.sh`\n\n`pull`\n\n, `run`\n\n, `stop`\n\n, `exec`\n\n, `attach`\n\n, `list`\n\n, `logs`\n\n, `stats`\n\n, `events`\n\n, `inspect`\n\n, `prune`\n\n, `rmi`\n\n, `gc`\n\nplus:\n\n— create a new image layer from a running container's current filesystem. The DAG store computes the delta against the original image, producing a content-addressed layer.`commit`\n\n— show file-level changes between a running workload and its original image. The store compares DAG trees to produce an add/modify/delete listing.`diff`\n\n— live resource limit changes (CPU millicores, memory bytes) without restarting the workload.`update`\n\n— bidirectional file copy between host and workload paths.`cp`\n\n— OCI-compatible single-file tarball export/import for air-gapped environments. Re-import produces identical content hashes.`save`\n\n/`load`\n\n— bearer token auth for private OCI registries.`login`\n\n/`logout`\n\nNative Dockerfile builder (`FROM`\n\n, `RUN`\n\n, `COPY`\n\n, `ADD`\n\n, `WORKDIR`\n\n, `ENV`\n\n, `CMD`\n\n, `ENTRYPOINT`\n\n) with content-addressed layer caching by instruction hash. Uses runc directly for `RUN`\n\n— no Docker daemon. Multi-platform builds via `--platform linux/amd64,linux/arm64`\n\n.\n\nKernel binaries are first-class OCI content. `pullrun kernel install`\n\ndownloads a vmlinux from an OCI registry into the DAG store. The `--kernel-image`\n\nflag lets any workload specify a custom kernel by OCI reference — same store-backed, content-addressed pipeline: verified by digest, cached forever, pushable to any registry.\n\nFull Docker Compose-compatible workflow: `up`\n\n, `down`\n\n, `logs`\n\n, `ps`\n\n, `build`\n\n. Supports dependency ordering (topological sort), port mapping, environment variables, volumes (bind mounts), resource limits (CPU/memory), labels, and per-project bridge networks for isolation. Parses standard `docker-compose.yml`\n\nfiles via the [ compose-spec/compose-go](https://github.com/compose-spec/compose-go) library.\n\nEach service can run as a container or VM — use `--backend vm`\n\nto boot all services as Firecracker microVMs from the same compose file, no changes required.\n\nDrop-in CRI shim at [ cri/pullrun-cri/](/pullrun/pullrun/blob/main/cri/pullrun-cri) — implement\n\n`RuntimeService`\n\nand `ImageService`\n\nfrom the Kubernetes CRI API. Maps pod sandboxes to pullrun workloads, supports RuntimeClass (`pullrun-container`\n\n/ `pullrun-vm`\n\n), pod annotations for image/CPU/memory overrides, and streaming (exec, attach, port-forward).A native **control-plane stub** lives in [ control-plane/](/pullrun/pullrun/blob/main/control-plane):\n\n`pullrun-controller`\n\n(scheduler) + `pullrun-agent`\n\n(per-node deployer) communicating over gRPC. This is a v1 work-in-progress with etcd, `.pullrun.local`\n\nDNS, and admission control planned — but the wire protocol is stable today.Native [Model Context Protocol](https://modelcontextprotocol.io) server exposing 15 runtime operations as MCP tools — `run`\n\n, `stop`\n\n, `exec`\n\n, `list`\n\n, `get`\n\n, `inspect`\n\n, `logs`\n\n, `stats`\n\n, `pull_image`\n\n, `list_images`\n\n, `build`\n\n, `push`\n\n, `prune`\n\n, `compose_up`\n\n, `compose_down`\n\nplus MCP resources (`pullrun://workload/{id}`\n\n, `pullrun://workload/{id}/logs`\n\n, `pullrun://store/info`\n\n, `pullrun://images`\n\n). Works in stdio mode (for opencode, Claude Code, Cursor) or SSE mode (for remote agents via HTTP).\n\nGate workloads before they run — built-in support for:\n\n**Cosign** signature verification (Ed25519 key pairs, key ID matching)**SBOM** evaluation (CVSS scoring, ban by license)**Seccomp** profiles (`default`\n\nallowlist of ~50 syscalls,`unconfined`\n\n, or custom JSON)**Read-only rootfs**— prevents runtime tampering (write only to`--volume`\n\nmounts)— blocks`no_new_privileges`\n\n`setuid`\n\nand`capset`\n\nescalation- Policy is declarative:\n`required_signature: true`\n\n,`max_cvss_score: 7.0`\n\n,`deny_licenses: [\"GPL-3.0\"]`\n\nCompose all four: `--require-signature --readonly-rootfs --no-new-privileges --seccomp-profile default`\n\n.\n\nNodes share image blocks peer-to-peer via gRPC + Bloom filters. One node pulls from the registry, the rest delta-sync from each other. Features: mDNS/discovery for zero-config LAN peer finding, Bloom filter cache to avoid redundant transfers, gossip protocol for peer state, delta computation, registrar service for peer tracking.\n\nUser-defined bridge networks with IPAM, inbound/outbound port forwarding, DNS resolution, and `iptables`\n\nintegration. Four modes per workload via `--net`\n\n: ** isolated** (default for containers, loopback only with host proxy on\n\n`10.42.0.1`\n\n), **(shared**\n\n`bridge`\n\n`pullrun-br0`\n\nbridge, inter-workload communication), **(default for VMs, userspace NAT via slirp4netns — no bridge, no iptables),**\n\n`slirp`\n\n**(shares host namespace),**\n\n`host`\n\n**(no network). Isolation is enforced by the proxy, not per-workload VLANs.**\n\n`none`\n\nAES-256-GCM encryption at rest, decrypted into workload tmpfs at runtime. `pullrun secret create/get/ls/inspect/rm`\n\n— data stays encrypted on disk, only the runtime process can decrypt.\n\nSingle-file OCI-compatible tarball export for air-gapped environments. Re-import produces identical content hashes.\n\nReal-time event stream via `pullrun events`\n\n— `IMAGE_PULLED`\n\n, `WORKLOAD_STARTED`\n\n, `POLICY_DENIED`\n\n, etc. Per-workload `stats`\n\nwith CPU/memory. Prometheus metrics exporter built into the daemon. PrometheusRule alerting config in [ deploy/](/pullrun/pullrun/blob/main/deploy).\n\n`pullrun rmi`\n\nremoves an image by tag or digest with **immediate cascade deletion** of unreachable subtree nodes. Per-node refcounts (`node.refcount`\n\nsidecar files) preserve shared layers — a layer referenced by another image is never deleted until the last referencing image is removed. Crash recovery via `recompute_all_refcounts`\n\non daemon startup rebuilds refcounts from all tagged image and workload roots.\n\n`pullrun gc`\n\nreclaims unreachable DAG nodes (orphaned layers, manifests, blobs) that are no longer reachable from any tagged image or running workload. Features: dry-run by default (report only), `--apply`\n\nto actually delete, `--force`\n\nto bypass the 90% safety guard, op-lock protection for in-flight operations, VM kernel image pinning via `kernel_image_digest`\n\n. The store no longer grows forever.\n\nFull TTY support with **detach/re-attach** via `Ctrl-P Ctrl-Q`\n\n. Works across all backends (container, Firecracker VM, Apple VM). Detached workloads keep running — re-attach with `pullrun exec --tty <id> /bin/sh`\n\n. Even works on exited workloads (daemon starts a fresh sleep container).\n\n`pullrun run --health-cmd 'curl -f http://localhost:80'`\n\n— periodic health checks with configurable interval, timeout, and retries. `--restart on-failure|always|unless-stopped`\n\ncontrols automatic restart on exit. Health state is surfaced via `pullrun inspect`\n\nand `pullrun events`\n\n.\n\nStopped VMs behave like hibernated machines — all writes preserved, restart on demand with `exec`\n\n. Backend specifics: **Apple Virt** rootfs persists via VirtioFS, **Firecracker** retains the ext4 image, **Container (runc)** rootfs is ephemeral (only `--volume`\n\nmounts survive). No re-pull needed.\n\n`pullrun login <registry>`\n\nfor bearer token auth. Daemon accepts `--insecure-registry`\n\nfor plain-HTTP mirrors and air-gapped LAN caches.\n\nPullrun ships a CRI shim in [ cri/pullrun-cri/](/pullrun/pullrun/blob/main/cri/pullrun-cri) that implements the Kubernetes Container Runtime Interface. It maps pod sandboxes to pullrun workloads and supports:\n\n`RuntimeClass`\n\n—`pullrun-container`\n\nfor runc containers,`pullrun-vm`\n\nfor Firecracker VMs- Pod annotations:\n`pullrun.io/image`\n\n,`pullrun.io/cpu-millicores`\n\n,`pullrun.io/memory-bytes`\n\n- Streaming: exec, attach, port-forward\n- Image management via the DAG store\n\nDeploy as a DaemonSet with manifests in [ deploy/](/pullrun/pullrun/blob/main/deploy):\n\n```\nkubectl apply -f deploy/runtime-daemon.yaml\nkubectl apply -f deploy/serviceaccount.yaml\nkubectl apply -f deploy/servicemonitor.yaml\n```\n\nAny MCP-compatible AI agent (opencode, Claude Code, Cursor) can control pullrun through natural language:\n\n```\n# Start the MCP server\npullrun mcp\n\n# In opencode or Claude Code, the agent can now:\n#   \"pull alpine and run it as a VM\"\n#   \"exec into my-app and check the logs\"\n#   \"show me all running workloads\"\n#   \"run docker-compose up from my project\"\n```\n\nThe MCP server exposes 15 tools and 4 resource types. SSE mode for remote agents: `pullrun mcp --sse :8080`\n\n.\n\n```\n# Node A — seed\npullrun-runtime daemon --sync-addr 0.0.0.0:9500\n\n# Node B — pulls delta blocks from Node A\npullrun-runtime daemon --sync-addr 0.0.0.0:9501 \\\n  --sync-peers node-a.example.com:9500\n```\n\nEach block verified by content hash before acceptance — no trust required.\n\n| Backend | Isolation | Platform | Boot Time | Best For |\n|---|---|---|---|---|\n| 🐧 Linux Containers (runc) | Process (namespace) | Linux, macOS, Windows (WSL2) | ~400 ms | Dev, CI/CD, dense packing |\n| 🔥 Firecracker microVM | Per-VM kernel (KVM) | Linux x86_64, Windows (WSL2 x86_64) | ~500 ms cold / ~200 ms warm pool | Multi-tenant, untrusted workloads, compliance, fast-recycling sandboxes |\n| 🍎 Apple Virtualization | Per-VM kernel (Hypervisor.framework) | macOS Apple Silicon | ~160 ms | macOS dev, Apple Silicon CI |\n\n```\n                              pullrun (Go CLI)\n                   pull · run · build · compose · inspect\n                   events · stats · network · secret · mcp\n                              │\n                              │ gRPC (UDS or TCP)\n                              ▼\n                   ┌─────────────────────────────────────┐\n                   │         pullrun-runtime             │\n                    │  ┌──────────┐   ┌──────────────────┐ │\n                    │  │ Store    │   │ Executor         │ │\n                    │  │ (DAG)    │   │ runc / VM        │ │\n                    │  │ └ rkyv   │   │ └ VmPool (warm)  │ │\n                    │  │ └ mmap   │   │                  │ │\n                    │  │ └ DashMap│   │                  │ │\n                   │  └────┬─────┘   └──────┬───────┘    │\n                   │       │                │            │\n                   │  ┌────┴────────────────┴────┐       │\n                   │  │       Network            │       │\n                   │  │  IPAM · Proxy · DNS      │       │\n                   │  └──────────────────────────┘       │\n                   │                                      │\n                   │  Sync · Policy · Secrets · Metrics   │\n                   └──────────────────────────────────────┘\n                              │\n                   ┌──────────┴──────────┐\n                   │      Kubernetes     │\n                   │  CRI shim · Runtime │\n                   │  Class · Prometheus │\n                   └─────────────────────┘\n```\n\nThe store uses `DashMap<Digest, Arc<Mmap>>`\n\nfor lock-free concurrent reads — the first reader pays for `mmap()`\n\n+ page faults, every subsequent reader is a single atomic load. The Rust workspace is eleven crates (store, oci, exec, vm, net, dns, vsock, sync, policy, runtime, init); the Go side is the CLI, CRI shim, compose, and control-plane stub.\n\n```\nproto/            # Protobuf definitions (single source of truth)\nruntime/          # Rust workspace — core data plane\n  pullrun-store/   # Zero-copy DAG store (rkyv + mmap + DashMap concurrent cache)\n  pullrun-oci/     # OCI client + DAG converter\n  pullrun-exec/    # Executor trait + runc wrapper\n  pullrun-vm/      # Firecracker + Apple Virt backends, warm VM pool (pool.rs), pullrun-init guest agent\n  pullrun-net/     # IPAM, proxy, DNS, iptables, slirp4netns\n  pullrun-dns/     # In-process DNS server for workload resolution\n  pullrun-vsock/   # Vsock transport layer for VM guest-host communication\n  pullrun-sync/    # P2P block sync (Bloom, mDNS, gossip)\n  pullrun-policy/  # Cosign, SBOM, seccomp gates\n  pullrun-runtime/ # gRPC daemon\ncli/pullrun/      # Go CLI (cobra) — 30+ commands\ncri/pullrun-cri/  # Kubernetes CRI shim\ncontrol-plane/    # Multi-node orchestration stub: pullrun-controller + pullrun-agent (v1 WIP)\ncmd/pullrun-compose/ # Docker Compose-compatible CLI\ndeploy/           # K8s manifests, Prometheus rules, alerts\ndocs/             # Architecture, operations, policy, MCP\ntools/            # Standalone smoke-test workspaces (apple-virt-exec, firecracker-smoke, etc.)\n```\n\n| Document | What You'll Find |\n|---|---|\n|\n\n[docs/ARCHITECTURE.md](/pullrun/pullrun/blob/main/docs/ARCHITECTURE.md)[docs/OPERATIONS.md](/pullrun/pullrun/blob/main/docs/OPERATIONS.md)[docs/POLICY.md](/pullrun/pullrun/blob/main/docs/POLICY.md)[docs/WINDOWS.md](/pullrun/pullrun/blob/main/docs/WINDOWS.md)[docs/ALL_MCP.md](/pullrun/pullrun/blob/main/docs/ALL_MCP.md)[docs/cross-node-dag-sync.md](/pullrun/pullrun/blob/main/docs/cross-node-dag-sync.md)A technical report describing the architecture is available in [ /paper](/pullrun/pullrun/blob/main/paper/pullrun_paper.pdf) and archived on Zenodo:\n\n[https://doi.org/10.5281/zenodo.20679669](https://doi.org/10.5281/zenodo.20679669)\n\nApache 2.0 — see [LICENSE](/pullrun/pullrun/blob/main/LICENSE). Contributions subject to [CLA.md](/pullrun/pullrun/blob/main/CLA.md).\n\n**Built with Rust 🦀 and Go 🐹**", "url": "https://wpnews.pro/news/show-hn-pullrun-run-one-oci-image-as-a-container-firecracker-or-apple-vm", "canonical_source": "https://github.com/pullrun/pullrun", "published_at": "2026-07-14 17:19:20+00:00", "updated_at": "2026-07-14 17:48:27.027468+00:00", "lang": "en", "topics": ["developer-tools", "ai-infrastructure", "ai-agents"], "entities": ["Pullrun", "Firecracker", "Apple Silicon", "Kubernetes", "Docker", "MCP"], "alternates": {"html": "https://wpnews.pro/news/show-hn-pullrun-run-one-oci-image-as-a-container-firecracker-or-apple-vm", "markdown": "https://wpnews.pro/news/show-hn-pullrun-run-one-oci-image-as-a-container-firecracker-or-apple-vm.md", "text": "https://wpnews.pro/news/show-hn-pullrun-run-one-oci-image-as-a-container-firecracker-or-apple-vm.txt", "jsonld": "https://wpnews.pro/news/show-hn-pullrun-run-one-oci-image-as-a-container-firecracker-or-apple-vm.jsonld"}}