Skip to main content
Blitz
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage
Edit page

History

Blitz began as a Go port of the Python Code Puppy, under that name. Both implementations lived in one repository (python/ and go/, at github.com/rmcguinness/code_puppy) until the Go version reached feature parity; on 2026-09-26 the Python implementation was removed, the Go code moved to the repository root, and the product was renamed Blitz. The last commit with both is tagged python-final in that former repository. This repository (github.com/retail-cortex/blitz) starts from a fresh history.

What follows is the comparison as it stood when the Python code was retired, kept as a record. Paths such as python/ and go/ refer to that layout, and features added afterwards aren’t in it.

Go measurements were taken on 2026-09-24 on Apple Silicon (arm64), macOS, warm cache. Python startup and memory figures come from the earlier benchmark and were not re-run. Source counts were measured today for both.


1. Performance and footprint

Metric Python Go Notes
Warm --version 0.960 s 0.020 s ~48× faster
Interactive start → exit (config, sandbox probe, engine) — 0.030 s
First run of a new binary 25.3 s (env init) 0.76 s Go’s first run is macOS scanning the new binary
Peak memory (RSS), --version 136.3 MB 37 MB Go was 16.5 MB before MCP, Anthropic, Markdown and line-editor dependencies
Distribution Python 3.11+ venv / pipx + wheels Single static binary (CGO_ENABLED=0) No runtime dependencies
Binary size n/a 56–61 MB per platform Grew from ~18 MB; see §4

2. Code size

Python (python/code_puppy) Go (go/cmd, go/pkg)
Source files (non-test) 271 91
Non-blank source lines 71,962 16,443
Test files 380 64
Non-blank test lines — 10,696
Direct dependencies 150+ (uv.lock) 27 (go.mod; OpenTelemetry added 8)

3. Capabilities

✅ supported · ➖ partial · ❌ not found

Area Python Go Go notes
Providers ✅ many (Gemini, OpenAI/Codex, Anthropic, Z.ai, Gemini Code Assist, round-robin, model catalogue) ➖ Gemini, Anthropic, OpenAI-compatible, Ollama No model picker/catalogue; fallback chain instead of round-robin
Agents ✅ Python classes + JSON ✅ Markdown + YAML frontmatter, embedded ./agents only with --trust-workspace; built-ins can’t be overridden
Sub-agent delegation ✅ ✅ Depth-limited invoke_agent
Skills ✅ ✅ Agent Skills plus Castor definitions; sandboxed Python scripts with per-requirements environments Scripts run in gVisor (Linux) or Seatbelt/bubblewrap, capped by [skills.policy]; they write only to an output directory
MCP servers ✅ ✅ stdio + HTTP Per-server approval, prefixes, per-agent scoping; stdio servers sandboxed
Hooks ✅ hook engine ✅ pre/post tool, prompt submit Exit-2 / JSON block protocol
Plugins ✅ plugin system ❌ MCP and hooks cover some of the same ground
Approvals ✅ confirmations ✅ diff preview; once / session / always Saved rules scoped per workspace; never override deny rules
Undo ✅ undo manager ✅ per-turn checkpoints, /undo, /diff Refuses to clobber later edits unless forced
Sessions ✅ autosave, browser, /dump_context / /load_context ✅ persistent, --resume / --continue, named snapshots (/session save, /session load <name>) Scoped per workspace; loading a snapshot starts a new session from it, as Python’s /load_context does
Compaction ✅ ✅ automatic + /compact [focus]
Token / cost tracking ✅ ✅ per turn and session Cache reads/writes priced; doctor flags unpriced models
Project instructions ✅ ✅ AGENTS.md / PUPPY.md
Web ➖ browser tooling ✅ web_fetch, web_search (Google via Gemini grounding, Brave, Tavily, SearXNG), /search web SSRF protection on every hop; no browser automation
Session names ✅ autosave names ✅ named after the first prompt, /rename, terminal title, resume command printed on exit From Antigravity’s /rename, /title and exit hint
Side questions ❌ ✅ /btw <question> Answered in a throwaway copy of the session; read-only; nothing kept (idea from Google’s Antigravity CLI)
/search ❌ ✅ /search web <terms> (top five links read by the agent), /search session <terms> (the transcript, including compacted turns) Search turns are read-only. Session search is literal and doesn’t cover tool output; Google search costs aren’t in /cost (see README, Search)
Images / attachments ✅ ✅ @image mentions, /attach, /paste, --image, view_image tool Gemini, Anthropic, OpenAI-compatible; images kept out of session files
i18n ✅ ✅ English, Spanish, Canadian French /locale; external JSON catalogs; model replies in the chosen language
Shell passthrough ✅ !cmd ✅ !cmd Runs as the user in the workspace; audited
Plan mode ➖ /plan (instructions only) ✅ /plan, --plan Enforced: only read-only tools run, including in sub-agents
Slash commands ✅ many ➖ No /cd (the workspace is the sandbox root; use -d), /truncate (use /compact), /tutorial
Per-model settings ✅ /model_settings: sampling, reasoning/thinking, retry strategy ➖ /model_settings, [model_settings."<model>"]: temperature, max_tokens, top_p, seed Reasoning/thinking settings not ported. Each fallback uses its own settings; settings a provider rejects are left out
Per-agent models ✅ /pin_model, /unpin ✅ /pin_model, /unpin, [agent_models], agent default_model Cross-provider; pinned sub-agents priced by their own model
Steering mid-turn ✅ Ctrl+T, injected before the next model call ✅ type or Ctrl+T; delivered with the next tool result macOS and Linux; late messages become the next prompt
Onboarding / menus ✅ wizard, interactive menus ➖ config init, doctor, line editor with completion
Scripting ➖ ✅ json / stream-json, --max-turns, exit codes
File sandbox ➖ access checks (fs_access.py) ✅ os.Root roots, read-only roots, blocked globs incl. symlinks
OS sandbox for shell ❌ not found in source ✅ Seatbelt (macOS), bubblewrap (Linux) Writes confined, secrets unreadable, network optional
Command policy ➖ ✅ parsed allow / deny / auto-approve Checks every sub-command, including wrappers and bash -c
Process lifetime ➖ backgrounding ✅ nothing outlives the CLI Guarded even against SIGKILL
Secret handling ✅ secret store backends ✅ env scrubbing, redacted audit log, owner-only files
Audit log ➖ ✅ JSONL of prompts, tools, approvals, hooks, undo
Diagnostic log ✅ error log (error_logging.py) ✅ slog JSONL, async writer, secrets masked Trace IDs on each line when telemetry is on
Resilience ✅ HTTP retry, MCP circuit breaker / health monitor / retry manager ✅ retries with backoff for every provider, stall timeouts, MCP restart + circuit breaker + timeouts, parallel tool cap No MCP health dashboard
Model fallback ✅ round-robin model ✅ ordered llm.fallback_models, across providers Failover (not load balancing): per-model circuit breaker, notices, priced by the answering model
Telemetry ✅ opt-in Logfire ✅ opt-in OpenTelemetry (OTLP/HTTP traces + logs) Turn → agent → model/tool spans; content stripped unless capture_content
Release PyPI ✅ GoReleaser: SBOMs, keyless cosign signatures, reproducible builds

4. Trade-offs in the Go version

  • Binary size: the MCP SDK, Anthropic SDK, Markdown renderer (glamour) and line editor took the binary from ~18 MB to ~58 MB. Startup is unaffected. If size matters, the Markdown renderer is the easiest to make optional with a build tag.
  • Breadth: Python still leads on providers, plugins and interactive menus. Go leads on sandboxing, auditability, scripting and distribution.
  • OS sandbox coverage: macOS and Linux only. Windows builds run without it and without the process guard.

5. Architecture

graph LR
    subgraph Go["Go (Google ADK)"]
        CLI["Cobra CLI + line editor"] --> Cfg["Trusted config (modenv)"]
        Cfg --> Engine["runtime.Engine"]
        Engine --> Runner["ADK runner + persistent sessions + compaction"]
        Runner --> Agents["llmagent tree (embedded Markdown personas)"]
        Agents --> Tools["tools.Registry"]
        Tools --> WS["Workspace sandbox (os.Root)"]
        Tools --> Exec["ExecEnv: OS sandbox, process guard, env scrub"]
        Tools --> MCP["MCP manager"]
        Engine --> Hooks["Approvals, hooks, audit"]
    end

Appendix: architectural shifts (from the first comparison, 2026-09-22)

1. Agent definitions

  • Python: Agent definitions were hardcoded Python classes (BaseAgent subclasses) mixed with string templates and dynamic class imports. Adding or customizing an agent required editing Python source files or dealing with loose JSON schemas.
  • Go: Personas are standardized as Markdown files with YAML frontmatter (internal/agents/builtin/*.md). They are baked directly into the binary at compile time via Go’s //go:embed, yet can also be dynamically dropped into ./agents/*.md or ~/.code_puppy/agents/*.md without recompilation.

2. Configuration and secrets

  • Python: Configuration relied on raw os.environ reads, extensive monkey patching, and complex credential stores (secret_store.py).
  • Go: Driven by retail-cortex/modenv (internal/config/config.go), enabling hierarchical environment cascading (.env.toml -> .env.<runtime>.toml -> .env.local.toml) and native decryption of cloud://, pks://, and simple:// secret URIs.

3. Tool execution and schemas

  • Python: Used pydantic-ai with heavy runtime introspection and multiple monkey patches (pydantic_patches.py was 26 KB).
  • Go: Uses Google ADK functiontool.New(), which automatically and safely infers compliant JSON Schemas from strongly-typed Go structs at initialization via github.com/google/jsonschema-go.

4. Concurrency and streaming

  • Python: Constrained by the Global Interpreter Lock (GIL) and asyncio thread dispatching. Long shell commands or background subprocesses required intricate coordination to avoid blocking the event loop.
  • Go: Leverages native goroutines, channel synchronization, and Go 1.23+ iter.Seq2[*session.Event, error] streaming, giving fluid TUI rendering with near-zero overhead.

Packaging and portability

  • Python:
    • Requires a pre-installed Python 3.11+ interpreter.
    • Relies on platform-specific C/Rust extensions (cryptography, pydantic-core, pillow), which frequently fail to compile on minimal containers, Termux/Android, or hardened CI runners.
    • Installation involves downloading hundreds of megabytes of wheel archives.
  • Go:
    • Compiles to a single static binary (CGO_ENABLED=0).
    • Zero dependencies: runs out of the box in scratch Docker containers, Alpine Linux, or bare metal.