Menu Bar App

Command palette, window tiling, and session management

The lattices menu bar app sits in your menu bar and controls your workspace from there.

Installation

lattices app          # Build (or download) and launch
lattices app build    # Rebuild from source
lattices app restart  # Quit, rebuild, relaunch
lattices app quit     # Stop the app

The first run builds from source if Swift is available, otherwise downloads a pre-built binary from GitHub releases.

Command palette

Press Cmd+Shift+M from anywhere to open the command palette. It’s a searchable list of every action the app can perform, with fuzzy matching on titles and subtitles.

Project commands

CommandDescription
Launch projectCreate a new session and open terminal
Attach projectFocus or open the running session
Sync projectReconcile session to declared config
Restart pane in projectKill and re-run a specific pane’s command

Window commands

Available for running sessions:

CommandDescription
Go to projectFocus the terminal window (switches Spaces if needed)
Tile project LeftSnap window to left half
Tile project RightSnap window to right half
Maximize projectExpand window to fill screen
Detach projectDisconnect clients, keep session alive
Kill projectTerminate the tmux session

Tab group commands

Available when groups are configured in ~/.lattices/workspace.json (see Tab Groups):

CommandDescription
Launch groupStart the group session (all tabs)
Attach groupFocus the running group session
Group: TabSwitch to a specific tab within a group
Kill group GroupTerminate the group session

Layer commands

Available when layers are configured in ~/.lattices/workspace.json (see Layers):

CommandDescription
Switch to Layer: labelFocus and tile the layer’s project windows

App commands

CommandDescription
SettingsOpen preferences (terminal, scan root)
DiagnosticsView logs and debug info
Refresh ProjectsRe-scan for .lattices.json configs
Quit LatticesExit the menu bar app

Project discovery

The app scans a configurable root directory (up to 3 levels deep) for .lattices.json files. It skips .git/ and node_modules/.

Auto-detection for the scan root checks these paths in order: ~/dev, ~/Developer, ~/projects, ~/src.

For each project found, the app reads:

  • Pane names and commands from .lattices.json
  • Dev command and package manager from package.json
  • Running status by checking tmux has-session

Session management

The app calls the lattices CLI for session operations. Launch runs lattices in the project directory, Sync runs lattices sync to reconcile panes, and Restart runs lattices restart <pane> to kill and re-run a pane’s process. Detach and Kill call tmux detach-client and tmux kill-session directly.

Window tiling

The app can tile terminal windows to preset screen positions via the command palette. It finds windows by their [lattices:session-name] title tag.

For Terminal.app and iTerm2, tiling uses AppleScript to set window bounds by matching the title tag. For other terminals, it tiles the frontmost window.

Tile positions (app)

PositionArea
LeftLeft half
RightRight half
Top LeftTop-left quarter
Top RightTop-right quarter
Bottom LeftBottom-left quarter
Bottom RightBottom-right quarter
MaximizeFull visible screen
Left ThirdLeft third
Center ThirdCenter third
Right ThirdRight third
Center70% width, 80% height, centered

Space navigation

“Go to” commands can switch macOS Spaces to reach a window on a different desktop. The app uses a three-path fallback:

  1. CGWindowList (needs Screen Recording) — looks up the window by title tag, finds its Space via SkyLight, switches to it, then raises the window
  2. Accessibility API (needs Accessibility) — finds the window via AXUIElement, raises it, and activates the app
  3. AppleScript — iterates windows by name for Terminal/iTerm2, or bare-activates for other terminals

When a window is found and focused, the app flashes a green border highlight around it for ~1 second so you can spot it immediately.

Grant Screen Recording and Accessibility permissions in System Settings > Privacy & Security for all three paths to work.

Voice commands

See Voice Commands for the full guide.

Press Hyper+3 to open the voice command window. Hold Option to speak, release to stop. Lattices transcribes via Vox, matches to an intent, and executes. Built-in commands: find, show, open, tile, kill, scan.

A Claude Haiku advisor runs in parallel, offering follow-up suggestions in the AI corner. Configure the model and budget in Settings > AI.

Settings

Open via the command palette or the gear icon in the main view. The settings window has four tabs:

General

SettingDescription
TerminalWhich terminal to use (auto-detected from installed)
Modelearning or auto (see below)
Scan RootDirectory to scan for .lattices.json configs (type a path or click Browse)

Mode controls how the app handles session interaction:

  • Learning — shows tmux keybinding hints when you detach (helpful while getting used to tmux)
  • Auto — detaches sessions automatically (fewer prompts)

AI

SettingDefaultDescription
Claude CLI pathAuto-detectedPath to claude binary
Advisor modelHaikuhaiku (fast) or sonnet (smarter)
Budget per session$0.50Max spend per Claude CLI invocation

Shows live session stats: context usage %, session cost, and learned pattern count.

Shortcuts

Shows keyboard shortcut reference:

ShortcutAction
Cmd+Shift+MOpen command palette
Hyper+1Screen map
Hyper+2Window bezel
Hyper+3Voice commands
Hyper+4Desktop inventory
Hyper+5Omni search
Hyper+6Cheat sheet
Cmd+Option+1/2/3Switch workspace layer
Ctrl+B DDetach from session
Ctrl+B XKill current pane
Ctrl+B Left/RightMove between panes
Ctrl+B ZZoom pane (toggle)
Ctrl+B [Scroll mode

Docs

Embedded quick reference with glossary, “how it works” steps, and links to open the full config.md and concepts.md docs.

Supported terminals

TerminalLaunchFocus/AttachTile by tag
Terminal.appyesyesyes
iTerm2yesyesyes
Warpyesactivatefrontmost
Ghosttyyesactivatefrontmost
Kittyyesactivatefrontmost
Alacrittyyesactivatefrontmost

“yes” means full AppleScript-based window matching by title tag. “activate” means the app is brought to front but a specific window can’t be targeted. “frontmost” means tiling applies to whatever window is in front.

Screen OCR

See Screen OCR for full details on configuration, scanning, search, and agent usage.

The app reads text from visible windows using Apple’s Vision framework and stores results in a local SQLite database with FTS5 full-text search. Agents can use this to “see” what’s on screen.

How it works

  1. Every 60 seconds, the app captures the top visible windows as images
  2. A SHA256 hash detects whether the window content has changed
  3. Changed windows are processed through VNRecognizeTextRequest (fast mode)
  4. Results are stored in ~/.lattices/ocr.db with full-text indexing
  5. Entries older than 3 days are automatically purged

Desktop Inventory integration

The Desktop Inventory view (Hyper+4) uses OCR to make windows searchable by their content — not just by title or app name. When you type a search query, windows matching by OCR content show contextual snippets.

API access

Agents can query OCR data through four API methods:

MethodDescription
ocr.snapshotCurrent OCR results for all visible windows
ocr.searchFull-text search across history (FTS5 syntax)
ocr.historyTimeline of OCR results for a specific window
ocr.scanTrigger an immediate scan (bypasses timer)
import { daemonCall } from '@lattices/cli'

// Find windows showing error messages
const errors = await daemonCall('ocr.search', { query: 'error OR failed' })

// Read what's currently on screen
const snapshot = await daemonCall('ocr.snapshot')

More in the Agent API reference.

Requirements

  • Screen Recording permission — required to capture window images
  • Granted via System Settings > Privacy & Security > Screen Recording

Agent API server

The menu bar app runs a WebSocket server on ws://127.0.0.1:9399. It starts automatically when the app launches and stops when the app quits.

Checking status

lattices daemon status

Or programmatically:

import { isDaemonRunning, daemonCall } from '@lattices/cli'

if (await isDaemonRunning()) {
  const status = await daemonCall('daemon.status')
  console.log(status) // { uptime, clientCount, version, windowCount, tmuxSessionCount }
}

What it provides

  • 35+ RPC methods for reading windows, sessions, projects, spaces, layers, processes, terminals, and OCR. Also launching/killing sessions, tiling windows, switching layers, and managing tab groups.
  • 5 real-time events (windows.changed, tmux.changed, processes.changed, layer.switched, ocr.scanComplete) broadcast to all connected clients.
  • Window tracking that monitors the desktop window list and correlates windows to lattices sessions via title tags.
  • Space awareness, so it knows which macOS Space each window is on.

Security

The server binds to localhost only (127.0.0.1:9399). Not accessible from the network. No authentication, so any local process can connect. This is intentional — it’s for local automation, not remote access.

Full method list in the Agent API reference.

Diagnostics

The diagnostics panel shows a timestamped log of window navigation attempts, including which path succeeded or failed. Useful for debugging Screen Recording / Accessibility permission issues.