The Running list

Everything you left running, in one list: dev servers, agents, ssh sessions, anything that stopped, and the servers on this Mac that no tab started. Select a row and the detail beside the list says the rest. It is learned from what you ran; there is nothing to set up.

The Running list under its button, with doclife’s server selected: the page it serves, then its address, tab, folder, command and process, Restart if it stops, and its buttons in one row at the bottom. Under No tab, two servers an agent started in a scratch folder read new/frontend and orig/frontend; Docker is folded under 1 other app.

Opening the list

Running in the tab strip, Shell ▸ Show everything running or ⇧⌘R opens it, and so does Show Everything Running in the menu bar. The button appears only while something is running; the menu item and the shortcut always work. The heading counts what is running, what is waiting for you and what stopped, the same counts as the tab strip, the menu bar and the Dock.

The list and the detail

The list is in groups, what needs you first: Waiting for you, Stopped, Running in tabs, then the servers no tab owns under No tab and background tunnels under Tunnels. Each row is one line, in columns that never move: what runs; where, which is the tab, the folder it was started in (new/frontend, with a parent folder only when two would read the same) or where a tunnel goes (→ :3306); one fact, such as its port, exit 1 or ssh; and for how long. Select a row and the detail beside the list says the rest:

An agent
Its task, or the question it is asking, word for word, with its own first answer as a button. See answering from the list.
A server or a command
The page it serves on top, then its name, how long it has run and when it started (for 7h · since 14:01), and one line each for its address, its tab or folder, the command as you typed it, and its process number and memory; then Restart if it stops.
Something that stopped
Why, with the line Opsty read. See when something stops.
A server no tab owns
Its folder, what it runs and its process, and Stop, which shows the kill it sends. A long folder is folded in the middle, such as /tmp/…/deps/new/frontend/.next/standalone; copy it and you get the whole path. A server that renamed itself, as Next.js does (next-server), is shown by that name, beside the program it runs: node, renamed itself next-server.
A tunnel
Where the forward goes, in a sentence, its two ends, and Disconnect, which shows its kill.
A tab you just closed
How long until what runs in it stops, with Undo. See closing a tab.

The detail ends in one row of buttons, always in the same place, with Copy address and Copy command among them. The filled one is what ⏎ presses, and it never runs or stops anything: Go to tab, Open, Go to the block or Undo. A button that runs or stops something names what it sends: Stop on a tab sends ⌃C, as if you pressed it there; on a server no tab owns it sends kill 48211, a TERM signal that lets the server close itself. Servers and commands only: an agent or an ssh session is ended from its own tab.

A tab back at its prompt stays on the list while a server it started is still listening behind it, and says how many there are.

Keys

↑ and ↓ select a row (Page Up, Page Down, Home and End too), ⏎ presses the filled button, ⌘C copies the selected row’s address or command, ⇥ moves into the detail’s buttons, and esc closes the list and gives the keyboard back to the grid. Commands, paths, addresses and an agent’s question can be selected in the detail, and copy exactly as written. In a window narrower than 880 pixels, the detail opens under its row instead of beside the list.

Answering an agent from the list

When Claude Code asks permission, its detail quotes the question and offers Claude’s own first answer as a button, word for word, such as Yes. Before sending it, Opsty reads the agent’s screen again: if the question is no longer there, nothing is sent and the detail says Answer it in the tab, where it is now. When an agent has simply finished, the detail has Reply to Claude Code… instead; what you type is sent only while it is still waiting at the same turn. These are the same checks as answering from a notification.

Servers no tab started

About every two seconds Opsty asks macOS’s lsof which programs your account runs are listening on a TCP port, and ps which tab, if any, each one descends from. So a server an agent started in the background is listed under that agent’s tab, as in └ vite · :5173 · started by claude.

A server no tab owns that looks like one a person started, such as an old node still holding :3000, or a Python or Homebrew server, is listed under No tab, with the folder it was started in, and how long ago, its memory and its process number in its detail. Its Stop button shows the kill 48211 it sends. A forward running in the background (ssh -f -N) is listed under Tunnels, with where it goes and the server it goes through.

Whose a server is, Opsty decides by the program file it runs, never by the name it gives itself. Ports held by other apps (Docker, an editor, an app’s helper) are folded into one row at the end of the list, 2 other apps, closed until you open it, with each app once and its ports; they have no Stop and are not counted. macOS’s own are not listed. The port card still names whatever holds a port. A command line is shown without its environment, with passwords and tokens removed. Settings ▸ Privacy ▸ See every server on this Mac switches all of this off (allServers = false), and Opsty goes back to asking only about each tab’s own programs.

The page a server serves

Select a server and, a moment later, its detail shows a small picture of the page it serves. When the tab serving it prints that the page changed, such as Vite’s hmr update, the picture is taken again two seconds later, and its caption says so: refreshed 2s after the save. When the server fails to send the page’s own stylesheets, the caption says that too, such as 2 stylesheets returned 500 — the server’s problem: the page looks unstyled in any browser, not only here. Moving down the list with ↓ loads nothing on the way: a page is loaded only for the server you stop on, and only while it stays selected.

A hidden window loads http://localhost:/; any request the page makes to anything other than this Mac, such as a web font or an analytics script, is cancelled, a port forwarded over ssh is never opened, and the picture is not saved. Settings ▸ Privacy ▸ Peek at a port switches it off (peekPorts = false).

Restart if it stops

In the detail of a server or a long-running command on this Mac, Restart if it stops shows the exact command it would type again, with a switch. It is offered only for something meant to stay up: a run that listened on a port, or a dev server, a watcher or a worker. A chain of steps, such as a release script, is never offered it, even when it ends with a server. Arm it, and each time that command stops, Opsty types it in the same tab with Enter, and the row says how many times it has. After five stops within two minutes it gives up: the row says stopped · keeps failing, and a card shows the error that kept repeating and, when Opsty recognizes it, offers the fix with Place in a new split.

You armed it, for that command. Nothing else in Opsty restarts by itself.

Port forwards

An ssh session’s detail lists its forwards, from -L on its command line and LocalForward in ~/.ssh/config, each said in a sentence, as addresses with Open and Copy address.

When you have a server to forward from, Forward a port… at the top of the list opens a small form: the Server, the Port on this Mac and the address on the server, then a sentence saying where the forward goes. Place in a new tab puts the ssh -N -L … command in a new tab for you to run.

When a port is already in use

The port card: Another server is already using port 3000, the server that holds it, and buttons to go to it, stop it, or run on another port.

When a command fails because its port is taken, the card says Another server is already using port 3000 and names whatever holds it:

  • Another tab. The command and the tab, such as npm run dev in tab ‘shop’, and how long it has been running. Go to that tab brings it forward. Stop it and run here sends ⌃C to that tab, waits for the port to come free (at most five seconds), then runs your command again here.
  • A server no tab owns. What it is, the folder it was started in, how long ago, its memory and its process number. If a person started it, Stop it and run here carries the exact command it runs, such as kill 48211 && npm run dev, and the card says The button runs exactly what it says.
  • Part of macOS or another app. Named, and never offered a kill: It is part of macOS, so leave it running and use another port. On many Macs, Control Center’s AirPlay receiver holds :5000.

Another port places your command again with a free port, written the way the tool documents it: --port for Vite, Astro and Nuxt, -p for next dev, npm run dev -- --port 3001 through npm, and PORT=3001 in front of anything else. It is placed on your line, not run.

With See every server on this Mac off and no tab holding the port, the card says Something else is already using port 3000. and offers lsof -i :3000 with Put on the line.

When something stops

A command that ran for five seconds or more and then failed is treated as something that stopped, such as a dev server that died or a watcher that crashed:

  • its tab says stopped, and if you were looking elsewhere a notification says shop · stopped, with the line Opsty read;
  • its lamp becomes a red cross and stays one until you act: run something in that tab, press Clear in its detail, or close its failure card. Looking at the tab clears the count on the Running button and the Dock, not the cross;
  • the list shows it under Stopped, and its detail says why.
shop’s server stopped: its detail has the command, how long it ran and its exit code, Opsty’s sentence over the line it read, the fix with Put on the line, and Go to the block as the Enter.

A stop’s detail has the command as you typed it, how long it ran, its exit code, and then one of two things:

  • when one of Opsty’s failure explanations fits, its sentence, under From the error it printed, with the line it read, quoted, and its one fix with Put on the line;
  • when none fits, What the command said last: the program’s own last error lines, quoted as it printed them. Opsty does not guess a cause.

Then its buttons. Go to the block (the Enter) brings the tab forward with that command in view. Run the command above again types the command shown above it and presses Enter, so the click is your Enter; it is there only while the tab is back at its prompt. Copy output · for an AI copies the command and its output for a chat, and Clear takes the stop off the list and puts out the cross.

Three other doors open the list at a stop: clicking its notification, Why it stopped in the tab’s right-click menu, and Show in Running on its failure card.

Errors while it is still running

A dev server that prints an error and carries on has not stopped, so Opsty reads its output as it arrives. Vite’s Internal server error and Pre-transform error, Next.js’s ⨯ lines and tsc --watch errors get a red mark beside the error, a count on the tab and an errors button in its detail on the list. No notification is sent, since nothing stopped.

⌘↓ walks to each one, as it walks between commands, and a card explains it in one sentence and names what it read, such as From tsc’s error code. Open line 12 in the editor opens the file at that line in Cursor, Visual Studio Code, Windsurf, Zed or VSCodium, preferring one that is running, or else in the Mac’s default app for that file. When the program reports the fix, such as a reload of that file or a clean compile, the mark turns gray. Settings ▸ Helpers ▸ Errors while it runs turns this off.