Ovvi

Data: app vs herdr

What the app stores and what herdr owns

Where things live

One rule decides where each new thing goes (D57):

  • Anything that takes space in the layout is a multiplexer pane.
  • Transient UI (the palette, popovers, hover, chips) lives in app memory only.
  • Per-device settings live in app storage.

The installed app is Ovvi.app, dev.ovvi.app, which only make install and make dmg build; any other Release build (make app, a measure) is dev.ovvi.app.release, with defaults and saved windows of its own, claiming ovvi-release://. A Debug build (make run, the UI tests, CI) is Ovvi Dev.app, dev.ovvi.app.debug, so it has its own defaults, saved windows, notifications, login item and browser data, and it claims the ovvi-dev:// scheme, not ovvi://. Its folders on This Mac are ~/.config/ovvi-dev and ~/Library/Logs/Ovvi Dev/plugins. It never reads or writes the installed app's. What it shares are the files that belong to the sessions and panes both apps show: ~/.cache/ovvi and ~/.local/state/ovvi on each machine, and on This Mac the herdr server jobs with their logs (~/Library/Logs/Ovvi/<session>.log) and ~/Library/Caches/ovvi, whose SSH sockets are per app.

scripts/reset-app-data.sh [--dry-run] [bundle id] deletes one build's data on This Mac for a fresh start (the installed app's by default), while that build is not running. Run it without sudo. macOS keeps an app's saved windows in ~/Library/Daemon Containers, which needs Full Disk Access for the terminal; the first launch after a reset closes them anyway (Welcome). When macOS refuses to delete a folder (some WebKit caches), the script goes on, lists what it kept and exits with 1. For a Debug build it also deletes ~/.config/ovvi-dev and ~/Library/Logs/Ovvi Dev. For the installed app, and only while no Ovvi build runs, it also deletes ~/.config/ovvi, ~/Library/Logs/Ovvi, ~/Library/Caches/ovvi, ~/.cache/ovvi and ~/.local/state/ovvi, which other builds share. It never touches herdr's sessions or the agents' files.

Every piece of data

DataOwnerWhere
Spaces, tabs, panes, order, labels (a browser pane's kind, iid and typed address: The label; a plugin pane's plugin id, iid and place: Labels and instance ids)herdrsession.snapshot
Split tree and ratiosherdrsnapshot.layouts[]
Terminal content and PTYherdrterminal session frames
Agent kind, status, completion_seq, session (agent_session)herdragents[], panes[]
A machine's sessionsherdrherdr session list --json, run on the machine
The sessions each machine listed last, for the new-window viewapp, per devicememory, and ~/Library/Caches/<bundle id>/sessions.json by SSH target (This Mac by its id); memory only with -session, -defaultSession or -machines. Removing a machine drops its entry
Remote machines: name, SSH target, icon, idapp, diskUserDefaults, JSON under machines
Settings: appearance, interface style, text size, Focus Follows Mouse, Balance splits automatically (balanceSplits), what a new pane opens (newPaneOpens), the notification switches, the terminal's font, cursor, Option key and copy on select, the first view of new agents and each agent's extra arguments (agentArguments.<command>), whether the sidebar shows Archived Sessions (showArchivedSessions), the Sort Spaces a session starts with (spaceOrder) (Settings) and whether the welcome is done (welcomeDone, Welcome); a floating pane's window frame, per paneapp, diskapp storage (UserDefaults)
Per window: the machine's id (machine), the names of its open pages (pages), the page in view (page), each page's selected space and tabs and its floating panes with their Stay on Top (selection, one JSON string), whether it shows the new-window list (picking), sidebar shown or hidden (sidebar) and sidebar width (sidebarWidth)app, disk@SceneStorage, one set per window
Per page of a window: the selected space, the tab per space, the keyboard card per tab, the zoomed card. Per open session: its HostStore, made on first use. Per session: which window controls it (Control between windows).app, per devicememory
Seen values, program icons, git state of each space, a divider's ratio while it is draggedapp, per devicememory
A browser pane's page and its back and forward listthe pane's machine$HOME/.local/state/ovvi/<session>/browser/<iid>.json (State on the machine)
Approved browser origins, the newest 200 per machineapp, disk, per deviceUserDefaults, a list under browserApprovals.<machine id> (When a page loads by itself)
Remote browser cards on This Mac's network, the newest 200 per machineapp, disk, per deviceUserDefaults, a list of <session>/<iid> under browserViaMac.<machine id> (This Mac's network)
Browser cookies, storage and cache, one store per machineWebKit, disk, per device~/Library/WebKit/<bundle id>/WebsiteDataStore/<machine id>/ (Profiles)
The choosers of new panes (New pane); browser cards' web views, by terminal idapp, per devicememory
Plugin cards, by terminal id: the page and its unsaved edits, the file's hash at the last read or save, Back and Forward, the header's values and the plugin's state as last set, the tree's filter, a diff's Viewed marks (The plugin API); a dropped web card's and a chat's last pictureapp, per devicememory
A plugin card's state and header values (Git's commit message, the diff's Side by Side, Word Wrap and file list; File Explorer's Show Hidden Files, File's Word Wrap, and Markdown's mode, lock and fold)the pane's machine$HOME/.local/state/ovvi/<session>/<plugin>/<iid>.json (State)
Plugin packages, their list, the confirmed plugins and the defaults' install recordsapp, disk, This Mac~/.config/ovvi/plugins/, settings.json (packages, hideInNewPane with the plugins and agents that New Pane leaves out, and plugins with each plugin's settings that differ from their defaults: Plugin settings in settings.json; keys with the keyboard shortcuts the user changed: Keyboard Shortcuts), trust.json, plugins/.defaults.json (Packages and installs)
The sidebar's folded spaces and open Archived Sessions (foldsAndShelves, a line each), Archived Sessions' agent (archivedAgent), each session's pinned spaces, Sort Spaces and Show Only Pinned Spaces (spaceChoices, a line each: machine, session, then pinned ‹space›, sorted ‹order› or only pinned) and the time of each agent's last state change with its state_change_seq (agentMarks.‹machine› ‹session›)app, disk, This Mac~/Library/Preferences/‹bundle id›.sidebar._Users_‹you›_.config_ovvi.plist, a defaults domain named after the build and the config folder, so a test's -configFolder, a Debug build and a Release build each keep their own
Plugin logsapp, disk, This Mac~/Library/Logs/Ovvi/plugins/<id>.log (Errors and logs)
The files a plugin card shows and savesthe pane's machinethe files themselves; a save killed halfway leaves a .ovvi-save.* beside the file (Edits, saves and reloads)
A chat per agent pane, by terminal id: its history, marks (how far each file was read), draft, messages on their way, and Chat or TUIapp, per devicememory, on the session's HostStore (Chat view)
A chat's side files: hooks and state lines, OpenCode's password, pi-ovvi, OpenCode's pluginthe pane's machine~/.cache/ovvi/ (Side files); files untouched for 30 days go
The ovvi command and its mailboxeach machine where Ovvi opened a session~/.cache/ovvi/bin/ovvi and ~/.cache/ovvi/rpc/ (Agent control); mailbox files older than 60 minutes go on connect
An agent's transcript, session record and serverthe agentits own files and server on the pane's machine; Archived Sessions reads them (Archived Sessions)
An agent session's titlethe agent; the app keeps the last one read per pane in memorythe agent's own files on the pane's machine (Session titles)
ControlMaster socketsapp~/Library/Caches/ovvi/, while running

Nothing the app saves describes herdr's state

The only exception is each window's restore state: the names of its pages. A page whose session was deleted is skipped. A fresh install on a new Mac rebuilds every space, tab and pane from herdr.

Which pages a window opens

  • A restored window opens the pages in pages again, in order, and shows page, each with its selection. A session that is not running starts, as its Start does (a restart of the Mac stops every session; a remote machine connects first); a name the machine no longer lists is skipped. macOS hands a restored window its scene storage a moment after the window first shows, so the window waits for it (at most 1 s) before it opens a page.
  • With -session on the command line, every window restores only that session (a run against a throwaway session never reopens another), with its saved selection, and a new window (⌘N) lists only ovvi-* sessions.
  • With none left, the first page is the session named by the -session launch argument (a test's), else none: the window shows the new-window view. On This Mac the app starts -session's session when it is stopped (a launchd job, D47). It never opens a session by itself: only a restored window starts the sessions it had.
  • A new window opened for a machine (the machine menu, a machine just added) is on that machine and opens its default. File ▸ New Window (⌘N) opens no page.
  • No setting names a session to open. -session is read from the argument domain only.

On this page