Architecture
Blitz is a monorepo of its programs (the CLI, the service, the tray, the Electron desktop app and the VS Code extension) over shared Go packages, in one Go module (github.com/retail-cortex/blitz) built with Bazel. Spec: monorepo.
flowchart TB
CLI["<b>apps/cli</b><br/>blitz and its REPL"]
DESK["<b>apps/electron · apps/desktop/web</b><br/>Electron app and React page"]
SVC["<b>apps/service</b><br/>blitzd"]
CONTRACT["<b>The contract</b><br/>pkg/api · pkg/client · pkg/socket · proto/blitz/v1"]
ENGINE["<b>The engine</b><br/>pkg/engine · runtime · tools · session · …"]
SHARED["<b>Shared</b><br/>pkg/config · secrets · i18n · images · observability · redact · legal · loginitem · textutil"]
CLI --> CONTRACT
DESK --> CONTRACT
CLI -. "--local" .-> ENGINE
SVC --> ENGINE
SVC --> CONTRACT
ENGINE --> CONTRACT
CONTRACT --> SHARED
ENGINE --> SHARED
- Apps (
apps/) are the programs. Code private to one app lives underapps/<app>/internal/. - The contract is what front ends program against:
pkg/apidefinesBackend, the interface a front end drives, with the values, events and typed errors that cross it.proto/blitz/v1is the same contract on the wire. - The engine (
pkg/engineand below) is Blitz without a user interface.engine.Openbuilds aWorkspacethat implementsapi.Backendin process. None of it prints. - Shared packages (
pkg/) are used by every layer: settings, catalogs, images, logs and telemetry. See shared packages.
- Apps depend on
pkg/, never on each other. (Tests may run the service throughapps/service/servicetest.) - Front ends (the REPL, the desktop app),
pkg/api,pkg/clientandpkg/socketnever reach the engine. Only the service and the CLI’s--localmode link it.
The rules are enforced twice: the engine’s Bazel visibility lists only who may use it, and bazel run //tools:check_deps (in CI) queries the build graph and fails on any library that breaks them.
A front end holds an api.Backend and doesn’t know which it has:
| Implementation | Where the engine runs | Used by |
|---|---|---|
*engine.Workspace |
In the same process | The service; the CLI with --local |
*client.Remote |
In the service, over the socket | The CLI when the service runs |
The desktop app is a third client: its page calls the service’s Connect API directly, through the socket proxy of its host (blitz-tray --serve, pkg/pagehost), with a generated TypeScript client.
This is why the CLI behaves the same attached or local, and why a session started in the terminal can continue in the desktop app.
- The engine: a workspace, a turn, and the ADK.
- The service API: the protos, streaming turns, approvals across processes; and the API reference, generated from them.
- Sandboxing and trust: the layers between the model and your machine.
- The build: Bazel, generated code, static analysis, reproducible releases.