AI Coding Guides Deep Dives
Zig 0.15 • 3 MB Binary • 6 Backends • 16 Tools • MIT

Wintermolt: The Everything-Agent in 3 MB

A single native binary with zero runtime that ships 6 AI backends, 16 built-in tools, cron scheduling, Tailscale mesh networking, camera vision, browser automation, MCP bidirectional support, chat bridges to 4 platforms, and a macOS menu bar app.

(Alright, ad over. Back to the serious technical analysis.)

What is Wintermolt?

Wintermolt is an autonomous AI agent CLI written entirely in Zig 0.15. It compiles to a single 3 MB native binary with only two external dependencies — libcurl for HTTPS and sqlite3 for persistence — both pre-installed on macOS and most Linux distributions. Unlike every other agent in this set, it has zero runtime: no Node.js, no Python, no Electron, no virtual environments.

The project ships ~18,400 lines of Zig across 51 source files, plus two prebuilt Zig static libraries (libforagent.a and libforlearn.a) from sibling projects. The codebase is organized into clean modules: agent core, API clients, tools, MCP, chat/web/menubar bridges, and a canvas renderer.

📌

Key differentiator

Wintermolt is the only agent in this entire set that cross-compiles to any platform Zig supports — ARM boards like Jetson and Raspberry Pi included — with a single build command: zig build -Dtarget=aarch64-linux-gnu.

Architecture overview

Module Files Lines What it does
src/main.zig 1 1,202 Entry point, REPL, 7 execution modes
src/agent/ 13 5,226 Core agent: loop, tools, config, history, storage, scheduler, RAG, skills, subagents, router
src/api/ 7 2,460 Multi-backend AI clients (Ollama, Claude, OpenAI, DeepSeek, Qwen, Gemini)
src/tools/ 14 4,521 16+ built-in tools: bash, file I/O, grep, glob, HTTP, search, camera, browser, Tailscale, canvas
src/mcp/ 4 1,001 MCP client + server (bidirectional)
src/chat/bridge.zig 1 278 Chat platform IPC (Discord, Telegram, Slack, WhatsApp)
src/web/bridge.zig 1 1,062 Web UI WebSocket bridge with streaming
src/menubar/bridge.zig 1 314 macOS native menu bar Swift sidecar IPC
src/gateway/bridge.zig 1 213 OpenAI-compatible API gateway

The agentic loop

The core loop lives in src/agent/loop.zig (~646 lines). The AgentLoop struct runs a prompt → tools → observe → repeat cycle with up to 25 tool iterations per turn:

  1. User message added to history with approximate token counting (approx_tokens += text.len / 3)
  2. RAG indexing — fire-and-forget rag.indexMessage() for Pinecone semantic memory
  3. Tool relevance filtering — keyword-matches user text against trigger lists to select extended tools (tools.getRelevantDefinitions())
  4. API call — streams to the primary backend with live terminal output via callback
  5. Response parsing: .end_turn, .max_tokens, .stop_sequence, .tool_use, or .unknown
  6. Tool executionexecuteTools() iterates over tool_use content blocks
  7. Results fed back as user-role messages (required by the API pattern)
  8. Context overflowhistory.emergencyCompact() (drops to 40% budget) and retries

The sendToBackend method implements automatic fallback: if the primary backend fails, it tries Ollama first (local, no rate limits), then OpenAI.

📌

Key file

src/agent/loop.zigAgentLoop struct, processInput() at line 182, sendToBackend() at line 294

6 AI backends — one binary

All backends share a unified protocol.Message / protocol.Response wire type in src/api/protocol.zig (~281 lines). The dispatch happens in loop.zig's switchBackend:

Backend Protocol Streaming Auth Default Model
Ollama NDJSON Yes, line-by-line None (local) qwen3:0.6b
Claude SSE (Anthropic) Yes, event-driven X-Api-Key claude-sonnet-4-20250514
OpenAI SSE (OpenAI) Yes Bearer token gpt-4o-mini
DeepSeek SSE (OpenAI-compatible) Yes Bearer deepseek-chat
Qwen SSE (OpenAI-compatible) Yes Bearer qwen-plus
Gemini SSE (OpenAI-compatible) Yes Bearer gemini-2.0-flash

The DeepSeekClient struct is effectively a universal OpenAI-compatible client — it's reused for OpenAI, DeepSeek, Qwen, Gemini, and the custom forAI endpoint by simply overriding the api_url field.

Three hand-written streaming parsers handle the wire formats: sse.zig (~461 lines) for Anthropic SSE, openai_sse.zig (~287 lines) for OpenAI SSE, and ndjson.zig (~250 lines) for Ollama NDJSON. Each is an incremental character-by-character parser with no streaming library dependency.

The 16 built-in tools

Tool dispatch lives in src/agent/tools.zig (~717 lines) with a three-layer architecture:

Tool What it does
bashShell execution with safety checks (pattern-matches against rm -rf /, dd if=, etc.)
file_readRead any file (text or images via multimodal)
file_writeCreate or overwrite files
file_editSurgical find-and-replace editing
globRecursive file search by pattern
grepContent search with regex
http_requestHTTP GET/POST/PUT/DELETE to any URL
web_searchDuckDuckGo search (no API key)
camera_captureCamera snapshots, screenshots, OAK-D depth
image_processFormat conversion (BMP, PNG via sips/ffmpeg)
browser_controlFull Chrome automation via DevTools Protocol (~895 lines)
memory_searchSemantic search over conversation history (Pinecone RAG)
scheduleCron jobs — schedule recurring commands
tailscaleMesh VPN — query peers, devices, connectivity
canvas_updateA2UI — render rich UI surfaces in terminal or web
harness_createCLI-Anything — generate agent wrappers for any software

The bash tool includes automatic API key redaction — it scans for 12 secret patterns (sk-ant-, sk-proj-, xoxb-, ghp_, AIza, etc.) before returning output to the AI context.

Cron scheduler

src/agent/scheduler.zig (~756 lines) implements a SQLite-persisted job scheduler with three schedule types:

The tickScheduler() is called from the REPL loop on every iteration. It queries due jobs, executes each via the bash tool, and updates last_run/next_run. Jobs are auto-disabled after max_retries consecutive failures.

No other agent in this set has a built-in cron scheduler.

MCP: both client and server

Wintermolt is one of only two agents in this set that implements MCP bidirectionally (Crush is the other).

As server (src/mcp/server.zig, ~214 lines): Exposes 20+ Wintermolt tools via JSON-RPC 2.0 over stdio. Supports initialize, tools/list, tools/call, resources/list, prompts/list, ping.

As client (src/mcp/client.zig, ~421 lines): Loads external MCP servers from ~/.wintermolt/mcp.json, spawns each as a child process with stdin/stdout pipes, runs the 3-step MCP handshake, and prefixes all discovered tool names with "servername__" (e.g., filesystem__read_file).

Chat bridges

All bridges follow the same sidecar IPC pattern: Zig spawns a child process (TypeScript/Swift), communicates via JSON lines over stdin/stdout pipes. No sockets, no HTTP servers, no shared memory — clean process boundaries.

Bridge Sidecar What it does
Chat TypeScript Discord, Telegram, Slack, WhatsApp — multi-platform bot
Web TypeScript WebSocket UI at localhost:3000 with token-by-token streaming
Menu Bar Swift macOS native NSStatusBar app (~270 lines, no Electron)
Gateway TypeScript Exposes OpenAI-compatible /v1/chat/completions API

The chat bridge uses a 7-tier priority binding system in src/agent/router.zig (~585 lines): peerparent_peerguild_roleguildteamaccountchannel.

Memory and RAG

Tier 1 — SQLite (src/agent/storage.zig, ~793 lines): ~/.wintermolt/history.db with conversations and messages tables. All public methods are designed for catch-and-ignore — storage failures never break the agentic loop.

Tier 2 — Pinecone RAG (src/agent/rag.zig, ~577 lines): Vector database for semantic search with auto-embedding via Pinecone's integrated inference. Every user and assistant message is indexed fire-and-forget. Namespaced by user session (web mode) or domain (knowledge bases).

Skills system

Two-layer skill system:

The project ships 79 skill definitions across 11 domains: Zortran Core, Fortran Kernels, Zig Systems, Physics/Simulation, AI/ML Kernels, Cybersecurity, Synthetic Data, Agent Architecture, Audio/Music, 3D/VFX, and Engineering.

Unique engineering decisions

No @cImport pattern

All C interop uses explicit extern fn declarations (~12 curl functions, ~15 sqlite functions). No header file parsing, no platform-specific header dependency. Keeps the binary small and cross-compilation clean.

Hand-written streaming parsers

Three SSE/NDJSON parsers, each ~250–460 lines of incremental character-by-character processing. No streaming library dependency. Each handles escape sequences, nested objects, partial chunks across curl callbacks.

Docker sandbox mode

Optional sandboxed bash via Docker: read-only CWD mount, no network, memory/CPU limits, timeout enforcement. Falls back to host execution if Docker is unavailable.

Subagent system

Parent-child spawning with depth limiting (max depth 3, max concurrent 4). Each subagent gets its own AgentLoop with independent history and config. Callback-based design avoids circular dependencies.

Camera + vision built-in

Captures from cameras (imagesnap on macOS, ffmpeg on Linux, OAK-D depth). Object detection via local LLaVA model. Base64-encoded images flow through the agentic loop as vision content blocks.

Browser automation

Full Chrome DevTools Protocol integration (~895 lines). List tabs, navigate, click elements, type text, evaluate JS, screenshot, and snapshot page content.

7 execution modes

Mode Command Description
REPLwintermoltInteractive terminal session
Single-shotwintermolt -e "prompt"Run one prompt, print result, exit
Setupwintermolt --setupInteractive API key + model wizard
Chatwintermolt --chatMulti-platform messaging bot
Webwintermolt --webBrowser UI at localhost:3000
Menu Barwintermolt --menubarmacOS native status bar app
MCP Serverwintermolt --mcp-serverExpose tools via JSON-RPC 2.0

Strengths

Tradeoffs

⚠️

Where Wintermolt gives things up

  • TypeScript sidecars — while the core is pure Zig, the chat, web, and gateway bridges require TypeScript runtimes. The core binary doesn't need them, but full functionality does.
  • Prebuilt librarieslibforagent.a and libforlearn.a are distributed as prebuilt Zig archives, not built from source in-tree.
  • Bash safety is pattern-based — unlike Neovate's quote-aware pipeline parser or Claude's tree-sitter AST analysis, Wintermolt's bash guards use regex pattern matching.
  • Less polished than Claude Code — the feature surface is enormous, but the UX polish of productized agents like Claude Code or Crush is not quite there yet.
  • Harder to audit — 18,400 lines of Zig is compact for what it does, but the breadth of features (cron, Tailscale, camera, browser, chat, MCP, RAG) means there's a lot to verify.

Key files to read

📌

Core runtime

src/agent/loop.zig (agentic loop, 646 lines), src/agent/tools.zig (tool dispatch, 717 lines), src/agent/config.zig (multi-backend config, 461 lines), src/agent/storage.zig (SQLite persistence, 793 lines)

API clients

src/api/ollama.zig (NDJSON streaming, 484 lines), src/api/deepseek.zig (universal OpenAI-compatible, 373 lines), src/api/sse.zig (Anthropic SSE parser, 461 lines)

Unique features

src/agent/scheduler.zig (cron jobs, 756 lines), src/tools/browser.zig (CDP automation, 895 lines), src/tools/camera.zig (vision, 482 lines), src/tools/tailscale.zig (mesh VPN, 160 lines), src/agent/rag.zig (Pinecone RAG, 577 lines)

MCP and bridges

src/mcp/client.zig (MCP client, 421 lines), src/mcp/server.zig (MCP server, 214 lines), src/web/bridge.zig (WebSocket bridge, 1,062 lines), src/menubar/bridge.zig (macOS menu bar, 314 lines)

Verdict

Best designed, if you value a portable binary

Wintermolt is the only agent here that can be cross-compiled to ARM boards, embedded devices, or any Zig target. The no-runtime philosophy is carried through every module — explicit extern fn declarations, hand-written parsers, and JSON-lines IPC for all sidecars.

Most ambitious feature set

No other agent in this set combines a coding CLI, cron scheduler, Tailscale mesh query, camera vision, browser automation, MCP bidirectional, multi-platform chat bot, macOS menu bar app, and an OpenAI-compatible gateway — all in one 3 MB binary.