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

Where to pick up

Written 2026-09-24 at commit 7e211697 on main; updated 2026-09-25, 2026-09-26 and 2026-09-27. On 2026-09-26 the code moved to github.com/retail-cortex/blitz with a fresh history (initial commit 53f8c53): the commit hashes below, and the python-final and v0.1.0 tags, exist only in the former repository, rmcguinness/code_puppy. Read this first when resuming. the roadmap has the detail behind each finished item, and Manual verification has the checks that need a person.

Resume here (2026-10-01)

CI: green on bcc06f7 (run 36848932128: Linux, macOS, reproducible), after the fixes below; before them, green on 8c31870. The run on 904a46a failed on a data race the race detector caught once in TestRemoteTaskRequests (a published task event pointed at a variable then reused, pkg/engine/runtime/tasks.go); fixed in 8017779. The run on that failed on macOS: a test hung because the REPL’s prompt-time Ctrl+C watcher, stopped as a turn started, could still take the Ctrl+C meant for the turn (cancelOnSignal now waits for its watcher to go); fixed in the commit after this line. Check the latest with gh run list --branch main --workflow ci --limit 3 and gh run view <id> --log-failed. Since 2026-09-30:

  • Coverage went from 76.5% to 94.9% of the Go code on Linux, with the floor at 94%, and the page’s TypeScript is measured (17% of lines and branches; floor in vite.config.ts). The work found and fixed about twenty bugs, logged in the commits and, for the security ones, in the security log.
  • Tests pass without an OS sandbox (configtest.RunTools, BLITZ_SANDBOX_SHELL=auto in .bazelrc), with test sizes that fit and the big Go suites in shards.
  • Security: the sandbox is required on Linux, blitz security fix-apparmor and the desktop’s Allow bubblewrap lift AppArmor’s restriction for bwrap alone, ADC is shared with commands only on request, the ant sign-in is hidden, and a sandbox escape through the ADC copies’ sweep is fixed (SEC-2026-08).
  • Desktop: the .deb depends on bubblewrap; install the blitz command from Settings, make a folder a git repository from Changes, a readable “/” menu, a white tray bolt, no maximum window size.

Tested by the owner (2026-10-01): the Linux sandbox checks (a, b and c in their note: blitz security fix-apparmor, the desktop’s notice and Allow bubblewrap, against a real AppArmor) on an Ubuntu instance.

Next, in order:

  1. The same on a Chromebook (ChromeOS’s Linux container, Debian): whether bubblewrap runs there at all (blitz security), and the .deb install (manual verification, The sandbox required on Linux and Fixing it; Chromebooks).
  2. Pin the Linux jobs to ubuntu-24.04 before GitHub moves ubuntu-latest to Ubuntu 26 (2026-10-19).
  3. The security log’s open items, SEC-2026-O1 (fix-apparmor piping the profile to root) first.
  4. Tests for the page’s components (its coverage is 17%), and Go branch coverage (gobco), suggested but not set up.
  5. Smaller: blitz workers runs <unknown> says “hasn’t run yet” rather than that there’s no such worker; TestEngineCapsParallelToolCalls now compares the unlimited run with the one-at-a-time run instead of a fixed 1.1 s, which failed on a loaded machine.

Picking this up on another machine. Everything is in the repository; nothing lives only on the machine it was done on.

  • Clone git@github.com:retail-cortex/blitz.git, then follow building: Bazelisk as bazel, and on Linux git bubblewrap. On Ubuntu 24.04, blitz security fix-apparmor (or the sysctl there, for the gVisor tests too) lets the sandbox tests run; without it they skip, and everything else passes (BLITZ_SANDBOX_SHELL=auto in .bazelrc).
  • gh auth login to read CI’s logs (gh run view <id> --log-failed): the API won’t give them anonymously.
  • Commits since 2026-09-30 are unsigned (the owner’s GPG key couldn’t be unlocked from the agent’s shell); commit.gpgsign is unchanged.
  • A local .deb is version 0.0.0: install it with sudo apt install --reinstall ./blitz-desktop_amd64.deb.
  • Before a commit: tools/check_format.sh, and tools/coverage.sh --config=race as CI runs it (floor 94%); the page has its own floor (bazel test //apps/desktop/web:coverage). Docs-only commits carry [skip ci], and go before the code commit when pushed together, since CI runs on the last commit only.
  • Security problems go in the security log.

Earlier: 2026-09-27, end of day

The first release candidate, v0.1.0-rc.1, is ready to tag but blocked on GitHub billing.

  • main is at 1930d13. Both CI build jobs passed on it (tests, coverage 78.6% on Linux against the 78% floor, every check), and the Linux and macOS archive checksums are identical. Only the reproducible job (run 36369532092) failed, twice, without starting: “recent account payments have failed or your spending limit needs to be increased”. Every workflow is blocked until the organization’s Settings › Billing & plans is fixed.
  • Checked locally with a throwaway tag: the stamp reads 0.1.0-rc.1 in blitz, blitzd and Info.plist; each archive holds blitz, blitzd, blz, README, LICENSE, NOTICE and THIRD_PARTY_NOTICES; sign_macos.sh builds the unsigned disk image (95 MB).
  • Tag signing is off for this repository only (git config --local tag.gpgSign false; the owner’s global setting signs, and needs a pinentry prompt).

Next, in order:

  1. Once billing is fixed: re-run the failed job (gh run rerun 36369532092 --failed), then git tag -a v0.1.0-rc.1 -m "Blitz 0.1.0-rc.1" 1930d13 && git push origin v0.1.0-rc.1. The release workflow makes a draft release: five archives with SBOMs, signed checksums.txt, the macOS disk image (ad hoc signed: no Apple Developer ID yet; the owner has applied), and .debs for x86-64 and ARM, each with a cosign bundle.
  2. Check the draft against the README: cosign verify-blob and sha256sum -c, archive contents, versions. The owner tests the Linux binary; send them the download-and-verify commands and what to try (--version, license, doctor, a short session).
  3. Pin the Linux jobs to ubuntu-24.04: GitHub moves ubuntu-latest to Ubuntu 26 from 2026-10-19 (WebKitGTK 4.1, user namespaces for the sandbox).
  4. sign_macos.sh: hdiutil create is deprecated in favour of diskutil image.
  5. The owner may enable private vulnerability reporting (Settings › Security); docs/CONTRIBUTING.md already points reporters there.
  6. proto-gen-md-diagrams (the owner maintains it): upstream fixes for escaping comments, skipping the license header and optional front matter would let docs/api_pages.sh go. The owner is checking the repository’s state first.
  7. Coverage: see Resume here (2026-10-01) above.

State

Roadmap items 1–22 are done and committed, and item 23 (the desktop app) is in progress; each has its own commit:

Commit Change
383ab847 Per-file locks for parallel edits; refuse to write a file that changed during approval
ae509e39 Earlier work: Anthropic provider, workspace-scoped sessions, /compact, MCP prefixes/agents, saved forged tools, web search, pricing, i18n, images
bd0a0bb5 slog diagnostic log + opt-in OpenTelemetry (content stripped), chained turn traces
04bd68dc post_tool hooks on an ordered background worker
b13ba38d Retries for every provider, stall timeouts, MCP stdio restart + circuit breaker, parallel tool cap
72acd1c4 Steering a running turn (type or Ctrl+T)
4d1f31c5 !cmd, enforced /plan and --plan, /tools, /show
042263dd Ordered model fallback across providers; Ollama base-URL fix
7a06b7a6 Default Gemini model → gemini-3.8-flash
7e211697 Per-agent models ([agent_models], /pin_model, /unpin)
b652f263 Per-model settings ([model_settings], /model_settings)
36c2758b Removed the committed editor swap file; *.swp ignored
957c08b9 Named session snapshots (/session save, /session load <name>, --resume=<name>)
9eeab5e6 Google search via Gemini grounding; /search web, /search session
155d595b, a5f34180, e2f02959 Item 22: Castor skill definitions and [skills.policy]; the gVisor/OS script sandbox; environments, run_skill_script, /envs
(the commit removing python/) Go-only repository: Python removed (tag python-final), Go at the root, workflows ci.yml and release.yml, Apache 2.0 with NOTICE, planning docs in .agents/
1370b80f Side questions (/btw)
56a870a4, dce9baa9, c239dfb8, f318498d Dependabot and a macOS release note; pinned release tools, GOTOOLCHAIN=local, a cross-host reproducibility check; project-layout with code in internal/; actions upgraded (checkout v7, setup-go v7, Node 24)
8ce5c642 ROADMAP item 23, phase 2: engine.Open and engine.Workspace replace cmd’s buildEnv
75630f18 Phase 3: Workspace.Run and Steer, one turn lifecycle for the REPL and one-shot runs
e657a7bd Phase 4, agents and models: typed operations for /agents, /agent, /model, /pin_model, /unpin, /model_settings, /set
ef91966a Phase 4, sessions: /session list/new/load/save, /resume, /rename
8bbe0b94 Phase 4, checkpoints and approvals: /undo, /checkpoints, /diff, /approvals
5bf56f4c Phase 4, skills, envs, MCP and tools: /skills, /envs, /mcp, /tools
4ddbb783 Phase 4, the rest: /cost, /context, /compact, /memory, /locale, /sandbox, /attach, /paste, /search; tui.App reduced to the workspace and terminal state
900c1b96 ROADMAP item 23 replanned: one service per user, CLI attaches, Connect + buf
3fb181cd, af7cad97 Phase 5: api.Event instead of ADK events for every client; the prompt is recorded before steering can start
42aaf41b Phase 5b: per-workspace state, no dependence on the working directory
f9a6e7bf ROADMAP item 24 planned: workers
d8c08d91 Phase 6: the service API as protos, buf, generated Go and Connect code
2e4cb2c0, a6ed23d6, a926faa6 Phase 7: apps/service/internal/server, approvals over the stream, blitz serve, the workspace lock
26e261cd, d969c75f, d5562753 Phase 8: api.Backend, pkg/client, the CLI attaching to the service, --local
31531764, (the commit adding pkg/engine/workers.go) Item 24a–b: worker definitions, schedules, permissions (ApprovalRequest.Targets); enabling pinned to the hash, [workers.policy]
(the commit adding pkg/engine/session/title_test.go) Session names from the first prompt, /rename, terminal title, resume hint on exit

bazel test --config=race //... passes (vet and staticcheck run in every compile), and so does bazel run //tools:check_deps.

Dated reminders

  • Gemini 3.8 Flash price (handled). The introductory $0.75 / $3.75 / $0.075 per 1M tokens ends on 2026-12-31. config.PriceChanges switches gemini-3.8-flash to $1.50 / $7.50 / $0.15 from 2027-01-01 (UTC) when the configuration loads, so no code change is due then; a long-running blitz serve picks it up at its next restart. Before a release in 2027, check https://ai.google.dev/gemini-api/docs/pricing and fold the change into DefaultPricing.

Open work, in suggested order

Priority (2026-09-26, owner’s decision): close feature gaps before adding new features. The gaps are specified as requirements in specs/spec_backlog_026.md (Blitz’s own) and specs/spec_parity_027.md (against Claude Code, Antigravity CLI and Antigravity; §14 gives the order; §12 records the five conflicts with earlier decisions, decided below). Specs 001–025 describe current behaviour; move requirements into them as gaps close.

  1. Release readiness is done (roadmap item 27): licensing, comments, specs, this site, the README, contributing, owners, and coverage in CI. Coverage’s weakest packages (see coverage) are where tests are most needed; raise tools/coverage/floor.txt as it rises.

  2. ROADMAP item 23 is done in a first version: the per-user service (blitzd, service install), the proto API, the CLI attaching to it, workers (item 24), and the desktop app (now the Electron app, bazel build //:mac-app). Next, in order: run MANUAL_VERIFICATION sections 36–37 (the service, workers and the app need a person, and some checks are 💲); then the known gap of workers’ edits joining /undo (ROADMAP 24c). An attached CLI’s process list and !cmd audit are done (2026-09-29, CL-04). The app’s slash commands, Markdown, images, notifications, translation and release job are done (2026-09-27, branch desktop-polish); its signing is item 3.

  3. Manual verification (needs a person). Nothing in MANUAL_VERIFICATION.md has been run yet. It covers real providers (💲 = paid calls), terminal behavior, the macOS and Linux sandboxes, MCP, steering, fallback and pinning. Record results in the file; any failure becomes the next task.

  4. Name the release archives’ macOS binaries (spec_monorepo_028 §5): they have their own UUIDs but are signed a.out by Go’s linker; build them on the macOS runner and codesign --identifier, or sign with rcodesign on Linux, keeping the archives reproducible.

  5. Sign and notarize the desktop app (needs an Apple Developer Program membership). The release job (release.yml desktop, spec_release_025 REL-20–26) signs ad hoc and warns until these repository secrets exist (Settings › Secrets and variables › Actions):

    • MACOS_CERTIFICATE: a Developer ID Application certificate with its private key, exported from Keychain Access as .p12, then base64 -i cert.p12 | pbcopy;
    • MACOS_CERTIFICATE_PASSWORD: the .p12’s export password;
    • DESKTOP_SIGN_IDENTITY: the certificate’s name, Developer ID Application: <name> (<TEAMID>) (security find-identity -v -p codesigning);
    • NOTARY_KEY: an App Store Connect API key (Users and Access › Integrations › Team Keys, role Developer), the .p8 file’s text;
    • NOTARY_KEY_ID and NOTARY_ISSUER: that key’s ID and the issuer ID shown on the same page.

    To try it locally first: with the certificate in your keychain and the .p8 on disk, bazel build --config=release //apps/electron/packaging:Blitz_arm64.app (or Blitz_x64.app), then DESKTOP_SIGN_IDENTITY=… NOTARY_KEY_PATH=… NOTARY_KEY_ID=… NOTARY_ISSUER=… apps/electron/packaging/sign_macos.sh "$(bazel cquery --config=release --output=files //apps/electron/packaging:Blitz_arm64.app)" <version> Blitz.dmg. Then tag a release and run MANUAL_VERIFICATION §18’s desktop checks. Neither the signed path nor the release job has run yet; if gh release upload can’t find the draft release by its tag, pass the release’s ID instead.

    The CLI archives stay unnotarized (the release job could sign their macOS binaries with the same certificate and key, and notarize them in a zip); until then the release notes (.github/release-footer.md) and the README explain clearing the quarantine flag. Dependabot (.github/dependabot.yml) keeps the pinned action SHAs current. ~/.gnupg/gpg-agent.conf now points at GPG Suite’s pinentry-mac; the next tag will show whether tag signing works.

  6. Skill scripts, follow-ups (ROADMAP item 22 is done: Castor definitions, [skills.policy], the gVisor/OS ScriptBox, environments, run_skill_script, /envs):

    • TypeScript scripts;
    • scripts that write the workspace directly, with snapshots;
    • requires-python with uv-managed interpreters;
    • storage_uri and resources;
    • running the opt-in real-install tests in CI (BLITZ_PYENV_TESTS=1);
    • adding a network field to Castor’s proto, instead of custom_hints.network.
  7. Optional: reasoning settings per model. Python’s /model_settings also sets reasoning_effort, extended thinking and budgets. The Go wrapper (pkg/engine/runtime/settings.go) is where they’d go, mapped to genai ThinkingConfig, which each adapter translates differently.

  8. Optional, from the Antigravity review (ROADMAP, “Antigravity CLI review”): /copy (last reply to the clipboard, with OSC 52 over SSH), --add-dir <path> at startup, /grill-me (the agent interviews you before coding), and /fork [n] (branch a new session from an earlier turn).

Decisions already made (don’t redo without a reason)

  • The product is Blitz (2026-09-26), renamed from Code Puppy: binary blitz (with blz as a symlink), module github.com/retail-cortex/blitz, proto package blitz.v1, ~/.blitz, .blitz/ in workspaces, BLITZ.md, BLITZ_* variables, the [blitz] config section, the default agent blitz, Blitz.app (dev.blitz.desktop), the login item dev.blitz.service / blitz.service. A clean break: nothing under the old name is read or migrated. NOTICE and docs/content/about/history.md keep the attribution to Mike Pfaffenberger’s Code Puppy. The repository moved to retail-cortex/blitz (2026-09-26); the remote, the README’s and .goreleaser.yaml’s cosign identity now name it, and releases made before the move verify against the former repository’s identity. The tone pass is done (no mascot; status marks ✓ ✗ ! ↳ only; a one-line banner and agent › prompt; persona-free agent prompts; qa-kitten is qa; puppy_name/owner_name and the legacy puppy.cfg loader removed). A deliberate proto break is declared with a Breaking-API: <why> line in the commit message, which CI’s buf breaking step honours. blitz exec <prompt> is the explicit one-shot form (flags shared with the root command; no prompt is a usage error), and the README opens with the Blitz lore, with claims kept to what exists. Not done: a blz refactor command (to be designed), and the Sam Walton line, left out pending a source (his famous bird dog was Ol’ Roy).

  • No shared event bus. Considered for steering and dropped: audit, hooks and traces are fed from engine callbacks, and steering didn’t need a bus.

  • Steering rides on tool results (message_from_user), because ADK model callbacks can’t add session events (Session() returns nil there).

  • Each turn is its own trace root. Turns are linked to the previous turn and tagged gen_ai.conversation.id; the previous turn’s traceparent is kept in session metadata as last_turn. A session is never one long trace.

  • Content is never exported by default. The ADK puts tool arguments and results on every execute_tool span, so pkg/observability filters them before export. OTel providers are built here, not with adk/telemetry.New, which adds its own unfiltered exporter.

  • The Python implementation is gone (2026-09-26): the Go code is the repository root, and python-final tags the last commit with Python (in the former repository’s history). Don’t reintroduce a second implementation.

  • Not ported from Python: /truncate (use /compact) and /tutorial. Reasons are in ROADMAP item 14. (/cd was also left out then; it is now planned, see below.)

  • Parity decisions (2026-09-26, owner), replacing earlier rejections; details in specs/spec_parity_027.md §12:

    • bypass permission mode instead of --dangerously-skip-permissions: entered only with --permission-mode bypass, and it refuses to run unless the OS sandbox is active; deny rules and blocked paths still apply. blitz.auto_approve becomes this mode. Prompt fatigue is mainly addressed by accept-edits and a reviewing-model auto mode.
    • /cd is adopted: it closes the workspace and reopens the target through engine.Open (lock, roots, sandbox, memory, MCP, project config) and moves the session; nothing is patched mid-session.
    • Project configuration is adopted in layers: .blitz/settings.toml may tighten without asking; anything that runs code or loosens policy loads only after trust pinned to the workspace path and a content hash; credentials, endpoints, telemetry targets and sandbox loosening are never read from a project. This replaces “configuration only from trusted locations” as the rule for project files; user configuration still loads only from trusted locations.
    • The REPL stays line-based, with inline arrow-key pickers; full-screen views go in the desktop app.
    • /boost and agent teams are deferred until background sub-agents and worktrees exist.
  • fallback_models switches only before any output and never on cancellation. Breakers are asked just before each attempt (regression tests guard this).

  • Model settings are applied per built model, not per agent. newProviderModel wraps every model, so each member of a fallback chain uses its own [model_settings]. Applying them in newLLMAgent would give fallbacks the primary’s settings.

  • Snapshots are never continued in place. Loading one (by name or ID, /session load, /resume, --resume=) copies it to a new session, as Python’s /load_context does, and --continue skips snapshots.

  • No Anthropic server-side web search (dropped by the user). No Google Custom Search JSON API: it shuts down on 2027-01-01, so google means Gemini grounding.

  • /search web pre-approves exactly the URLs it hands over, for that turn only (tools.WithFetchGrants); everything else the agent fetches still asks.

  • Telemetry and OTel need one provider per process: the ADK binds its tracer to the first global provider.

  • Bazel, in a monorepo (2026-09-27, owner’s decision; reverses “No Bazel” of 2026-09-26). The engine had bled into the front ends; the repository is now three apps over shared packages (apps/, pkg/, pkg/engine/), and Bazel 9.2 builds and tests everything: Go, the desktop page, the protos (generated, never committed) and the packages. The service is its own program, blitzd. Make, GoReleaser and the tools module are gone; tools come through Bazel, and host tools are a last resort (bazel run //tools:tidy for dependencies). The Linux desktop build uses the system’s GTK through pkg-config, deliberately not hermetic. specs/spec_monorepo_028.md.

  • Superseded 2026-09-27 by the monorepo decision above. Layout follows golang-standards/project-layout (2026-09-26): apps/cli (CLI/TUI, pure Go) and apps/desktop (Wails, cgo, built on each OS); code in internal/, pkg/ only for deliberately public APIs; frontend in apps/desktop/web, packaging in build/. Slash-command logic moves from tui to a UI-agnostic pkg/engine shared by both UIs.

  • One engine service per user (2026-09-26, replacing “a process per tab”): the service (blitz serve; since 2026-09-27 its own program, blitzd) hosts every workspace over Connect on a Unix socket; the CLI attaches when it’s running, else runs in-process. Scheduled workers (item 24) run in it. See ROADMAP item 23.

  • The module path is github.com/retail-cortex/blitz, matching the repository.

Conventions, layout and commands: Development.