Open source · MIT · Single user · Local-first

An external control surface
for the agent you already run

The engine keeps running on your own machine. From the browser you watch it work, manage its tools and models, cut in mid-turn — and when you need to, open a file, start a shell, or mark the exact spot on a page that should change. Single user, loopback only, no database: the source of truth stays the engine's own session files.

npm -g install oh-my-agent-web
See the UI
pi / Codex / Claude Code / opencode / DeepSeek Harness Windows · macOS · Linux Node ≥ 22.19
127.0.0.1:25257 · demo-app
A real session: projects and sessions on the left, thinking blocks and tool cards in the middle, the diff of the same repo on the right

A real session: thinking, tool calls, the diff and usage in one screen.

What it is

Not another agent engine,
and not a SaaS for your sessions

It doesn't rewrite your prompt and doesn't take over tool implementations — you install pi, Codex, Claude Code or opencode, and the workbench gives them a readable UI, clickable buttons and a session list that lives on disk. Three hard rules shape everything you see.

01 / NO DATABASE

No database

Sessions are the engine's own JSONL / threads. The web UI reads them, renames them, deletes them — it never keeps a second copy.

02 / NO FAKING

No faking

If an engine can't do something, the button isn't drawn (capability matrix). If a panel has no data, it says so instead of borrowing another engine's config.

03 / NO OVERREACH

No overreach

Listens on 127.0.0.1 by default. Remote access means an explicit -H 0.0.0.0 and a password set on the machine itself.

One conversation

The process is laid out,
not hidden behind a spinner

Thinking blocks, tool calls, changed files, tokens and cost all live in the transcript — and the composer stays usable while a turn is running.

See how it reasoned and what it did

Tool cards carry arguments, the full command, output, duration and status. When a turn finishes they fold into one line — “3 thinking · 5 tools · took 20s” — and unfold into the full timeline.

✓The footer is this turn's usage: in / out / cache / cost, with one click to copy.
✓Changed-file chips: which files this turn touched; click one to land on the diff.
✓Clickable paths: src/App.tsx in prose opens the preview.
The footer of an answer: a markdown table, changed-file chips, and this turn's tokens and cost

Steer, queue, stop

The composer never locks while a turn runs: steer takes effect immediately, queue waits for this turn to end, stop keeps whatever was already produced.

# running › look at how store.ts persists # you cut in › switch App's subscription too steered # and queued one more › add a test afterwards queued 1
steerqueuestopfalls back to queue on other engines

Mark the passage, leave a note

Select any passage and a small toolbar appears: add it to the session, annotate it, or ask about it in a temp chat. The passage keeps a ①②③ badge and the composer grows an “N notes” capsule.

After annotating: a numbered badge in the text and an “N notes” capsule in the composer

@ for files, / for commands

Type @ to search the workspace, ↑↓ to pick, Enter to insert @src/store.ts. Type / for local commands (new, rename, model, session stats) or ones handed straight to the agent (compact, plan mode).

The @ mention panel, grouped into “Add” and “Recent”
Right-hand workspace

Read files, run commands,
and mark “change this” on the page

A multi-tab workspace on the right: file preview, diff, a real terminal, an embedded browser and temp chats. The first three are for review; the browser is for development.

Files & changes

Directory tree, search by filename, full-text search (with masks like web/src/**); previews cover markdown, mermaid, images, PDF, audio and video. Switch to “Changes” for a diff against HEAD: a +10 −1 summary, line-level red/green, or changes only.

✓Select lines and “add to conversation” writes @src/store.ts:120-138
✓Read-only by design: agents or the terminal edit files, this pane verifies
The diff view: +10 −1 against HEAD, with line-level red and green

A real terminal

The terminal is a real PTY (node-pty + xterm.js): vim, top, Ctrl-C, colours and line editing all behave, and the cwd follows the session's project. Refreshing the page ends the PTY; switching tabs does not.

zshcoloursCtrl-Ccwd follows the session
demo-app on main $ git status -s M src/App.tsx M src/store.ts $ git diff --stat src/App.tsx | 5 +++-- src/store.ts | 11 ++++++++++- $ npm test -- --run ✓ src/store.test.ts (3 tests) Tests 5 passed (5)

The web loop: open, mark, hand it over

Open a local page in the right pane (requests go through a local proxy, cookies stay out). Hit 📍 next to reload to enter pick mode: click the spot that should change, write one line right there, and the page keeps a ①②③ badge. Mark several spots in a row; they all arrive as “N notes”.

✓Marks come back: on reload or navigation they are re-drawn from their selectors.
✓Numbered per page: 1, 2, 3… never renumbered; Esc leaves pick mode.
✓Separate from notes: page marks stay on this machine; sent notes clear.
A campaign page opened on the right, its title marked ①, and “1 note” in the composer
Configuration

Models, skills, MCP, plugins, subagents —
all follow the current engine

Switch to Codex and these panels read Codex's own data. A panel that isn't wired up says so, instead of showing pi's config.

Models panel: providers with endpoints and a model allow-list

Models & providers

OAuth subscription logins, built-in providers, custom endpoints and API shapes; tick the models you want. Keys never leave the server — only the last 4 characters come back.

Skills panel: installed, enabled and disabled skills, with the SKILL.md summary

Skills

Reads ~/.agents/skills; enabling or disabling renames the file, with no second state file. Skill Hub adds search and one-click install.

MCP panel: global and project configs, exposure, connection test

MCP

Global and project configs, project entries override; four exposure modes; “Test connection” does a real handshake and reports the tool count.

Subagents panel: templates, default concurrency and an enable switch

Subagents

Built-in explore / general-purpose / plan, editable and disableable; concurrency 1–12 with the rest queued. Every subagent is a real session.

Plugins panel: pi package states and per-package disable

Plugins

Plugins are pi packages: npm, git or local directories, in four states loaded · installed · missing · disabled. Disabling doesn't delete files.

Push panel: local push state, target devices and a test push

Push & voice

One push when a turn ends (prefixed ❌ on failure, ⏹ on interrupt) that opens the session; four event sounds plus offline local TTS.

Tour

Five regions, one job each

Projects and sessions on the left, the transcript in the middle, the workspace on the right, and “how this turn runs” at the bottom. Every entry point can be hidden in settings.

127.0.0.1:25257
Full UI

Projects and sessions · transcript · source view · status bar

Multiple engines

Each one runs its own native loop

An engine is not “the same prompt in a different skin”: each is wired to its official loop, and capability differences hide buttons in the UI.

pinative SDK · default
Codexapp-server · JSON-RPC
DeepSeek HarnessACP
opencodeACP
Claude CodeACP adapter
Capabilitypicodexdshopencodeclaude
Approvals✓✓✓per config✓
Model / thinking level✓✓✓✓model only
Resume history✓✓✓✓✓
Steer✓————
Subagent panel✓————
Workbench manages providers✓————
Temp chat (in memory)✓————
Get started

Two commands, and you have a workbench

Requires Node ≥ 22.19. It installs three equivalent commands: oh-my-agent-web, aw and agent-web. On Linux the embedded terminal needs node-pty built locally (make / g++ / python3).

Install

npm -g install oh-my-agent-web, or the one-line script that keeps everything under ~/.oh-my-agent-web without touching system npm.

Run

In your project, run aw: it starts in the foreground and opens the browser, listening only on 127.0.0.1:25257.

Use

Hit “New session” and send the first message. To reach it from a phone or another machine, use -H 0.0.0.0 and set a password under Settings → Remote first.

Terminal
# install
npm -g install oh-my-agent-web

# start in your project (foreground + open the browser)
cd ~/code/my-proj
aw

# run detached, check status, stop
aw -d
aw status
aw stop

# another port / a specific workspace
aw -p 25258
AGENT_WEB_CWD=~/code/my-proj aw
awForeground, opens the page (Ctrl-C to quit)
aw -dDetached; logs go to daemon.log
aw statuspid / port / engine / sessions / workspace
aw -H 0.0.0.0Allow remote access (set a password first)
Security model

By default it lives on loopback

A single-user tool deserves a boundary small enough to explain: who gets in, how, and what happens when they fail.

1
Local is password-free, everyone else is not

Loopback peer and loopback Host is let in; any other source is rejected until a password exists.

2
The password can only be set locally

A remote visitor can't set the first password — otherwise whoever scans the port first owns it. It is stored in the data dir and takes effect immediately.

3
Three wrong tries pause logins for 30 minutes

Attempts and duration are configurable (1–20 tries / 1–1440 minutes). The lock persists across restarts, and Settings shows the login activity.

4
Tools and commands go through approvals

Read-only tools pass automatically; the rest ask per “tool + target”. “Always allow” writes to approval-rules.json, and a finished turn clears pending approvals.

5
The web proxy carries no cookies

The iframe sandbox omits allow-same-origin, so remote JS can't reach the workbench's storage or API.

Remote access = two things

-H 0.0.0.0 lets the outside in; the password keeps people out. Domains, LAN IPs and public IPs are treated the same — no extra allow-list.

Where data lives

Sessions stay in the engine's own directory (pi: ~/.pi/agent/sessions). The workbench only keeps settings.json, the lock file, logs, push subscriptions and local UI preferences. Open it on another device and you see the same session files.

FAQ

Questions people ask

Does it copy my Claude Code / Codex sessions somewhere?

No. It reads the engine's own session files or threads, and only displays, renames or deletes them. It keeps no second database and doesn't touch the engine's prompt or tools.

Is my code uploaded anywhere?

Not by the workbench. Only the model providers you configure receive requests; there is no relay service in between.

Why is it local-only by default?

Because it can run commands and read/write files. Listening on 127.0.0.1 means “anyone who can open this page could already operate this machine”. Remote access is an explicit -H plus a password.

Does it work on a phone?

Yes. Narrow screens become a single column, the sidebar turns into a drawer, and the composer is 18px so iOS doesn't zoom. For remote use: -H 0.0.0.0 plus a password; push notifications need https (an installed PWA works).

Which platforms are supported?

macOS, Linux and Windows. On Linux the embedded terminal needs node-pty compiled in place — install make / g++ / python3, or let the one-line script pass --with-build-tools.

Subagents versus temp chats — what's the difference?

A temp chat is a channel a person opens: nothing is saved, it disappears when closed, and it can be saved as a real conversation. A subagent is a task the agent delegates: it has its own context and session file and reports back.

Why are some panel buttons greyed out?

That's the capability matrix: semantics the current engine doesn't support (say, steering on non-pi engines, or the subagent panel) simply aren't drawn, instead of sending a command that is bound to fail.