OVARI TERMINALv0.2.0

/ Docs

Documentation

From installing it to the trust boundary. The same ground the repository README and CLAUDE.md cover, in an order you can read start to finish.

Installing

The short path is an installer from the Download page: an NSIS installer (.exe) on Windows, a .dmg on macOS, an .AppImage on Linux.

Signing: releases are not code-signed yet, so Windows SmartScreen and macOS Gatekeeper may warn you. The SHA-256 of every installer is on the download page — it is worth checking.

From source

git clone <repo> ovari-terminal
cd ovari-terminal
npm install        # postinstall builds node-pty
npm run dev

npm install runs electron-builder install-app-deps in its postinstall step, because node-pty is native. Node 25 or newer is required — the tests rely on Node stripping TypeScript itself.

First run

On an empty window there is one thing to do: open a terminal. The New terminal dialog asks for three things — a working directory, a startup command and environment variables — and only the folder is required.

  • Quick shell — no dialog, a plain shell in your home directory.
  • Claude / Codex — an agent in the focused pane’s folder, with the model settings baked in.
  • Update CLIs — runs claude update; codex update in a new terminal so the output stays readable.

On the second launch it offers to restore the previous session. With the checkbox on, commands starting with claude get --continue appended, so the conversations pick up where you left them.

Restore does not bring back environment values, because those are never written to disk. Add them again where a session needs them.

Sessions and presets

One pane is one process. The working directory decides what the agent can see, the startup command decides what runs in the shell, and the environment variables exist only inside that PTY.

Presets

The chips at the top of the dialog are saved sessions, shown as command @ folder. "Save as preset" stores the current form and a chip fills it back in. Up to 32 presets are kept.

When a process exits

The exit code appears under the pane header with a Restart button. The restart happens in place: the pane keeps its id and its position, but the scrollback is gone.

Panes, tabs, layouts

Split right and Split down open the same dialog and split the focused pane. Drag the divider between panes to set the ratio.

  • ZoomCtrl + Shift + F or the ⤢ in the pane header. The split underneath stays alive, just covered.
  • TabsCtrl + Shift + N opens a workspace, Ctrl + PageUp and Ctrl + PageDown step through them. Hidden tabs keep running.
  • Saved layouts — the Layouts menu saves the current tab as a template and opens it in a new tab. A template always starts fresh.
  • Font sizeCtrl + wheel, or Ctrl + + / -.
Layout, tab names, pane names, presets, font size and the alert toggle live in workspace.json — under %APPDATA%/ovari-terminal on Windows.

Drag and drop

One drop can carry both folders and files: folders become terminals, files become typed paths.

  • A folder on the window — a terminal opens in it. If the dialog is open, it fills the working-directory field instead.
  • A file on a pane — its path is typed at the prompt, without a newline, quoted when it contains whitespace. Nothing is executed.
  • An image out of a browser — that drag carries bytes and no path. The app writes it to a temp file and inserts that path, which is the one form an AI CLI can open.
  • A pasted screenshotCtrl + V or Ctrl + Shift + V takes the same route: a temp file, then its path.
  • A pane header on another pane — dropped in the middle they swap, dropped on the outer quarter of an edge it splits in there.
  • A pane header on a tab — the pane moves into that workspace while it runs.
  • A tab on another tab — reorders the strip.

The 📎 in a pane header is the same insertion without a drag: it opens a native file picker and the chosen paths go in the same way.

Dropped and pasted images land in %TEMP%/ovari-terminal-media with a timestamp in front of the name, and are cleaned up on the next launch a day later — an image is a hand-off, not storage.
Ctrl + Shift + Z undoes the last move, twenty deep. Undo is deliberately limited to rearrangements: once a terminal has been opened or closed the trail is dropped, because no undo can bring a killed shell back.

AI CLIs

The Claude and Codex buttons start an agent in the focused pane’s folder with the flags baked in. The models are pinned in two constants in App.tsx — edit those two lines when a stronger model ships.

CLAUDE_COMMAND = "claude --model 'opus[1m]' --effort ultracode"
CODEX_COMMAND  = "codex -m gpt-5.6-sol -c model_reasoning_effort='high'"

Remote control

The button types /remote-control into every pane running Claude Code. Two signals decide which panes those are: the startup command begins with claude, or the usage poll matched the pane to a Claude transcript. The command and the Enter are two separate writes about 120 ms apart — arriving as one chunk, a CLI input box can read the trailing carriage return as part of a pasted block instead of a submit.

Broadcast

While it is on, every keystroke goes to all panes of the active tab. The workspace gets a border you cannot miss, because typing into six agents by accident is expensive. Opting out is simple: put the session on another tab.

Token and cost meters

The meter does not estimate. It reads the CLIs’ own append-only transcripts — ~/.claude/projects/**/*.jsonl and ~/.codex/sessions/**/*.jsonl — in a single directory walk covering every pane, every 15 seconds.

  • A pane matches a transcript when the working directory matches and the file was written after that pane opened.
  • A byte offset is kept per file, so each poll parses only what was appended since the last one.
  • Claude cost comes from a price table; a model with no entry reports tokens rather than a guessed number.

The pane header shows a short figure ($0.42 or 128k), the top bar shows a per-source breakdown, and with more than one pane a Σ total in which every session is counted once.

The glass interface

The blur is drawn by the operating system, not by the browser engine. From Windows 11 22H2 the window asks for an acrylic system backdrop, macOS gets under-window vibrancy, and the stylesheet is translucent from :root down so the effect can come through.

Why there is no blur under the text

backdrop-filter filters what is painted below its surface, and that has to be redone whenever the surface repaints. Behind a terminal streaming output, across six panes, that costs real frames — so in-page blur is reserved for chrome that only repaints on interaction: the top bar, the tab strip, pane headers, dialogs and menus. The body of a pane is a plain translucent layer over the system blur.

If you want less transparency

  • The system reduced-transparency setting (prefers-reduced-transparency) switches to flat dark surfaces — the same ones Windows 10 and a missing backdrop-filter get.
  • By hand: the --fill-* variables at the top of src/renderer/styles.css carry every alpha. --fill-pane is the terminal body — raise it to buy back contrast over a bright wallpaper.
The terminal itself is transparent: the xterm theme background is #0b0b0b00. Alpha only counts in #rrggbbaa or rgba() form — xterm silently falls back to opaque black for any other syntax.

Keyboard shortcuts

KeysAction
Ctrl + TNew terminal (splits the focused pane)
Ctrl + Shift + ESplit right
Ctrl + Shift + OSplit down
Ctrl + WClose the focused pane
Ctrl + Shift + FZoom the pane / put it back
Ctrl + FSearch the scrollback (belongs to the pane)
Ctrl + Shift + CCopy the selection (or Ctrl + Insert)
Ctrl + Shift + VPaste (or Shift + Insert)
Right-click a paneCopy, paste, select all, clear the scrollback
Ctrl + Shift + NNew tab (workspace)
Ctrl + PageUp / PageDownPrevious / next tab
Alt + arrowsFocus the neighbouring pane
Ctrl + + / - or Ctrl + wheelFont size
Ctrl + Shift + ZUndo a move
EscClose the dialog
Double-click a pane nameRename
Ctrl + Z deliberately belongs to the shell (job control), which is why undo is Ctrl + Shift + Z. For the same reason Ctrl + F is the pane search and zoom is Ctrl + Shift + F.

Data and the trust boundary

A terminal runs shell commands, so the trust boundary must not be decoration. The renderer is treated as untrusted input.

  • Sandboxsandbox: true, contextIsolation: true, nodeIntegration: false. No Node access in the renderer; the whole surface is a frozen window.terminalApi.
  • Channels — every handler checks the sender (this window main frame), validates the raw payload, then checks who owns the id. 32 sessions at most.
  • External links — HTTPS only, no credentials in the URL. Window opens and navigations denied, CSP in a packaged build.
  • What is written — layout, tab and pane names, presets (variable names only), font size, toggles. workspace.json is written to a temp file and renamed, and loading it goes through the same caps as a renderer payload.
  • What is not written — environment values, scrollback, and running processes.

Versioning and releases

A version is born in one place: you write what changed under Unreleased in CHANGELOG.md, then cut it with one command.

npm run release patch      # 0.2.0 -> 0.2.1
npm run release minor      # 0.2.0 -> 0.3.0
npm run release 1.0.0-rc.1 # an explicit version
npm run release minor -- --no-git
  • It bumps package.json and moves the Unreleased notes into a dated section.
  • With a git repository it commits and writes an annotated tag (v0.3.0); without one it says so and carries on.
  • The app receives the version at build time (__APP_VERSION__) and shows it next to the wordmark in the top bar.
  • This website reads the same two files, so the download and release pages follow on their own.

Installers for the website

npm run dist       # electron-builder -> release/
npm run downloads  # release/ -> site/public/downloads/ + manifest.json

The downloads script renames the files into URL-friendly slugs, measures them, hashes them with SHA-256 and writes the manifest. When a platform has no local file the download page falls back to the GitHub release link; when that is not configured either, it offers the build-from-source route.

Troubleshooting

No glass effect

The system backdrop does not exist before Windows 11 22H2 (build 22621), where the window stays flat — that is not a bug. If transparency effects are switched off in the system, or reduced transparency is requested, the interface goes flat on purpose.

The agent does not continue the conversation

The --continue added on restore only works if that folder has a previous conversation. If it does not, the pane prints the CLI error and the Restart button is right there.

A terminal will not start

The working directory has to be a real folder — the main process re-checks that. Windows spawns powershell.exe -NoLogo, everything else $SHELL -l, so login-shell PATH is available to the CLIs.

The scrollback is gone

Scrollback and running processes are in memory only. After a pane restart, an app restart or a reboot the layout comes back, the output does not.