Concepts
Core ideas, glossary, and architecture of lattices
Glossary
| Term | Definition |
|---|---|
| Command Palette | The menu bar app’s primary interface (Cmd+Shift+M). Searchable list of actions: launch, tile, sync, restart, settings. |
| Window Tiling | Snap terminal windows to preset screen positions (halves, quarters, thirds, maximize, center). Works from the CLI (lattices tile) or the command palette. |
| Agent API | WebSocket server (ws://127.0.0.1:9399) inside the menu bar app. Exposes 35+ RPC methods and 5 real-time events for programmatic control. See the API reference. |
| Agent | Any program that calls the agent API autonomously — an AI coding agent, a shell script, a CI pipeline, or a custom tool. |
| Session | A persistent tmux workspace that lives in the background. Survives terminal crashes, disconnects, and closing your laptop. One session per project. Requires tmux. |
| Pane | A single terminal view inside a session. A typical setup has two panes side by side — Claude Code on the left, dev server on the right. Requires tmux. |
| Attach / Detach | Attaching connects your terminal to an existing session. Detaching disconnects but keeps the session alive — your dev server keeps running, Claude keeps thinking. Requires tmux. |
| Sync / Reconcile | lattices sync brings a running session back in line with its declared config — recreates missing panes, re-applies layout, restores labels, re-runs commands in idle panes. Requires tmux. |
| Ensure / Prefill | Two modes for restoring exited commands on reattach. Ensure auto-reruns the command. Prefill types it but waits for you to press Enter. Set via .lattices.json. Requires tmux. |
| tmux | Terminal multiplexer (optional). Provides persistent sessions, pane layouts, and command restoration. Install with brew install tmux if you want session management. |
How it works
- You create a
.lattices.jsonfile in your project root (or runlattices init) - The menu bar app discovers the project and adds it to the command palette
- You can tile windows, switch layers, search via OCR, and use the agent API
- With tmux installed,
latticesalso creates persistent terminal sessions:- Each pane gets its command (claude, dev server, tests, etc.)
- The session persists in the background until you kill it
- You can attach/detach from any terminal at any time
- If
ensureis enabled, exited commands auto-restart on reattach
Architecture
- The menu bar app is the core. It provides the command palette,
window tiling, OCR, project discovery, and the agent API (a WebSocket
server on
ws://127.0.0.1:9399). It works with or without tmux. - The CLI handles tiling, OCR queries, and (when tmux is installed)
session management via
tmuxshell commands. - Agents and scripts connect to the agent API over WebSocket. They can do everything the app and CLI can do: discover projects, tile windows, switch layers, read on-screen text, and subscribe to real-time events. See the Agent API reference.
- When tmux is installed, the app and CLI can also launch, sync, and manage persistent terminal sessions. All layers share the same session naming convention so they always agree on which session belongs to which project.
Session naming
A session name is <basename>-<hash>, where:
basenameis the project directory name (non-alphanumeric chars replaced with-)hashis the first 6 hex chars of the SHA-256 of the full absolute path
This guarantees unique session names even if two projects share the
same directory name (e.g. ~/work/app and ~/personal/app).
Both the CLI (Node.js crypto.createHash) and the app (Swift
CryptoKit.SHA256) produce identical hashes.
Window discovery via title tags
When lattices creates a tmux session, it sets the tmux option:
set-titles-string "[lattices:<session-name>] #{pane_title}"
This embeds a [lattices:name] tag in the terminal window title. The
menu bar app uses this tag to find windows via three fallback paths:
- CGWindowList (needs Screen Recording permission) — fastest, reads window names from the window server
- Accessibility API (needs Accessibility permission) — queries AXUIElement window titles for the terminal app
- AppleScript — iterates Terminal.app or iTerm2 windows by name
Space switching via SkyLight
The menu bar app can switch macOS Spaces to reach a session’s window.
It uses private SkyLight framework APIs loaded at runtime via dlopen:
CGSMainConnectionID— get the connection to the window serverCGSGetActiveSpace— current Space IDCGSCopyManagedDisplaySpaces— enumerate all Spaces per displaySLSCopySpacesForWindows— find which Space a window is onSLSManagedDisplaySetCurrentSpace— switch a display to a Space
This is the same approach used by Loop and other macOS window managers.
Ensure/prefill restoration (requires tmux)
When you run lattices (no arguments) and a session already exists:
- lattices checks the
ensure/prefillflag in.lattices.json - For each pane, it queries
#{pane_current_command}via tmux - If the pane is running a shell (bash, zsh, fish, sh, dash) — meaning
the original command has exited — it either:
- ensure: sends the command + Enter (auto-restart)
- prefill: sends the command without Enter (manual restart)
- Then it attaches to the session as normal
Agent control
The agent API gives agents the same control as a human using the
menu bar app. An agent can list projects and windows, launch sessions,
tile windows to screen positions, subscribe to real-time events
(windows.changed, tmux.changed, layer.switched), and sync
sessions back to their declared config.
A typical orchestrator sets up a multi-project workspace in a few
daemonCall() invocations. See the Agent API reference
for the full method list and code examples.
Key shortcuts (inside tmux)
These work when you’re inside a tmux session:
| Shortcut | Action |
|---|---|
| Ctrl+B D | Detach from session |
| Ctrl+B X | Kill current pane |
| Ctrl+B Left | Move to left pane |
| Ctrl+B Right | Move to right pane |
| Ctrl+B Up | Move to pane above |
| Ctrl+B Down | Move to pane below |
| Ctrl+B Z | Zoom pane (toggle) |
| Ctrl+B [ | Scroll mode (q exits) |
The prefix Ctrl+B means: hold Control, press B, release both,
then press the next key.