Zeus
Native macOS control plane for coding agents. Run Claude Code, Codex, Cursor, Grok, OpenCode, Gemini, and a catalog of other CLIs in parallel, locally or over SSH. Each session is a real PTY with a live status (working, needs you, done). Closing the window never kills an agent. A daemon restart brings the conversations back.
Zeus is not an IDE and not a model. It is the place you watch a fleet, jump to the session that is stuck, and accept the work.
Install
Zeus requires macOS 15 or newer. Download the current universal DMG from Releases, drag Zeus to Applications, then complete the one-time Gatekeeper exception. The current release is ad-hoc signed and is not available through Homebrew.
See Getting started or the illustrated macOS install guide for the complete installation flow.
In this book
| Section | What it covers |
|---|---|
| Getting started | First project, first session, first quit |
| The workbench | Sidebar, inspector, lineage tree, overview |
| Keyboard | Every shortcut that matters |
| Agents and status | Catalog, resume, what the colors mean |
| Worktrees | Isolated checkouts for parallel edits |
| Orchestration | MCP spawn, wait, prompt, read |
| Fleet patterns | Ways to run more agents than you can watch |
| Settings | Defaults, layout, hibernate, hosts |
| Command line | zeus session, worktrees, doctor |
| Remote hosts | SSH machines in Settings → Remote |
| Remote nodes | First-party zeus-node on a VPS |
| Updates | How auto-update works |
| Security model | Trust boundaries |
| Privacy | Local data and network activity |
| Support | Diagnostics and logs |
| Roadmap | Product direction |
Getting started
Install
Zeus requires macOS 15 or newer. The current universal DMG is ad-hoc signed, not Developer ID signed or notarized. Download it only from GitHub Releases, open the DMG, and drag Zeus to Applications.
For the first launch, open Finder → Applications, Control-click or right-click Zeus, and choose Open. If macOS still blocks it, try to open Zeus once, then go to System Settings → Privacy & Security → Security and choose Open Anyway. The illustrated macOS install guide shows each screen in the flow.
Do not disable Gatekeeper or remove quarantine attributes globally. Homebrew installation and in-app updates remain unavailable until a Developer ID signed and notarized release ships. See Updates.
Ten minutes to a fleet of one
- Open Zeus. If no project is open, use Open… (
⌘O) or Quick Open (⌘P) and pick a repository from the Projects & Folders section. - Press
⌘N. Choose Claude Code, Codex, or whatever is installed, type the first prompt, and press Return. You can also press⌘Tto launch your default agent in the current project with no prompt. - Work in the embedded terminal. The sidebar row tells you whether that agent is working, waiting for you, or done. You do not have to keep reading the PTY.
- Press
⌘⇧Dif the inspector is closed. Info is identity and usage. Review is the git diff for this worktree. Code opens a file. Artifacts collects ports, PRs, and other finds. - Quit Zeus (
⌘Q) and reopen it. The background Engine still owns the PTY. The session and its scrollback are still there.
If the agent you wanted is missing from the launcher, install its CLI so it
is on PATH, then reopen the picker. Zeus does not install agents for you.
zeus doctor confirms the Engine is up and whether claude and codex
are on PATH.
What you are looking at
┌ sidebar ┐ ┌ toolbar + tabs or tree ┐ ┌ inspector ┐
│ project │ │ │ │ Info │
│ session │ │ live terminal │ │ Review │
│ session │ │ │ │ Code │
│ + New │ │ optional shell │ │ Artifacts │
└─────────┘ └────────────────────────┘ └───────────┘
The sidebar is the map of the fleet. The center is the session you are in. The inspector is how you accept the work without leaving Zeus.
The menu bar extra is a glance: click the Zeus item to see who is noisy without bringing the window forward.
Three habits that pay off immediately
One worktree per agent that writes code. Two agents in the same checkout
will fight over files. ⌘N and MCP spawn_agent can both create a worktree.
See Worktrees.
Let a lead spawn, do not type every child yourself. A hosted Claude, Codex, Grok, or OpenCode session already has Zeus MCP. Ask it to open a reviewer, a tester, or a second implementer. Children nest under the lead in the sidebar and in the workflow tree. See Orchestration.
Jump to whoever needs you. ⌘⇧J selects the next session that is blocked
on input. ⌘⇧O opens the session overview. Treat the rest of the fleet as
background.
Agent support, briefly
Claude Code and Codex have the richest status detection and resume. Cursor, Grok, OpenCode, Gemini, and the rest of the catalog still get a real PTY, a sidebar row, and (when the CLI is installed) a launch button. Missing binaries show an install hint instead of a dead shortcut.
Remote, when you are ready
- SSH hosts live under Settings → Remote. Zeus bootstraps a small Helper
on the machine. No
tmux. See Remote hosts. - First-party nodes add accounts, usage, and laptop↔VPS handoff. See Remote nodes.
Prefer a dedicated non-admin account on the remote machine.
Diagnostics
zeus doctor
Daemon logs and session state live under
~/Library/Application Support/Zeus. Logs may contain terminal output, paths,
or secrets printed by a process. Redact them before sharing. Email
hi@nasrul.info for help. See Support
for what to include.
Local data and uninstalling
Quit Zeus. Then stop anything still holding the socket if you also want a
clean slate (zeus doctor will tell you whether an Engine is running).
Remove the app and these directories to delete local state:
~/Library/Application Support/Zeus
~/Library/Application Support/zeus
~/Library/Caches/zeus/updates
Read Privacy and the security model before using Zeus with sensitive repositories or remote hosts.
The workbench
Zeus is a three-pane machine. Learn the panes and the rest of the product falls into place.
Sidebar
Projects group sessions. Each row is one agent or shell: title, host badge,
and a status mark. Click a row to focus it. ⌘1 through ⌘8 jump to the
nth visible session. ⌘9 jumps to the last.
Useful moves:
- New Agent at the top of the sidebar, or
⌘N, opens the composer. - Pin a project or session you always want at the top.
- Collapse a lead session to hide its spawned children when the tree is loud.
- Rename the selected session with
⌘R. - Archive with
⌘⇧W. Archived rows drop into the project's archive group. They stay as history. They are not the resume path. - Reorder a row inside its project with
⌃⌘↑and⌃⌘↓. - Needs you is
⌘⇧J. It walks sessions that are blocked on input.
The footer can show an Update to … pill. That is the only place an available update lives until you click it. See Updates.
Terminal
The center card is a real terminal, not a chat log. Copy and paste work as
usual (⌘C / ⌘V). Find is ⌘F, then ⌘G / ⌘⇧G. Font size is ⌘+,
⌘-, and ⌘0, or Settings → Terminal.
⌘J opens a second, auxiliary shell under the same session. Use it for git,
tests, or a one-off command without stealing the agent's PTY.
When a session belongs to a spawn family (a lead plus children), a compact tab strip sits above the terminal. Switch with the mouse or, in the tree view, with the arrow keys.
Tabs and the workflow tree
A family of spawned sessions can be shown two ways:
- Tabs keep the terminal on screen and list the family as chips.
- Tree replaces the terminal with the genealogy: each node is the agent's mark, a caption with the title and status, and rails to its children. A working node wears a spinner around the mark.
Open the tree from the Tabs / Tree control, or from the command palette
(Agent Workflow Tree). In the tree: ↑ ↓ move, Return or a
double-click opens that session's terminal, Esc returns to tabs.
Use tabs when you are in the conversation. Use the tree when you are conducting.
Inspector
⌘⇧D shows or hides it. Four tabs:
| Tab | Job |
|---|---|
| Info | Session briefing: identity, attention, location, lifecycle, lineage, and runtime |
| Review | Git workspace for this checkout: repository header, branch picker, pull-request navigation, and the live diff. Stage and commit stay on the working tree |
| Code | Worktree-scoped Changed / All files tree and the existing file viewer. Word wrap is a Settings toggle |
| Artifacts | Ports the session opened, pull requests it mentioned, and other finds |
Review is how Zeus earns the "accept the work" claim. Let the agent finish, then read the diff in the same window you used to watch it.
Code opens on Changed, using the same staged, working-tree, rename,
conflict, and untracked status data as Review. Switch to All files to browse
the selected local session's repository; directories load only when expanded,
and Git-ignored entries stay out of the tree. Opening a path from Review,
Quick Open, or a terminal reference reveals it in the tree and reuses the same
viewer below it. ⌘⇧E opens Code and focuses the tree. Type to filter, use
↑ / ↓ to move, → / ← to expand or collapse, Return to open, and Esc
or Tab to return focus to the viewer. Non-repository sessions can still use
All files, while Changed explains that Git status is unavailable. Remote
sessions remain view-only and are not browsed through the local filesystem.
Info answers the quick briefing questions for the selected session: what kind
of agent it is, where it runs, whether it needs you, when it last completed a
turn, whether a remote process can survive disconnect, and how it relates to
parent, child, and ⌘J workbench sessions. Sleeping and ended sessions explain
their lifecycle state and resumability. Paths, timestamps, and session IDs can
be copied from the panel.
Info keeps Git to a one-shot working-tree summary that jumps to Review; it does not poll in the background, show pull-request content, or mutate the repository. Artifacts and listening ports are counts that jump to Artifacts. Installation- level usage remains in the account menu; Info only shows usage when Zeus can attribute it to the selected session.
Session overview
⌘⇧O (also Session Overview in the palette) is the board of every live
session. Use it when the sidebar is a long list and you want a spatial
scan. Click a card to jump.
History
⌘⇧H opens recent activity. It is the short-term memory of what this
installation has been doing, not a search engine over every byte of
scrollback.
Worktrees sheet
⌥⌘W lists git worktrees Zeus knows about, which session owns which, and
which look stale enough to clean up. Cleanup is suggest-only: dirty,
unmerged, or main-branch trees will not reach the confirm step. See
Worktrees.
Menu bar
The Zeus extra in the macOS menu bar is a quiet radar. It shows how many sessions need you without stealing focus. Click it to pick a row and come back to the window.
Command palette and Quick Open
⌘K is the index of everything Zeus can start: new agents, new shells,
"New Claude Code in this project", "New Codex on this host", move the
selected Claude session, sync prefs, settings, docs, updates.
⌘P is the unified navigator. It searches files in the selected local
session's project (or the first open project on the startup screen), every
agent session, and indexed folders. Return opens a file in Code, switches to a
session, or launches your default agent in a folder; ⌘Return launches a
terminal for a folder result. Add extra folder search roots in Settings →
General. Remote sessions still appear, but their files are not indexed through
the local filesystem.
Layout
Settings → General → Projects sidebar on the right mirrors the chrome: sidebar on the trailing edge, inspector on the leading one. The terminal stays in the middle either way.
Keyboard
Zeus is built to be driven without hunting through menus. The palette (⌘K)
is the backup for anything you forget.
Start and stop
| Shortcut | Action |
|---|---|
⌘N | New Agent composer (pick kind, folder, first prompt) |
⌘T | New session with your default agent |
⌥⌘T | New terminal (login shell) |
⌘⇧N | New Codex session |
⌘O | Open a project folder |
⌘P | Search project files, agent sessions, and folders |
⌘W | Close the selected session |
⌘⇧T | Reopen the last closed session |
⌘⇧W | Archive the selected session |
⌘Q | Quit the app (sessions keep running) |
Move
| Shortcut | Action |
|---|---|
⌘1 … ⌘8 | Select the nth session |
⌘9 | Select the last session |
⌥⌘↑ ⌥⌘↓ | Previous / next session |
⌘[ ⌘] | Same, wrapping through the list |
⌃⌘↑ ⌃⌘↓ | Reorder the selected row inside its project |
⌘⇧J | Next session that needs input |
⌘⇧O | Session overview |
⌘R | Rename the selected session |
Chrome
| Shortcut | Action |
|---|---|
⌘K | Command palette |
⌘B | Show or hide the sidebar |
⌘⇧D | Show or hide the inspector |
⌘⇧H | History |
⌥⌘W | Worktrees sheet |
⌘, | Settings |
⌘J | Auxiliary shell under the current session |
Terminal
| Shortcut | Action |
|---|---|
⌘F | Find in the terminal |
⌘G / ⌘⇧G | Find next / previous |
⌘C / ⌘V | Copy / paste |
⌘+ ⌘- ⌘0 | Zoom in, out, reset |
Workflow tree
When the lineage view is Tree:
| Shortcut | Action |
|---|---|
↑ ↓ | Move between nodes |
| Return | Open that session's terminal |
| Double-click | Same |
| Esc | Back to tabs |
Palette worth typing
You do not have to remember every remote or project shortcut. Open ⌘K and
type:
new claude,new grok,new opencode- a project folder name
- a host name (
new codex on forge) workflowfor the agent treeworktree,settings,update
Unavailable agents stay searchable. If Zeus has a setup URL it will open the install docs instead of spawning a dead session.
Agents and status
Every session is a PTY. The agent catalog is data: one JSON manifest per CLI, describing how to spawn it, how to resume it, which keys approve or deny a prompt, and the screen rules that decide whether it is working, waiting, or done.
Zeus never installs an agent for you. Put the binary on PATH, sign in the
way that CLI expects, then launch it from Zeus.
What you can launch
The launcher, sidebar New Agent, ⌘N, ⌘T, and the command palette all
read the same readiness catalog. First-class entries (when the CLI is
installed) include:
Claude Code, Codex, Cursor, Grok, OpenCode, Gemini, Aider, Amp, Copilot, and the rest of the manifests shipped in the Engine.
A missing binary is not a crash. The row stays visible with an install hint and, when the manifest has one, a setup URL.
⌘T always does something useful. If your saved default agent disappeared,
Zeus falls through to another installed first-class agent, then to a login
shell.
Status you can leave the room on
Zeus reads the grid, the title, progress, hooks, and process facts. It reduces them to a small vocabulary:
| State | Meaning |
|---|---|
| Working | The agent is doing something. In the workflow tree the mark wears a spinner. |
| Needs input | It is blocked on you: a permission, a question, a confirm. Destructive prompts get a sharper color. |
| Done | It finished work you have not opened yet. |
| Idle | Quiet, and you have already seen it. |
| Hibernated | Frozen to save memory. Opening the session wakes it in place. |
| Ended | The process exited. Resume if the agent supports it. |
Claude Code and Codex have the richest rules (working, blocked-permission, blocked-question, idle, exited) plus resume. Other catalog agents get whatever their manifest knows. If Zeus cannot name a blocker it will not invent one. A lying spinner is worse than a quiet row.
⌘⇧J walks every session that needs input. Gentle status chimes (Settings →
General) are optional and stay quiet on mere token activity.
Resume
Closing Zeus does not end the process. Closing a session might, after a confirm if you left that setting on.
Agents that support resume can pick up a conversation after a clean exit or after you reopen a still-running PTY. Codex and Claude Code are the ones to trust here. Others may come back as a fresh CLI in the same folder.
Archiving (⌘⇧W) is for history, not resume.
Hosted vs a bare shell
A hosted agent is one Zeus launched from a manifest. Those sessions get Zeus MCP injected automatically (see Orchestration).
A plain terminal (⌥⌘T) is your login shell. It still has a sidebar
row and running/exited status. It does not get agent MCP, resume, or a
branded mark.
Marks in the tree
The workflow tree draws unbadged brand marks for Codex, Claude, Grok, OpenCode, and Cursor. Other kinds use a terminal glyph. Working sessions get a ring around the mark. Titles sit in a caption chip under the icon so the rails never run through the name.
Default agent
Settings → General → Default agent is what ⌘T and Quick Open launch.
Pick the CLI you reach for first. Everything else stays one ⌘N or ⌘K
away.
Worktrees
Two agents editing the same checkout will overwrite each other. A git worktree is a second working directory on a second branch, attached to the same repository. Zeus treats that as the default way to run parallel work.
Worktrees are isolation from merge conflicts, not a security boundary.
Create one
The everyday path is to ask a hosted agent. Zeus MCP is already injected, so
a lead can call spawn_agent with worktree: true, or create_worktree
first and then spawn into that path.
From the CLI:
zeus worktree create --repo ~/src/mldrills --branch spike-auth
zeus session spawn claude-code --cwd ~/src/mldrills --worktree --prompt "own the auth rewrite"
The new directory is a normal checkout. Commit, stash, or cherry-pick as you would anywhere else.
See what you have
⌥⌘W opens the worktrees sheet: path, branch, owning session, dirty or
not, and whether Zeus thinks the tree is stale enough to remove.
zeus worktree list --repo ~/src/mldrills
The inspector Review tab is bound to the session's cwd. If that cwd is
a worktree, you are reviewing that agent's branch, not main. Branches…
compares or opens another ref without confusing that with an in-place
checkout. Go to Pull Request… loads #123 or a GitHub URL even when no
agent printed the link. Opening a PR head uses an isolated worktree.
Clean up
Treat each worktree as a real checkout. Commit or move the changes you want before you delete it.
The sheet will only offer cleanup on trees it believes are stale (old,
merged, not dirty, not main). Confirmation is required. It will not
force-remove a dirty tree from the UI.
zeus worktree remove --repo ~/src/mldrills --path /path/to/worktree
--force exists on the CLI for when you know what you are doing. The app
does not expose that.
A good default
Give every writing agent its own worktree. Share a tree only when two sessions are supposed to touch the same files (a shell running tests under the implementer, for example).
Name the session after the bet (auth-rewrite, perf-spike) so the
sidebar reads like a kanban, not a pile of "Claude Code".
Orchestration
Zeus is most itself when one agent runs others. A hosted session can spawn a child, wait until it is done or stuck, read the output, answer a prompt, and release it. Those children are real Zeus sessions: sidebar rows, inspector diffs, workflow-tree nodes.
This is powerful. A spawned agent runs as your macOS user. Only talk to agents you trust, and read what they ask before you approve it.
You do not configure MCP by hand
For Claude Code, Codex, Grok, OpenCode, Gemini, and Cursor, Zeus writes a
per-session MCP overlay when it launches the process. The agent sees a
zeus server. You do not paste JSON into a dotfile for the default path.
Codex's built-in multi-agent spawn is turned off on purpose while Zeus is
hosting it. Those inner workers never become sidebar sessions. spawn_agent
is the path that does.
A plain ⌥⌘T shell does not get this server.
Tools the lead can call
| Tool | When to use it |
|---|---|
spawn_agent | Open a new Zeus session nested under this one. Pass kind, cwd, optional worktree, name, and prompt. worktree is local only. This is the only spawn that shows up in the UI. |
list_agents | Survey the fleet: id, kind, title, status, parent, cwd. |
list_children | Just the sessions this lead spawned. |
get_status | One session: working, idle, needsInput (with detail), or exited. |
send_prompt | Type into a session and, by default, submit. Use it for follow-ups and for answering a blocker. |
wait_for_agent | Block until done, needsInput, exited, or any. |
wait_for_children | Block until every child of this lead is done. |
read_output | Tail the PTY after a wait, so the lead can summarize or critique. |
release_agent | End a session and kill its process tree. The row stays in the list. |
create_worktree / list_worktrees / remove_worktree | Isolate parallel git work. |
whoami | The calling session's id, kind, cwd, and parent. |
zeus mcp-tools prints the live catalog. zeus mcp-call --tool list_agents
is the one-shot CLI for the same socket.
How to ask
You do not need to name the tools. Talk to the lead in the terminal:
Spawn a Codex in a fresh worktree on the auth rewrite. Wait until it is done or needs me. If it asks for a destructive permission, ping me instead of approving. Then spawn a second Codex to review the diff and stop at a PR description. Do not merge.
The lead should spawn_agent twice, wait_for_agent (or wait_for_children),
and read_output. You will see two nested rows and a tree with three nodes.
If a child is blocked, ⌘⇧J lands you on it. Answer in that terminal, or
tell the lead to send_prompt.
Shape of a good spawn
- Name the session.
namebecomes the sidebar title (auth-rewrite,reviewer,load-test). - Give it a worktree when it will edit. Share a cwd only when the child is a shell that should see the parent's files.
- Send the assignment after the child is ready. MCP
spawn_agentreturnspendingPrompt. The Engine does not type it. The lead shouldwait_for_agent(or wait until the child is idle) and thensend_prompt. The CLI--promptflag is different:zeus session spawninjects that text once the agent can take it. - Wait with a timeout.
wait_for_agentdefaults to five minutes. Long jobs should say so. - Read before you praise.
read_outputis how the lead learns what happened. Do not let it invent a victory from a quiet PTY.
CLI as a second conductor
Anything MCP can do, the zeus CLI can do from a script or from another
terminal:
zeus session spawn codex --cwd ~/src/mldrills --worktree \
--title auth-rewrite \
--prompt "Implement the JWT refresh plan in AGENTS.md. Stop at a passing test."
zeus session wait <id> --until done --timeout 1200
zeus session read <id> --source output --lines 80
See Command line.
What not to do
- Do not tell Codex to "use its subagents" while it is hosted in Zeus. Those stay inside one PTY. The sidebar will look empty and you will have lost the plot.
- Do not expect a local lead to MCP-spawn onto a remote host.
hostis not a supported MCP argument yet. Start remote sessions from the palette orzeus session spawn --host, then orchestrate children on that same machine. - Do not confuse a worktree with a sandbox. Children still have your keys.
- Do not skip Review. Orchestration without an accept step is just more unmerged branches.
Fleet patterns
Zeus is for the week you have more bets than attention. These patterns use only what the app already does. Mix them.
The lead and two specialists
One session you talk to. It does not edit much. It hires.
⌘Ta Claude or Codex in the repo, titledlead.- Tell it the outcome, the constraints, and that it must spawn specialists
into worktrees rather than touching
main. - Open Tree. You should see the lead above a row of marks.
- Drink coffee.
⌘⇧Jonly when something is red.
A useful split:
- Implementer (Codex or Claude) owns the patch.
- Reviewer (a different kind, Grok or OpenCode) reads
read_outputand the diff, never the same worktree as the writer if you can help it. - Shell (
kind: shell) runs the test command in the implementer's tree.
The lead calls wait_for_children, then writes you a briefing. You accept
or reject in Review.
Three spikes, one merge
You do not know which approach is right. That is a fleet, not a meeting.
Spawn three named worktree sessions (spike-index, spike-cache,
spike-rewrite) with the same prompt and a hard stop: "do not open a PR.
Leave a summary at the top of the diff." When they go idle, sit in session
overview (⌘⇧O) and open Review on each. Keep one tree, delete the other
two after you have stolen the good ideas.
The tree view is the scoreboard. Ended spikes stay on the board until you
archive them (⌘⇧W).
Local glass, remote muscle
The Mac is where you look. The 64-core box is where tokens burn.
Add the host in Settings → Remote. From ⌘K run New Codex on Forge
(or whatever you named it). Status, resume, and Review still happen in
this window. The Helper on the host owns the PTY. There is no tmux to
babysit.
A session that is already on Forge can spawn children there (same host,
same MCP). A lead that is still on the laptop cannot MCP-hire onto Forge
yet. Start the remote workers from the palette or
zeus session spawn --host forge, then talk to them from the tree.
If you enrolled a zeus-node, use handoff to move a Codex or Claude
thread to the VPS without copying auth.json. See
Remote nodes.
Overnight, not on fire
Settings: start at login, gentle chimes on, hibernate idle sessions after 15 or 30 minutes, memory limit at 6 GB.
Before you close the lid:
- Name every live session.
- Make sure each writer has its own worktree.
- Tell the lead what "done" means, and that it must not approve destructive prompts.
- Leave the menu bar extra enabled.
In the morning, ⌘⇧J is the inbox you actually have today. Hibernated rows
wake when you open them. Nothing was killed to save RAM.
Research / implement split
Grok (or Gemini) in the repo with worktree: false and a prompt that
forbids editing: "read, cite files, propose a plan, do not write patches."
Codex or Claude in a worktree with that plan pasted as prompt.
The researcher can send_prompt follow-ups. The implementer never has to
see the web. You stay on the implementer's Review tab.
Pair a shell with every writer
⌘J puts a login shell under the current agent. Use it for git log,
just test, htop. The agent keeps its TUI. You stop pasting command
output into the chat because you can see the repo yourself.
For a child that should be scriptable, spawn kind: shell from MCP instead
so the lead can send_prompt a command and wait_for_agent on exit.
Codex-only keyboard
If Codex is how you think, set it as the default agent and live on ⌘T and
⌘⇧N. Keep Claude a palette search away for the jobs it is better at
(long-context review, MCP-heavy leads). The catalog is not a loyalty club.
Conduct, then accept
A loop that scales:
- Tree to see who is alive.
- Needs you (
⌘⇧J) to unblock. - Review to read the diff in the same worktree.
- Archive the ones you have merged or abandoned.
- Worktrees sheet (
⌥⌘W) to delete the empty apartments.
If you skip step 3 you do not have a fleet. You have a garden of branches.
Naming
Sidebar titles are load-bearing. Claude Code 3 is how you get lost.
lead, auth-rewrite, reviewer, forge-load is how you scan.
⌘R is faster than regretting it at 1 a.m.
Settings
⌘, or Settings in the command palette. Four tabs.
General
Default agent. What ⌘T and a folder result in Quick Open launch. Used by
the sidebar's primary New Agent hint as well.
Projects sidebar on the right. Mirrors the chrome: projects on the trailing edge, inspector on the leading one.
Word wrap. Soft-wraps long lines in inspector Review and Code.
Start Zeus at login. Opens the app after you sign in to macOS. Sessions were already alive (the Engine outlives the window). This just puts the glass in front of you.
Confirm before closing a session. Asks before you kill a running
process with ⌘W.
Gentle status chimes. Quiet sounds for needs-input, completion, and memory pauses. Working sessions stay silent.
Updates. Background checks about 20 seconds after launch, then every six hours. Download and restart always wait for a click. See Updates.
Quick Open roots. Extra entries for Quick Open's Projects & Folders section, one per line and scanned four levels deep. Empty means the default folder plus parents of open projects.
Terminal
Color theme. Applies to the app chrome and every open terminal at once. The catalog includes the monochromatic Zeus Dark (default), Zeus Dark High Contrast, Zeus Light, Solarized, Dracula, One Dark, Gruvbox, Tokyo Night, Catppuccin, Vesper, Nord, Rosé Pine, Kanagawa, Everforest, GitHub Light, and friends.
Font size. Terminal text only, 10 to 20 pt. ⌘+ / ⌘- / ⌘0 do the
same from the keyboard.
Resources
Hibernate idle sessions. Off, 5 minutes, 15 (default), 30, or 1 hour. A frozen session is not killed. Opening it wakes the same process at the same screen.
Memory limit. 2, 4, 6 (default), or 8 GB per session. Crossing it freezes that session the same way.
Use these when the fleet is large and the laptop is small. They are how overnight runs stay polite.
Remote
Add, edit, or remove SSH execution hosts here. That is the supported path.
The on-disk catalog is
~/Library/Application Support/Zeus/hosts.json if you prefer to edit JSON.
Each host has a name, an SSH destination (you@forge or an ~/.ssh/config
alias), a default remote cwd, and optional first-party node fields
(endpoint, token file, node id). See Remote hosts and
Remote nodes.
id is generated from the name and then frozen, because sessions persist
it. Rename the label all you like. Do not expect to rewrite the id by
hand without confusing old rows.
What is not a setting
The last selected session, sidebar width, window placement, and which inspector tab you were on all persist automatically. You should not have to re-tune the furniture every launch.
Command line
The packaged app ships zeus next to the Engine. After a cask or DMG
install it should already be on your PATH. zeus --help prints the
map:
zeus <resource> <action> [target] [options]
--json is accepted on the session, worktree, events, and artifacts
commands when you want to script.
Doctor
zeus doctor
Checks that the Engine is reachable, that claude and codex are on
PATH, and that the session state file exists. Start here when the app
cannot connect or a spawn fails.
The version string to include in a support mail is the one in the account popover (and on the update row).
Sessions
zeus session list
zeus session list --all
zeus status # alias of session list --all
zeus session get <id>
zeus session read <id> --source scrollback --lines 80
zeus session send <id> "run the tests again"
zeus session send <id> "looks good" --no-submit
zeus session wait <id> --until done --timeout 600
zeus session spawn claude-code --cwd ~/src/mldrills --worktree \
--title auth-rewrite \
--prompt "Implement the plan in AGENTS.md. Stop at tests."
zeus session spawn codex --host forge --cwd ~/code/mldrills
zeus session archive <id>
zeus session archive <id> --undo
zeus session release <id> # kill the process tree, keep the row
zeus session release <id> --remove
wait --until accepts done, idle, working, starting,
needs-input, and exited. Default timeout is 10 minutes.
Spawn kinds are catalog ids: claude-code, codex, cursor, grok,
opencode, gemini, shell, and the rest zeus doctor lists.
Worktrees
zeus worktree list --repo ~/src/mldrills
zeus worktree create --repo ~/src/mldrills --branch spike-auth --base main
zeus worktree remove --repo ~/src/mldrills --path /path/to/worktree
Artifacts, events, ports
zeus artifacts <id>
zeus ports
zeus events subscribe --session <id>
zeus events wait --session <id> --until needsInput
MCP and hooks
zeus mcp-tools
zeus mcp-call --tool list_agents
mcp-stdio is the server the app injects into hosted agents. You rarely
need to run it yourself.
zeus hook and zeus notify are fail-open forwarders for Claude hooks
and Codex notify. They exist so those CLIs can poke Zeus. They are not
an interactive UI.
A tiny conductor script
id=$(zeus session spawn grok --cwd "$PWD" | awk '{print $1}')
zeus session wait "$id" --until done --timeout 300
zeus session read "$id" --source scrollback --lines 40
Pair this with Orchestration when the lead is another agent, and with Fleet patterns when you are the lead.
Remote hosts
Add machines under Settings → Remote. Each host is an SSH destination Zeus can spawn onto. The Mac stays the glass. The other computer owns the PTY.
The catalog is stored per installation at:
~/Library/Application Support/Zeus/hosts.json
A missing or empty file leaves Zeus in local-only mode. Prefer the Settings form. The JSON is there if you want to copy a host between machines.
Add a host
⌘,→ Remote → add a host.- Name is the label in the palette (
New Codex on Forge). - SSH is
you@forge, a hostname, or an alias from~/.ssh/config. - Default cwd is where new sessions land (
~/code). - Save. Open
⌘Kand type the host name.
| Field | Meaning |
|---|---|
id | Stable value stored on sessions. Generated from the name, then frozen. |
name | Label in pickers and badges |
ssh | SSH destination or ~/.ssh/config alias |
defaultCwd | Default remote working directory for new sessions |
{
"hosts": [
{
"id": "forge",
"name": "Forge",
"ssh": "you@forge",
"defaultCwd": "~/code"
},
{
"id": "studio",
"name": "Studio Mac",
"ssh": "studio.local",
"defaultCwd": "~/Developer"
}
]
}
Tailscale IPv4 addresses and MagicDNS names work like any other SSH destination when OpenSSH can resolve them. Zeus neither requires nor configures Tailscale for remote holder sessions.
How remote sessions work
SSH is only the authenticated, encrypted byte pipe. Zeus uploads a small
Helper (zeus-remote) the first time, then that Helper owns the Agent PTY
on the host. There is no requirement for remote tmux, Node.js, Python, or
a preinstalled Zeus service.
OpenSSH config and a short-lived ControlMaster are used for speed when they already exist. Session survival does not depend on them.
macOS SSH password and host-key prompts go through Zeus's askpass helper. They do not get parsed out of the protocol stream.
Day to day
- New agent on host in the command palette (search the host name) spawns there.
- A hosted session on that host still gets MCP, so it can hire local
children. A laptop lead cannot MCP-spawn onto the host yet. Use the
palette or
zeus session spawn --host. See Orchestration. - Move Session to … in the palette migrates the selected Claude session across hosts (v1 is Claude-only, because resume has to be trustworthy).
- Status, hibernate, Review, and the workflow tree work the same as local.
If the Helper cannot be verified, Zeus fails closed with a structured
error. It will not fall back to tmux.
Prefer a dedicated non-admin account and narrowly scoped credentials. See the security model.
First-party nodes
For provider accounts, fleet usage, and local↔cloud handoff on a VPS, enroll
a zeus-node alongside the SSH host entry. The Settings
form has optional node endpoint, token file, and node id fields for that.
Remote nodes
zeus-node makes a VPS (or another workstation) a first-party Zeus execution
host. Use it when SSH is not enough: you want per-machine Claude/Codex
logins, merged usage in the inspector, and a move/fork of a live thread
between laptop and VPS.
Provider credentials stay on the machine where the CLI runs. Zeus gets a versioned management interface for accounts, usage, provider sessions, and handoff.
SSH is still configured. It is the install/recovery path and the compatibility terminal path. It is no longer the source of truth for identity, usage, or movement.
Most people should start with Remote hosts. Come here when you are ready to treat a VPS as a first-class Zeus machine.
Install on the VPS
The VPS needs Claude Code and/or Codex on PATH, a private Tailscale address,
and systemd user services.
cargo build --release -p zeus-node
./scripts/install-node.sh
systemctl --user edit zeus-node
Set the listener to the VPS's Tailscale address in the override:
[Service]
Environment=ZEUS_NODE_LISTEN=100.64.0.2:7337
Then start it and print the one-time enrollment values:
systemctl --user enable --now zeus-node
zeus-node init
The node config is owner-only and contains its app-layer capability token.
Tailscale encrypts the transport; the token authenticates Zeus at the
application layer. Do not bind the listener to a public interface and do not
copy node.json wholesale.
On the local Mac, put only the printed token in an owner-only file:
mkdir -p ~/.config/zeus
chmod 700 ~/.config/zeus
printf '%s\n' 'PASTE_THE_TOKEN' > ~/.config/zeus/forge.token
chmod 600 ~/.config/zeus/forge.token
In Zeus, open Settings → Remote and add both the SSH fallback and
first-party node fields. The resulting hosts.json entry is:
{
"id": "forge",
"name": "Forge",
"ssh": "you@forge",
"defaultCwd": "~/code",
"node": {
"endpoint": "tcp://100.64.0.2:7337",
"tokenFile": "~/.config/zeus/forge.token",
"nodeId": "node-a1b2c3d4"
}
}
nodeId pins the stable identity. It may be omitted for first enrollment, but
should be saved after the first verified hello.
Individual accounts on each machine
Profiles are labels and identity metadata. An installation is that profile's login on one node. Provider secrets never appear in the profile registry or over the Zeus protocol.
zeus-node account add --provider codex --id personal --label Personal
zeus-node account add --provider codex --id work --label Work
zeus-node account add --provider claude --id personal --label Personal
zeus-node account login --id personal
zeus-node account status --id personal
zeus-node account default --provider codex --id work
zeus-node account list
You can run those commands directly from the local Mac against the VPS. No
interactive SSH shell is required. Add the enrolled connection flags to any
status or account command:
zeus-node account login --id personal \
--endpoint tcp://100.64.0.2:7337 \
--token-file ~/.config/zeus/forge.token \
--node-id node-a1b2c3d4
Codex uses the official app-server device-code/browser flow. The URL and
one-time code are printed where the command runs, so a VPS login completes in
the local browser without copying auth.json. Claude's supported interactive
auth command is streamed through the node; open the emitted URL locally. On
Linux, each Claude installation uses its own CLAUDE_CONFIG_DIR. Claude Code's
macOS Keychain credential is host-wide, so multiple simultaneous Claude
subscription identities on one Mac are intentionally not claimed as isolated.
Codex installations use a separate CODEX_HOME. Sessions bind to an explicit
profile; changing a node default affects new sessions, not a running session.
This is identity selection for legitimate personal/work contexts, not
automatic rate-limit failover.
Instant move and fork
The client handoff coordinator performs:
- target identity/account/capability preflight;
- source checkpoint at a turn boundary;
- content-addressed transfer of only missing blobs;
- target restore into quarantine;
- provider-native resume/fork (
thread/resumeorthread/forkfor Codex; background-agent resume/fork for Claude); - the same location lease committed on target and source.
The live workspace is never overwritten during staging. .git, provider homes,
SSH material, .env*, known credential files, dependency/build directories,
symlinks, oversized files, and special files are excluded and recorded in the
manifest. A failure before commit aborts both sides; a committed move is
reversed with a new move rather than destructive rollback.
The existing session.migrate SSH implementation remains available for old
hosts and recovery.
The same coordinator is available from the management CLI for a node-managed
session. This example moves a Codex thread from the local node to Forge; use
--mode fork to leave the source lease running:
zeus-node handoff \
--provider codex --profile work \
--session zeus-session-id --provider-session codex-thread-id \
--workspace "$PWD" --mode move \
--target-endpoint tcp://100.64.0.2:7337 \
--target-token-file ~/.config/zeus/forge.token \
--target-node-id node-a1b2c3d4
Add --endpoint, --token-file, and optional --node-id when the source is
another enrolled node rather than the local node service. The source and target
may use different provider logins under the same profile label, which makes a
local work installation and a VPS work installation independently tunable.
Fleet usage
Each node keeps usage.sqlite3 in WAL mode. Events are idempotent and
dimensioned by node, profile, session, provider, model, and source. The schema
distinguishes:
- subscription/rate-limit quota;
- estimated API-equivalent cost;
- authoritative billed spend.
Codex account/rate-limit/usage snapshots come from app-server. Node-managed
transcripts are scanned every 30 seconds as the durable fallback. Claude
OpenTelemetry collectors can normalize request events into usage.record;
transcript import remains available when telemetry is not enabled. The desktop
queries every enrolled node and merges today/month provider totals with its
local usage projection. An unreachable node never blocks local numbers and is
retried on reconciliation.
Operations and security
- Run one node per Unix user. Never run it as root.
- Bind only loopback or a Tailscale address. Public TCP is unsupported.
- Keep
node.json,accounts.json, provider homes, and enrollment-token files mode0600/ directories0700. - Provider credentials are node-local. Checkpoints and usage rows contain no auth material.
- Rotate enrollment by stopping the service, replacing
authTokeninnode.json, and updating enrolled token files. - Back up
usage.sqlite3,accounts.json, and provider homes according to provider policy. Checkpoint blobs are disposable caches. - Audit by checkpoint/move JSON records and the SQLite ledger; raw provider auth responses are not logged.
Protocol changes are additive within NODE_PROTOCOL_VERSION = 1. Clients
authenticate with node.hello, verify the pinned identity, and negotiate
explicit capability strings before using a feature.
Updates
The updater is disabled for the current ad-hoc-signed release. It rejects builds that are not Developer ID signed and notarized, including v0.3.0. Until a qualifying release ships, download new versions manually from GitHub Releases.
Once signed releases are available, Zeus will use the flow below. Checks are automatic; installing an update always waits for you.
What you see
Checks run about 20 seconds after launch, then every 6 hours (toggleable in Settings → General → Updates). Downloading and restarting are not automatic:
- A background check finds a release → the sidebar footer shows an Update to … pill. Nothing else happens.
- Click it → Downloading… with progress → the bundle is verified and staged.
- Click Restart to update… → Zeus hands off to a helper and quits.
Zeus holds live agent sessions, so it never relaunches itself uninvited. ⌘K → Check for Updates… and the version row in the account popover both run a manual check and report when you are already up to date.
Trust model
There is no separate updater signing key. A downloaded bundle is accepted only if all of the following hold:
codesign --verify --deep --strictpasses.- Its Team ID and bundle identifier match the running app.
spctl --assess --type executeaccepts it (notarization for a stapled bundle, without a network round trip).- Its short version string equals the version the feed promised.
At the feed layer, only strictly newer versions are offered (no downgrades), and downloads use HTTPS to the releases host. The feed URL is stable:
https://github.com/nnayz/zeus/releases/latest/download/appcast.json
Local cache
Staging lives under:
~/Library/Caches/zeus/updates/<version>/
If the app sits somewhere the user cannot write, the writability check fails before the download starts.
Release packaging steps live in zeus/UPDATING.md
in the repository.
Security model
Zeus is a local developer tool that deliberately launches other powerful local developer tools. It reduces orchestration mistakes; it is not a sandbox.
Trust boundaries
Desktop app and daemon
The app talks to a background daemon over local Unix sockets. The daemon owns PTYs, terminal replay logs, worktrees, child processes, and persistent session state. Socket and state paths are scoped to the current user. Another process already running as that user should be treated as inside the same trust boundary.
The PTY holder lets sessions survive daemon restarts. Compatibility changes to the holder protocol or on-disk registry must preserve existing sessions or ship an explicit migration.
Child tools
Shells, coding agents, hooks, MCP servers, and browser automation run with the macOS user's privileges. They can read any files that user and macOS privacy controls allow, use inherited environment variables, access configured credentials, and make network requests. Zeus does not inspect or approve each operation they perform.
Use separate worktrees to avoid accidental edit collisions, not as a security boundary. For untrusted code, use a dedicated OS account, VM, or container and restrict credentials and network access there.
Remote nodes
Remote sessions cross the SSH boundary and run under the configured remote account. Zeus relies on SSH host verification, keys, and configuration; it does not provide a separate encrypted relay or authorization layer. Prefer a dedicated non-admin user and narrowly scoped credentials.
Updates
The updater downloads a versioned ZIP from GitHub Releases, checks its SHA-256 from the release feed, verifies the code signature, requires the running app's Team ID and bundle identifier, validates notarization, and refuses downgrades. Published release assets are treated as immutable. Details are in Updates.
Sensitive data
Terminal replay logs can contain prompts, output, paths, and secrets emitted by tools. PR monitoring, remote hosts, and third-party agents can send data to their own services. Zeus itself has no account, analytics, or telemetry service; see Privacy.
Security assumptions
Zeus assumes:
- macOS and the current user account are not already compromised;
- installed agents, MCP servers, hooks, and shell configuration are trusted;
- GitHub, Apple code-signing/notarization, Homebrew, SSH, and dependency sources provide the guarantees documented by those systems;
- release operators protect their GitHub and Apple credentials.
Reporting
Report boundary bypasses, unsafe IPC/update behavior, credential disclosure, and unintended code execution to hi@nasrul.info (see the security policy).
Security policy
Supported versions
Security fixes target the latest Zeus release. Keep Zeus and the coding-agent CLIs it launches current.
Report a vulnerability
Email hi@nasrul.info with the subject line
Zeus security.
Include:
- affected Zeus version and macOS version
- minimal reproduction
- expected impact
- any suggested mitigation
Do not attach private terminal output, tokens, or personal paths unless they are strictly required to understand the issue — and mark that mail as confidential.
Acknowledgement should arrive within seven days. Fix and disclosure timing depend on severity and complexity.
Scope
Zeus intentionally runs local shells, coding agents, MCP tools, and optional remote commands. A tool doing something the operator explicitly authorized is not itself a Zeus vulnerability.
In scope:
- permission-boundary bypasses
- unsafe update or IPC behavior
- credential disclosure
- session isolation failures
- unintended remote execution
See the security model for trust boundaries.
Privacy
Zeus has no account system, advertising, analytics, or telemetry. There is no Zeus-operated service that receives your terminal contents or session history.
Data stored on your Mac
Zeus stores session state, terminal replay logs, host configuration, preferences, usage summaries, and search/index data under these locations:
~/Library/Application Support/Zeus~/Library/Application Support/zeus~/Library/Caches/zeus/updates
Terminal logs can contain prompts, command output, repository paths, and secrets printed by a process. Treat them as sensitive and redact them before sharing diagnostics. Archiving can intentionally preserve session metadata. Deleting the directories above removes all Zeus-managed local data after Zeus and its daemon are stopped.
Network activity
Zeus connects to GitHub Releases to check for and download updates. It may also make network connections when you explicitly use remote hosts, PR monitoring, browser automation, or a tool/agent that uses the network. Those tools and services have their own privacy practices. Zeus does not proxy their traffic through a Zeus-operated server.
Remote-node credentials remain in the mechanisms you configure (for example, SSH configuration and your keychain); they are not sent to Zeus.
Process access
Zeus is not sandboxed because its core function is to launch shells and coding agents, create worktrees, and communicate with local tools. Child processes run with your macOS user privileges and may inherit environment variables. Only run agents and MCP servers you trust, and review their permissions separately.
For vulnerability reports, email hi@nasrul.info (see the security policy).
Support
Email hi@nasrul.info for help, bugs, feedback, or security reports.
Diagnostics
zeus doctor
Include with your email:
- Zeus version (the account popover, or Settings → General → Updates)
- macOS version and chip
- agent involved (if any)
- steps to reproduce
- a small, redacted log excerpt
Logs
Daemon logs and session state:
~/Library/Application Support/Zeus
~/Library/Application Support/zeus
These may contain prompts, command output, paths, or secrets printed by a process. Redact before sending.
Screenshot soak test
The default Rust test suite uses a fake capturer and never requests macOS
Screen Recording permission. To exercise a real Zeus window deliberately, run
this from zeus/ while the Zeus app has an open window:
ZEUS_SCREENSHOT_SOAK=1 cargo test -p zeus-engine real_window_soak_is_explicitly_opt_in
macOS may ask for Screen Recording permission for Zeus. The test captures one 720p JPEG in memory, stops the stream immediately, and writes no screenshot file, so there is no artifact cleanup. Remove Zeus under System Settings → Privacy & Security → Screen Recording if you also want to clear the grant.
Roadmap
Direction only — not a release calendar.
Zeus is the attention and lifecycle layer for a fleet of coding agents. It sits above Claude Code, Codex, Cursor, Gemini, and shells: a native macOS control plane that keeps real PTYs alive, tells you which sessions actually need you, and is where you accept the work. It is not an IDE, not a model, and not a hosted agent.
The durable work is:
- Status you can leave the room on. Zeus reads the PTY grid, hooks, process facts, and title/progress, then reduces them to working / needs-you / done. Status is not a vendor API. The manifest catalog and the status reducer are how that knowledge ships.
- Sessions that survive the app, the Engine, and SSH. Holders own the PTY.
Quitting the window, restarting the daemon, or dropping a remote connection
must not kill the agent. Remotely, Zeus bootstraps a Helper over
ssh -Tand owns the remote PTY — notmux, no preinstalled service. - An agent-agnostic control plane. A new agent is a manifest: spawn, resume, approve/deny keys, screen rules. Worktrees isolate git collisions. MCP lets one agent spawn, wait on, prompt, and read another.
Everything on this page either deepens those three, or is explicit work we will not take.
Now
Harden what already makes Zeus usable as a fleet cockpit.
- Session persistence and Engine upgrades that stay boring and recoverable. Holders keep the PTY and agent process tree across app quit, Engine crash, and Engine upgrade. Screen checkpoints stay a cache: a bad file is a miss, not a lost session. Upgrade and recovery paths must restore the same process identity and the same terminal snapshot.
- Broader first-class agent manifests and status detection. Claude Code and Codex already have first-class status and resume. Other catalog agents should move toward the same: working / blocked-permission / blocked-question / idle / exited, with anti-flicker, blocker arbitration, and captured prompt text. Status quality is the product. A spinner that lies is worse than no spinner.
- Stronger release supply-chain checks. Signing, notarization, and the update feed stay a release gate. The updater already verifies SHA-256, signature, Team ID, bundle id, notarization, and refuses downgrades.
Next
Make “I can run more agents than I can watch” true.
Needs-you inbox
Status detection is the engine. The inbox is the product.
One queue across every live session — local and remote — of the things that actually need a human:
- permission prompts, with the captured prompt text and a risk label
- questions and confirmations
- failures and unexpected exits
- done-with-diff (the session finished and produced a change)
Triage is keyboard-first: approve, deny, jump to the session, snooze, or dismiss. One keystroke should clear a permission the way Superhuman clears mail. The sidebar remains the map of the fleet; the inbox is the work.
This is not a notification dump and not a second chat transcript. If the reducer cannot name the blocker, the inbox must not invent one.
Accept-the-work surface
Agents produce. Zeus is where you accept.
Each session that edits a repo should have a review cockpit bound to its worktree: live diff, stage, commit, PR, conflict view, this-agent-branch vs main. Existing git review and PR monitoring fold into that surface rather than living as separate toys.
A fleet without a merge surface is expensive chaos. Worktrees stay the isolation mechanism, not a security boundary: they prevent edit collisions so several agents can work the same project at once. Treat each worktree as a normal checkout — commit or move changes before deleting it.
Status catalog
Whoever has the best “is it stuck?” detection owns the category.
- First-class manifests for every serious CLI agent, kept current as their TUIs change.
- Hooks where the agent has them; screen rules where it does not.
- A new agent remains a JSON file: spawn, resume, approve/deny, screen rules. Adding a catalog entry must not require Engine code.
- Missing or stale rules fail soft (bare login shell / running-or-exited), never invent a confident wrong state.
This is a data moat that can grow without telemetry. Community or auto-updated rules are in scope; shipping session contents off-box is not.
Remote as a first-class machine
The Remote Holder is a rare technical asset. “Run this on the 64-core box” should be as cheap as local: one host picker, the same status, the same inbox, the same persistence.
- Clearer remote-host and remote-node setup and diagnostics. Probe, bootstrap,
persistence capability (
native-detach/user-supervisor/non-persistent), and structured transport errors must be explainable in the UI, not only in logs. - Instant move and fork between laptop and an enrolled
zeus-node(the existing handoff coordinator): checkpoint at a turn boundary, transfer only missing blobs, restore into quarantine, provider-native resume or fork, commit the location lease. The live workspace is never overwritten during staging. - The Mac stays the glass. Compute lives wherever it is cheapest or most
persistent. SSH remains the authenticated byte transport; Zeus never
reintroduces
tmuxas a remote session fabric.
Human-gated agent-to-agent
MCP spawn / list / status / send / wait / read / release is the seed of an OS for agent work. Unsupervised swarms are a liability. Supervised swarms are the wedge.
Make orchestration a first-class object, not a hidden tool call:
- named jobs (“three worktree-isolated agents, stop at PR”)
- parent/child lineage visible in the sidebar and inbox
- allowlists for who may spawn whom, on which host, in which project
- budgets (see fleet cost below)
- a paper trail of who spawned whom and what was sent
Do not add a multi-session remote supervisor or turn zeus-remote into a
second Engine. Orchestration stays in the local Engine; the Helper stays a
Helper.
Later
These compound the same loop once the inbox, accept surface, and status catalog are trustworthy.
Notifications that close the laptop
Desktop — and later phone — alerts only on needs-you or done, carrying the
actual blocker text. Quiet hours. Per-project and per-agent mute. Persistence
plus a page is how Zeus becomes all-day infrastructure instead of a window you
stare at.
This is not a firehose of token activity. Working sessions stay silent.
Fleet memory
Search across session titles, captured prompts, and terminal history: “what
did the Codex on auth-rewrite decide about JWT?” Jump to that screen offset.
A week of parallel agents becomes recoverable memory, not forty dead tabs.
Replay stays local. Terminal logs already can contain secrets; search must not create a new exfiltration path, a Zeus-operated index, or a requirement to keep unbounded raw logs.
Cost and quota as control
Usage accounting and the resource governor already exist. The feature is policy, not another chart:
- pause a provider when weekly quota hits a threshold
- cap a project or profile at a daily spend
- freeze the oldest idle session first when the machine budget is hit (the governor already hibernates unattended idle sessions)
- show spend and quota next to status, including merged totals from enrolled nodes
Parallel agents die on surprise bills. The orchestrator that prevents that becomes required. An unreachable node must never block local numbers.
Read-only observers
The current baseline is exactly one live attach/controller. A new attach revokes the old one. That remains correct for input.
A later enhancement is read-only spectators: a teammate or a second device watches a live session without resizing the PTY or injecting keystrokes. Share a session, not a screenshot. This is how Zeus becomes a team product without becoming a hosted SaaS. Multi-controller input and a Zeus-operated relay stay out of scope.
Cross-platform Engine
The desktop app is macOS. The Engine, Holder, and Remote Helper are already Rust. Broader Engine coverage (Linux as an execution host and, later, as a headless cockpit) extends the same ownership model. It does not reopen the transport, reintroduce Swift, or make a hosted Zeus account a prerequisite.
Distribution
- Signed, notarized GitHub Releases
- Homebrew cask (monorepo tap):
brew tap nnayz/zeus https://github.com/nnayz/zeus.git && brew install --cask nnayz/zeus/zeus - Deeper end-to-end coverage for updates and session recovery, including the existing remote soak and Helper-native probe gates
Not planned
These fights are already lost, or they contradict the product.
- A hosted Zeus account, analytics, or telemetry service. There is no Zeus-operated relay for terminal contents or session history.
- Treating agent processes as a security sandbox. Zeus launches powerful local tools with the user’s privileges. Isolation is an OS account, VM, or container — not a Zeus feature.
- Becoming an IDE. Zed, Cursor, and VS Code win the editor. Zeus owns fleet attention, PTY lifecycle, and accept-the-work.
- Becoming an agent or a model vendor. Claude Code, Codex, Gemini, and the rest win the conversation. Zeus stays above them.
- A Zeus Cloud that runs your agents for you. Remote execution is your SSH host or your enrolled node, on your credentials.
- Reintroducing
tmux,screen, orzellijas the remote session transport. The Remote Holder is the only remote transport. - A multi-session remote Zeus supervisor, or growing
zeus-remoteinto a second Engine. Hooks, MCP forwarding, artifacts, ports, usage, handoff, checkpoints, and resource governance stay local-Engine concerns unless this document andzeus/REMOTE_PORT.mdare revised together. - Requiring Node.js, Python, or a preinstalled Zeus service on the remote host for the default SSH path.
- Host-wide configuration: no
sudo, package installation, PAM/sshd changes, system services, or persistent user units as a setup step.