Skip to content

s-age/gazzo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gazzo

A macOS GUI for driving Claude Code agent sessions — and an experiment in handing Claude a local image generator.

gazzo is two things at once:

  1. A showcase of the concentric, message-driven architecture built on swift-kernelee: the same ring layout as the reference app ConcentricArch, deliberately exercising the two kernel primitives the reference app doesn't touch — .divert (the claude -p stream-json read loop is one self-diverting pipe shared by start and resume) and .fork (parallel session-file reads when browsing history).
  2. An experiment: what happens when you give Claude the ability to generate images? A local stable-diffusion.cpp engine (Metal-backed) is exposed to headless Claude sessions as an MCP tool, so an agent can decide to draw as naturally as it decides to read a file.

What it does

  • Browse native history — read-only view over ~/.claude/projects (project-scoped or all projects), with import into gazzo's own managed store under ~/.gazzo.
  • Start / resume agents — headless claude -p sessions over stream-json, with a live conversation view (thoughts, tool use, older-turn paging), stop, and rewind (edit an earlier prompt and branch the session from there).
  • Composer — model picker, working-directory picker, @ file mentions with search, per-session tool configuration, usage gauge.
  • Split panes — a splittable pane tree; every pane hosts its own session or a fresh composer.
  • Subagent watching — live transcripts of the subagents a session spawns.
  • Interactive tools for headless sessions — spawned sessions get ask_permission and ask_choice MCP tools, so a claude -p child can raise a native GUI prompt instead of failing silently.
  • Search, settings, artifacts — cross-catalog search, a Settings scene (models / tools / prompt / display / image generation), and an artifact pane that shows every generated image with QuickLook.

The image-generation experiment

The GazzoMCP stdio executable exposes three tools to the Claude sessions gazzo spawns:

Tool What it does
generate_image Generate a PNG from a prompt with the local engine; the image is returned to the model and saved under ~/.gazzo/images.
ask_permission Ask the gazzo user to allow or deny an action, via a GUI prompt.
ask_choice Ask the gazzo user to pick one of several options.

Design points:

  • The engine runs inside the MCP process, not the GUI: model weights stay resident between calls (with idle unload), a cross-process lock serializes generation, and everything keeps working with the GUI closed.
  • Models are managed from Settings — a FLUX.1-schnell preset can be downloaded in one click into ~/.gazzo/models; single-file gguf / safetensors SD-family models are picked up from the same directory.
  • The GUI never generates anything itself; it just watches ~/.gazzo/images and surfaces whatever the agent made in the artifact pane.

The interesting part is not the plumbing but the behavior: given the tool, Claude uses it — illustrating an explanation, iterating on a prompt after seeing its own output, or asking (via ask_choice) which of several compositions you prefer.

Architecture

Control is data: every cross-device call is a phantom-typed Symbol dispatched through a central Kernel, pipelines flow forward-only, and the UI observes a Redux-style shared buffer. The full write-up lives in ConcentricArch's README; the framework itself is swift-kernelee.

Sources/
├── Contract/         # shared vocabulary: ports (@callable), model, buffer states, errors
├── Compute/          # pure logic — jsonl / stream-json decoding, no I/O, no kernel
├── Infrastructure/   # I/O devices: history store (RO), session store (flock), claude CLI process
├── Circuit/          # orchestration sagas — rules, not logic (the divert stream loop lives here)
├── Driver/           # the single manifest binding ports to concrete devices
├── Presentation/     # SwiftUI — reads the buffer, dispatches, never writes
└── App/              # @main composition root — the only target that sees everything

Invariants worth calling out:

  • Only ids cross the bus. The claude Process and its pipes stay inside one Infrastructure actor; sagas pass Sendable handles.
  • ~/.claude/projects is read-only. gazzo never mutates native Claude Code history; its own state lives in ~/.gazzo, flock-guarded so the GUI and the MCP process can share it.
  • Streams are pipes, not recursion. The stream read loop is a pipe that keeps .diverting into itself — O(1) stack, one wiring diagram.

Debug tooling

Debug builds mount swift-kernelee's tooling: the kernel monitor (⌥⌘M — live message trace, buffer snapshots, time-travel) and the wiring graph (⌥⌘W — every pipeline rendered as a node graph). The repo also builds a kernel-introspect MCP server so coding agents can query the app's real wiring instead of grepping.

Build & run

Requires macOS 15+, Swift 6, and the claude CLI on your PATH.

swift build            # all targets, including GazzoMCP
.build/debug/gazzo     # run the app
swift test             # wiring exhaustiveness + decoder/fixture tests

Run the binary directly rather than swift run gazzo — the app expects its sibling GazzoMCP executable next to it (override with GAZZO_MCP_PATH).

Image generation needs one extra step (Apple Silicon recommended):

scripts/build-sdcpp.sh   # fetch + build stable-diffusion.cpp with the Metal backend
swift build              # now links the real engine

Without it everything else works; generate_image reports the engine as unavailable. Then download a model from Settings → Image Generation.

License

MIT © s-age

About

A macOS GUI for driving Claude Code agent sessions, built on swift-kernelee

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages