Appearance
Supported Code Agents
Otty integrates with the coding-agent CLIs you run yourself. You keep using the agent exactly as you would in any terminal — Otty plugs into it so the tab badges, notifications, history, resume, and (where the agent supports it) fork all work. The available features depend on the agent, as shown below.
| Agent | Command | How Otty connects | Resume | Fork | History | Usage | Quota |
|---|---|---|---|---|---|---|---|
| Claude Code | claude | Hooks in ~/.claude/settings.json | ✓ | ✓ | ✓ | ✓ | ✓ |
| Codex | codex | Hooks in ~/.codex/hooks.json (+ hooks = true in config.toml) | ✓ | ✓ | ✓ | ✓ | ✓ |
| OpenCode | opencode | Plugin in ~/.config/opencode/plugins | ✓ | ✓ | ✓ | ✓ | — |
| Cursor CLI | agent | Hooks in ~/.cursor/hooks.json | ✓ | — | ✓ | — | — |
| Kimi Code | kimi | Hooks in ~/.kimi-code/config.toml (TOML [[hooks]]) | ✓ | — | ✓ | ✓ | — |
| Pi | pi | Extension in ~/.pi/agent/extensions | ✓ | ✓ | ✓ | ✓ | — |
| omp | omp | Extension in ~/.omp/agent/extensions | ✓ | ✓ | ✓ | ✓ | ✓ |
| Grok Build | grok | Hooks in ~/.claude/settings.json (Grok reads it too) | ✓ | ✓ | — | — | — |
| Reasonix | reasonix | Hooks in ~/.reasonix/settings.json | ✓ | ✓ | — | — | — |
| CodeBuddy CLI | codebuddy | Hooks in ~/.codebuddy/settings.json | ✓ | — | — | — | — |
| Google Antigravity CLI | agy | Hooks in ~/.gemini/config/hooks.json | ✓ | — | — | — | — |
| GitHub Copilot CLI | copilot | Hooks in ~/.copilot/hooks/ | ✓ | — | — | — | — |
| Any other agent | your CLI | Custom integration: otty state:<name> from your own hook | — | — | — | — | — |
Installation is one click: the first time Otty needs the integration it asks to install the hook or plugin into that agent's own config — it won't touch your other settings. See Setup to install, manage, or remove it.
Running something that isn't on this list? It can still report itself to Otty and get the badges and notifications — see Custom agents.
Platform support
The built-in agent catalog, lifecycle hooks, session resume and supported fork commands are available on macOS, Linux and Windows. History discovery covers Claude Code, Codex, OpenCode, Cursor, Kimi, pi and omp, including Codex's CODEX_HOME and Kimi's KIMI_CODE_HOME overrides. OpenCode history supports both the legacy file store and the current SQLite database; Otty reads the database without modifying it and stores history pointers in its own user cache.
Linux and Windows expose session and prompt history through Open Quickly. Session usage follows the table above; plan quota is available for Claude, Codex and omp. Claude's plan file can be opened from the agent actions. Automatic restore keeps the saved terminal output when Claude's transcript is missing or empty, or when the session is still running as a background job.
Automatic permission approval is a separate platform feature: macOS has the AI reviewer, Linux currently uses configured tool rules, and Windows does not yet provide automatic approval.
Usage and plan quota
The last two columns are about numbers rather than control: how much a session has spent, and how much of your plan is left. They come from what each agent already records, so what you get differs per agent — which is why they are tracked separately from Resume and Fork.
Usage is the session's own accounting, shown in the agent's group in the details panel (⌘I): how full the context window is, the running token total, and — for the agents that compute one — what the session cost. It is read out of the log that agent already writes to disk. There is nothing to enable, nothing leaves your machine, and an agent that logs none of it simply shows no numbers.
Quota is your plan's remaining allowance, and only Claude Code, Codex and omp can answer for it. It is a separate column because it is a separate kind of read: Otty runs that agent's own CLI in the background — claude -p "/usage", codex app-server, omp usage --json — every few minutes, using the login the CLI already has. All three are on out of the box; Show Plan Quota on the agent's card under Settings (⌘,) → Agents turns one off.
The agents with a — in Quota aren't being neglected: OpenCode and pi bill per use and publish no ceiling to draw a bar against, and the rest expose no way to ask. See Usage readout for what each agent reports, and for how the bars are coloured.
Custom launch commands
Expand an agent under Settings → Integrations to override the command Otty uses when it starts, resumes, or forks that agent. This is useful for wrappers, absolute executable paths, and global flags. Otty appends the agent-specific session arguments, so enter claude --dangerously-skip-permissions, not a full claude --resume <id> command. Leave the field empty for the built-in default.
The same override can be written in the config file:
ini
agent-command = claude=claude --dangerously-skip-permissions
agent-command = codex=/opt/homebrew/bin/codex --profile workClaude Code
Anthropic's Claude Code CLI. Otty adds hook entries to ~/.claude/settings.json that report each turn's state (processing, idle, awaiting input).
- Resume reopens a past conversation with
claude --resume <id>. - Fork branches it into a new session with
claude --resume <id> --fork-session. - Transcripts live as JSONL under
~/.claude/projects/…, so History can search and reload them.
Codex
OpenAI's Codex CLI. Otty installs hooks into ~/.codex/hooks.json.
- Codex only runs hooks when the
hooksfeature is enabled in~/.codex/config.toml. Otty turns it on when it installs the hooks; if it ever gets switched off, Otty offers a one-click re-enable (then restart Codex in that tab). - Resume uses
codex resume <id>; Fork usescodex fork <id>.
OpenCode
The self-hosted OpenCode agent. Instead of hooks, Otty installs a small plugin into ~/.config/opencode/plugins.
- Resume uses
opencode --session <id>; Fork usesopencode --fork --session <id>. - Heads-up: OpenCode doesn't announce a session when you switch to it via
/sessions— Otty only picks it up once you send a message in that session. If a freshly-switched tab looks unlinked, type something and it connects.
Cursor CLI
Cursor's terminal agent, launched as agent (cursor.com/docs/cli). Otty adds entries to Cursor's JSON hooks in ~/.cursor/hooks.json that report each turn's state.
- Resume reopens a past conversation with
agent --resume <chatId>. - Fork is not offered — Cursor has no CLI fork command, so the Fork action stays greyed out.
- Transcripts live under
~/.cursor/projects/…/agent-transcripts/, so History can search and reload them.
Kimi Code
The kimi CLI (moonshotai/kimi-code). Its config home is ~/.kimi-code (override with $KIMI_CODE_HOME). Kimi exposes Claude-Code-style lifecycle hooks declared in TOML, so Otty adds an [[hooks]] entry to ~/.kimi-code/config.toml.
- Resume uses
kimi --session <id>. - Fork is not offered.
- Sessions are stored under
~/.kimi-code/sessions/…, so History can reload them.
Pi and omp
Pi (pi) and omp (omp) share one codebase — omp is a rebrand of pi — and both load TypeScript extensions the way OpenCode loads plugins. Otty installs one extension into ~/.pi/agent/extensions or ~/.omp/agent/extensions that reports each turn's state.
- Resume reopens a specific session with
pi --session <path>(omp --session <path>). - Fork branches it into a fresh session with
pi --fork <path>(omp --fork <path>). - Like OpenCode, pi/omp report the session id through the extension rather than a per-process file, so a freshly-switched tab links up once the agent emits its next lifecycle event.
Grok Build
xAI's grok CLI (x.ai/news/grok-build-cli). Its config home is ~/.grok (override with $GROK_HOME), but its hooks don't live there: the only user-wide hooks Grok reads are the ones in Claude Code's ~/.claude/settings.json, which it loads as a compatibility layer. That's where Otty installs the Grok integration — as its own entries, alongside (never on top of) anything already in that file. Grok's own hooks/ folder is per-project (.grok/hooks/ inside a repo) and a hook Otty put in ~/.grok/hooks/ would simply never run.
- Resume reopens a past conversation with
grok --resume <id>. - Fork branches it into a new session with
grok --resume <id> --fork-session. - Session history isn't wired up yet, so Grok sessions don't appear in History or Open Quickly.
- Because that file is shared, every agent's Otty hook in it can be started by the other agent's runner. Each one checks who invoked it and stands down when it isn't the right agent, so the badge always names what's actually running.
- Grok needs to trust a folder before it runs any hook there (it asks the first time, and
/hooks-trustdoes it by hand). Until you accept, the tab shows no badge.
Reasonix
The DeepSeek-native reasonix CLI (reasonix.io). Its config home is ~/.reasonix (override with $REASONIX_HOME). Reasonix runs shell commands on its lifecycle events, so Otty adds its entries to the hooks section of ~/.reasonix/settings.json and leaves everything else in that file untouched.
- Resume reopens a past conversation with
reasonix --resume <id>. - Fork continues in a copy with
reasonix --resume <id> --copy, leaving the original transcript alone. - Reasonix also reports when it's waiting for your approval, so the tab shows the awaiting-input badge — not just processing and done.
- Reasonix loads hooks when a session starts, so restart
reasonixin that tab after installing. settings.jsonis shared with Reasonix's own Hooks editor, so Otty won't rewrite it if it can't read it. If Install won't stick, the file has a syntax error — fix it (Reasonix ignores your hooks too while it's broken) and install again.- Resume looks up the conversation in the session store of the directory you started in, so run it from the same project directory.
- Session history isn't wired up yet, so Reasonix sessions don't appear in History or Open Quickly.
CodeBuddy CLI
CodeBuddy CLI runs as codebuddy. Otty adds its lifecycle hooks to ~/.codebuddy/settings.json, preserving existing settings and hooks.
- Resume uses
codebuddy --resume <id>. - After installing hooks, open CodeBuddy's
/hookspanel to review and activate external changes. On Windows, CodeBuddy runs its hooks through Git Bash.
Google Antigravity CLI
Antigravity CLI runs as agy. Otty adds a named group to ~/.gemini/config/hooks.json to report processing and completion. A stop with background tasks still running keeps the processing badge active.
- Resume uses
agy --conversation <id>. - Otty does not install tool permission decision hooks for Antigravity.
GitHub Copilot CLI
GitHub Copilot CLI runs as copilot. Otty installs a hooks file under ~/.copilot/hooks/, or $COPILOT_HOME/hooks/ when configured. It reports turn state and actual permission or input prompts; unrelated notifications do not set the awaiting-input badge.
- Resume uses
copilot --resume <id>. - This integration targets GitHub's standalone coding agent CLI.
Otty does not yet offer transcript history, usage/quota readouts, or a Fork action for these three integrations. Their own interactive commands remain available inside the terminal.
Custom Agents
The list above is what Otty ships adapters for — it isn't the limit. The tab badges and notifications are all driven by one CLI call, so any coding agent that can run a command when a turn starts and ends plugs into the same UI, with no change on Otty's side:
bash
otty state:myagent state=processing agent-pid=$$ session-id=abc123 label="My Agent"
otty state:myagent state=idle agent-pid=$$ session-id=abc123 label="My Agent"The name after state: is the agent id. An id Otty ships an adapter for (claude, codex, …) gets the full integration described above; any other id is treated as a custom agent — it drives the lifecycle badge and notifications under the name it reports, and nothing else.
The otty command has to be on your PATH: install it from Settings → Shell → Install CLI (see Install the CLI).
Arguments
| Argument | Required | Meaning |
|---|---|---|
state= | yes | processing — a turn just started · idle — the turn finished · awaiting — the agent is waiting for your approval or input · error — the turn failed |
agent-pid= | on the first event | PID of the agent process, used to pin the event to a pane. In a hook script "$PPID" is the agent that invoked it; if your agent calls Otty directly, pass its own pid. |
session-id= | recommended | A stable id for the conversation. Once a pane has seen it, later events carrying the same id land on that pane even without agent-pid. |
label= | optional | Display name for badges and notifications. Defaults to the capitalized id, so state:myagent reads as "Myagent". |
How Otty picks the pane
Otty matches an event to a pane by process tree: the reported agent-pid has to be a descendant of some pane's shell. That's deliberate — an event whose pid belongs to no pane is dropped, so the same agent running outside Otty (a desktop app, an editor extension) never badges an unrelated tab.
Built-in agents also have a cwd + process-name fallback, because Otty knows what their binaries are called. A custom agent has no such fallback, so its first event must carry agent-pid, otherwise there's nothing to match on and the call reports that no tab was found.
What a custom agent gets
- The processing / awaiting / done tab badges, and the Dock progress spinner.
- System notifications when a task completes and when the agent starts waiting for you.
- Correct ordering under Updated Time tab sorting, and keep-awake while a turn runs.
All of it honours the same per-tab switches as the built-in agents, so a tab whose agent badges or notifications are turned off stays quiet — see Notifications.
Not included: Resume, Fork, History, and auto-approve stay adapter-only. They need Otty to know how to relaunch the agent, where it stores transcripts, and which keystrokes answer a permission prompt — none of which a state report can carry.
Example: a hook script
Most agents can run a script on lifecycle events. Point them at something like this — it's the shape of Otty's own bundled hooks:
sh
#!/bin/sh
# $1 = processing | idle | awaiting
otty state:myagent \
state="$1" \
agent-pid="$PPID" \
session-id="$MYAGENT_SESSION_ID" \
label="My Agent" 2>/dev/null &Background it and swallow errors, as above: reporting state must never block — or break — your agent when Otty isn't running.
Resume without an integration
An agent that wants its sessions to survive a terminal restart can adopt the Terminal Resume Protocol (OSC 88). It's a vendor-neutral, open spec, so any tool that emits it gets resume in Otty without a bespoke integration.
Want your agent supported as a built-in, or building one that should plug in? Get in touch at otty@appmakes.io.
See also
- Setup — install and manage the integration per agent.
- Working with Code Agents — what the integration gets you.
- History · Fork / Branch Session — resume and branch any captured session.