Menu Bar App

Command palette, window tiling, and session management

Updated August 14, 2026 Edit on GitHub →

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 install  # Register launch-at-login and launch now
lattices app update   # Download the latest release and relaunch
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.

Use lattices app install when you want the companion to start now and open automatically at login. It installs a user LaunchAgent in ~/Library/LaunchAgents; inspect it with lattices app login status and remove it with lattices app login disable.

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

Command Description
Launch project Create a new session and open terminal
Attach project Focus or open the running session
Sync project Reconcile session to declared config
Restart pane in project Kill and re-run a specific pane's command

Window commands

Available for running sessions:

Command Description
Go to project Focus the terminal window (switches Spaces if needed)
Tile project Left Snap window to left half
Tile project Right Snap window to right half
Maximize project Expand window to fill screen
Detach project Disconnect clients, keep session alive
Kill project Terminate the tmux session

Tab group commands

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

Command Description
Launch group Start the group session (all tabs)
Attach group Focus the running group session
Group: Tab Switch to a specific tab within a group
Kill group Group Terminate the group session

Layer commands

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

Command Description
Switch to Layer: label Focus and tile the layer's project windows

App commands

Command Description
Settings Open preferences (terminal, scan root)
Update Lattices Download the latest release and relaunch
Diagnostics View logs and debug info
Refresh Projects Re-scan for .lattices.json configs
Quit Lattices Exit the menu bar app

Overlay actors and HUDs

Persistent overlay actors can be hidden or restored with Hyper+B. Apps can publish a static hover dashboard by exposing:

.lattices/hud/manifest.json

Register and publish one:

lattices hud register .lattices/hud/manifest.json --publish

The manifest points to a local index.html, optional icon, app activation target, HUD dimensions, and optional app-owned sources metadata for logs or state files. Lattices hosts the actor and loads the dashboard through a transparent WKWebView; the app owns the renderer and writes its own logs in the places it already uses.

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 start 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)

Position Area
Left Left half
Right Right half
Top Left Top-left quarter
Top Right Top-right quarter
Bottom Left Bottom-left quarter
Bottom Right Bottom-right quarter
Maximize Full visible screen
Left Third Left third
Center Third Center third
Right Third Right third
Center 80% width, 80% height, centered (20% margin all sides)

Moving windows between monitors

Window movement is a right-click action wherever a window is listed. Both surfaces share one movement engine — the same canonical window.move / window.place semantics the CLI and daemon API use — so moving from the app, the CLI, or the API always behaves identically.

Right-click a window in either surface:

  • Desktop Inventory — window rows in the inventory list.
  • Studio — window shapes on the canvas and window rows in the sidebar (both the visible-windows list and the layer trees).

The menu offers, top to bottom:

  • Move to Next Monitor — one click; cycles deterministically through the display topology and wraps. The window keeps its normalized position and size on the target display's visible frame, clamped to fit.
  • Move to Monitor — submenu listing each display by name; the current display is checked and disabled.
  • Move & Place — single-window only; pick an exact display, then a canonical slot (maximize, center, halves, quarters, thirds).

Right-clicking a member of a multi-selection moves the whole selection ("Move 3 Windows to Next Monitor"); each window keeps its own normalized frame, so selections never collapse into one slot. Move & Place is omitted for multi-selections because a single slot would stack the windows. On a single-display machine the movement section disappears entirely.

Moves happen immediately — no dialog. A short flash reports the truthful outcome (moved, partially moved, unverified, or blocked on the Accessibility permission), and the list or canvas refreshes with the selection preserved.

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+D 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.

The provider-backed assistant can run in parallel, offering follow-up suggestions in the AI corner. Configure the provider and credentials in Settings > Voice. Workspace chat itself uses Scout and needs no separate key.

Settings

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

General

Setting Description
Terminal Which terminal to use (auto-detected from installed)
Mode learning or auto (see below)
Scan Root Directory to scan for .lattices.json configs (type a path or click Browse)
Updates Download the latest release and relaunch the app
Keyboard Remaps Optional Caps Lock layer that maps hold to Hyper and tap to Escape

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)

Keyboard Remaps

Keyboard remaps are enabled by default for the laptop-friendly rule:

  • hold Caps Lock -> Hyper (Control + Option + Shift + Command)
  • tap Caps Lock -> Escape

Rules live in ~/.lattices/keyboard-remaps.json, and the Settings toggle can turn the layer off. Keyboard remaps require Accessibility permission because they use a local event tap.

Companion

Shows the secure local bridge status, Mac bridge fingerprint, supported capability grants, and paired iPad or iPhone devices. The paired-device list shows each device fingerprint, last-seen time, and granted capabilities. You can refresh the list, revoke an individual device, or forget all trusted companions.

The local companion bridge and trackpad proxy are off by default for privacy. Turn the bridge on in Settings > Companion, or open lattices://companion/enable to enable the bridge and jump straight to Companion settings. lattices://companion/disable turns it off again.

The trackpad proxy toggle lives here. Paired devices still need the input.trackpad grant before they can send pointer events.

AI

Setting Default Description
Workspace chat Scout Uses the existing local Scout broker and keeps a persistent Scout ref; no separate Lattices chat credential
Voice provider OpenAI Optional voice-only HudsonAI provider for interpretation and speech services
Provider credentials Not set API-key storage in the macOS Keychain for the selected provider

Shows assistant readiness and the selected provider's authentication state.

Shortcuts

Shows keyboard shortcut reference. These are defaults; you can change them from Settings > Shortcuts.

Shortcut Action
Cmd+Shift+M Open command palette
Hyper+1 Workspace home
Hyper+L Studio / screen map
Hyper+2 Window bezel
Hyper+3 HUD
Ctrl+Cmd+M Hands-off mode
Hyper+Space Hyperspace window survey
Hyper+G In-place window tools
Hyper+H Window navigation hints
Hyper+5 Omni search
Hyper+6 Cheat sheet
Ctrl+Option+Space Command bar
Ctrl+Option+G 4x4 grid placement
Ctrl+Option+V Fill open 3x2 cell
Ctrl+Option+arrows Tile halves
Ctrl+Option+1/2/3 Tile thirds
Cmd+Option+1/2/3 Switch workspace layer
Ctrl+B D Detach from session
Ctrl+B X Kill current pane
Ctrl+B Left/Right Move between panes
Ctrl+B Z Zoom pane (toggle)
Ctrl+B [ Scroll mode

Hyper+L opens Studio; close it with Escape or q when the map owns keyboard focus, or use the window close button. Hyper+3 opens or dismisses the HUD and its miniature workspace map. The Scattered and Full HUD presets intentionally retain a faint, non-interactive ambient surface after dismissal. Neither UI is the read-only terminal lattices map command; see that page for exact side effects, full-teardown steps, and tab-stack cleanup.

Docs

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

Supported terminals

Terminal Launch Focus/Attach Tile by tag
Terminal.app yes yes yes
iTerm2 yes yes yes
Warp yes activate frontmost
Ghostty yes activate frontmost
Kitty yes activate frontmost
Alacritty yes activate frontmost

"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+G) 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:

Method Description
ocr.snapshot Current OCR results for all visible windows
ocr.search Full-text search across history (FTS5 syntax)
ocr.history Timeline of OCR results for a specific window
ocr.scan Trigger an immediate scan (bypasses timer)


// 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

Local loopback services

The menu bar process owns fixed loopback ports (see LatticesLocalEndpoints):

Service Port Endpoint
Agent API / daemon 9399 ws://127.0.0.1:9399
Voice runtime (Hudson Voice / Vox) 9398 ws://127.0.0.1:9398

Both start automatically when the app launches and stop when the app quits. Voice does not require an external voxd for normal operation.

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:



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.