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
| Data | Owner | Where |
|---|---|---|
| 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) | herdr | session.snapshot |
| Split tree and ratios | herdr | snapshot.layouts[] |
| Terminal content and PTY | herdr | terminal session frames |
Agent kind, status, completion_seq, session (agent_session) | herdr | agents[], panes[] |
| A machine's sessions | herdr | herdr session list --json, run on the machine |
| The sessions each machine listed last, for the new-window view | app, per device | memory, 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, id | app, disk | UserDefaults, 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 pane | app, disk | app 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 device | memory |
| Seen values, program icons, git state of each space, a divider's ratio while it is dragged | app, per device | memory |
| A browser pane's page and its back and forward list | the pane's machine | $HOME/.local/state/ovvi/<session>/browser/<iid>.json (State on the machine) |
| Approved browser origins, the newest 200 per machine | app, disk, per device | UserDefaults, a list under browserApprovals.<machine id> (When a page loads by itself) |
| Remote browser cards on This Mac's network, the newest 200 per machine | app, disk, per device | UserDefaults, a list of <session>/<iid> under browserViaMac.<machine id> (This Mac's network) |
| Browser cookies, storage and cache, one store per machine | WebKit, disk, per device | ~/Library/WebKit/<bundle id>/WebsiteDataStore/<machine id>/ (Profiles) |
| The choosers of new panes (New pane); browser cards' web views, by terminal id | app, per device | memory |
| 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 picture | app, per device | memory |
| 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 records | app, 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 logs | app, disk, This Mac | ~/Library/Logs/Ovvi/plugins/<id>.log (Errors and logs) |
| The files a plugin card shows and saves | the pane's machine | the 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 TUI | app, per device | memory, on the session's HostStore (Chat view) |
| A chat's side files: hooks and state lines, OpenCode's password, pi-ovvi, OpenCode's plugin | the pane's machine | ~/.cache/ovvi/ (Side files); files untouched for 30 days go |
The ovvi command and its mailbox | each 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 server | the agent | its own files and server on the pane's machine; Archived Sessions reads them (Archived Sessions) |
| An agent session's title | the agent; the app keeps the last one read per pane in memory | the agent's own files on the pane's machine (Session titles) |
| ControlMaster sockets | app | ~/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
pagesagain, in order, and showspage, each with itsselection. 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
-sessionon 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 onlyovvi-*sessions. - With none left, the first page is the session named by the
-sessionlaunch 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.
-sessionis read from the argument domain only.