An agent-agnostic GUI for coding agents — a chat panel inside VS Code, or a browser UI served by a small NestJS host. It works with Pi and OpenCode, and stays engine-neutral: one session list, one transcript, one set of shortcuts, regardless of which agent is driving.
Whether you search for a Pi GUI, an OpenCode GUI, a VS Code Pi extension, a VS Code OpenCode client, a web UI for Pi/OpenCode, a comfortable UI for Pi, or a comfortable UI for OpenCode, Morse is the same comfortable interface.
It is built agent-agnostic on purpose: Pi and OpenCode are the engines today, and the same session list, transcript and UI are ready to host more (Grok Bot, Hermes, and other agents) as integrations land — no fork of the interface.
Pi normally lives in your terminal as a TUI; OpenCode can run as a TUI or a server. Morse gives either agent — its models, tools and sessions — a real interface without reimplementing any of it. This project doesn't embed an agent; it talks to each one through its own RPC/API, which is why you install the agent you want to use yourself.
VS Code extension:
Browser host:
Both clips run the same agent, transcript, and protocol; only the host differs.
I will update the new demo once everything is settled.
Morse started as a vibe-coded prototype, but not anymore. I fell in love with this app and got serious about making it genuinely useful and productivity-boosting. Now I've started carefully refactoring the codebase and engineering it heavily instead of just vibing.
- Two engines, one session list — pi and OpenCode drive the same sidebar, transcript and tabs. A session's
id belongs to Morse and records which engine holds its conversation, so reopening it returns to that engine.
pi is the default;
MORSE_ENGINE=opencode/morse.enginestarts new sessions on OpenCode when it is installed or a server is configured. - Pick the engine and the mode — an empty session offers every installed engine, and switching re-reads the
chosen engine's model/mode catalogs before the first prompt. An OpenCode session offers its primary agents
(
build,plan, and any you define) and can switch between them while it runs; the default follows your OpenCode configuration, not a Morse constant. - Multiple sessions across multiple projects — one gateway per session, kept warm (LRU), alive while you switch projects or reload the page. An In progress section lifts the sessions working right now, and a refresh reattaches and replays the transcript.
- A real transcript — markdown with highlighted, copyable code blocks; tool calls as a compact tree by default (one summary line per turn, steps and their files nested under it — the always-open timeline is one toggle away); thinking that streams as it arrives; paged history for long sessions.
- Steer while it works —
steer, follow-up and abort. A prompt sent mid-run is queued as a follow-up above the composer (Queued messages: edit, send now, remove) rather than refused, and runs when the current turn settles. Context compaction is a click away, with a confirmation. - Model & thinking that follow pi — pick any model pi is configured with; the thinking picker mirrors the
levels the current model supports in pi's own TUI and re-reads them on every switch, and a model added to
models.jsonappears when you open the picker — no reload, no restart. - Edit or fork what was sent — edit-and-resend forks before a past prompt and sends the rewrite; fork branches there and hands the prompt back to the composer. The old branch stays resumable.
- Attach context the way each host can — editor selection and live selection chips in VS Code; drag, drop
and pasted images everywhere; browser uploads land next to the session and ride as
@mentions. @mentionanything — a gitignore-aware picker for files and directories (@docs/drills in), opened with+or by typing@, with markdown formatting in your own prompts too.- Native interactions in VS Code — single-value interaction requests become QuickPick/InputBox there, and are rendered inline in the browser. A multi-field form is always rendered in the panel, because no native dialog can express it.
- Git, files and a terminal where there is no editor — on the browser host, a git panel (commit list, branch graph, uncommitted changes), an Explorer and a terminal, with read-only previews, diff views, and line ranges you drag to pin into your next message. VS Code keeps its own Explorer, editor, Source Control and terminal.
- Manage MCP servers — an indicator in the chat toolbar opens a manager for the servers pi sees for the
session's directory: their state, tools and errors, plus add, remove, enable and disable. In project scope,
disabling a user-level server writes a project override — the same file pi's own
/mcpwrites. - Prompt templates with a form — a
/<template>opens a generated form with a live preview, and a template file added or edited shows up without restarting pi. - Keyboard first —
Ctrl+Alt+…(⌘⌥…on macOS) starts a session, narrows the sidebar to a project, changes the model or the thinking level, toggles the git panel (browser host), and opens the compaction question;/jumps to the session search and?prints the whole list.
Morse does not ship an Agent Client Protocol engine yet. That is a deliberate decision, not an oversight. ACP standardises the conversation itself — sessions, prompts, streaming, permissions, cancellation, models, modes and commands — and that is genuinely useful. But the depth Morse needs around that conversation is still missing, and shipping it today would mean dead buttons and a half-empty panel.
What is missing for the ACP agents we can drive today:
- History. The agents we checked restore a resumed session without replaying it, so the transcript would start blank. The only fixes are reading the agent's private store or copying transcripts into Morse; the first is vendor-specific, and the second breaks the rule that the engine owns the conversation.
- MCP. ACP passes MCP servers when a session starts, but has no methods to list, add, remove, enable or disable them. Morse's MCP manager would have nothing to manage.
- Cost and usage. Usage updates carry context tokens; cost is optional, and the agent we checked sends none. The per-turn token breakdown is not a stable protocol field.
- Edit, fork and clone. ACP has no conversation-branching primitive (fork is still a draft proposal), so Morse's edit and fork actions would have to disappear.
- Model metadata. ACP reports a model id and name, not the context window, output limit, input modalities or provider the picker shows.
- Subagents and rich tool output. Child sessions are not standard in v1, and diffs live in agent-specific tool payloads rather than a shape Morse can render.
- Administration and bot mode. ACP is a conversation protocol, not an agent-configuration API: MCP servers, prompt templates, providers and bot configuration remain the agent's own business.
ACP v1 exists and works, but it is thin. ACP v2 (still a draft, and explicitly not to be shipped by default until it stabilises) improves the turn lifecycle, message identity, tool output and diffs. It still does not standardise history retention, MCP administration, model metadata, cost, prompt templates or child-session transcripts, and no ACP agent we tested negotiates it yet.
If those gaps close — or an ACP agent implements enough of them — the shape is already clear: one
integration-acp package for the protocol, one declarative profile per agent, and no new package per program.
The engine-agnostic seam is ready for it.
- Node.js 20+ (developed on 24) and npm 10+.
- At least one coding agent: the
piCLI installed and authenticated (pi --version), or a path to it viamorse.pi.path/MORSE_PI_PATH; or the OpenCode CLI (v2) onPATH(npm install -g @opencode/cli), or a runningopencode serveplus its password (MORSE_OPENCODE_URL/morse.opencode.url). - Optional: the second engine — Morse registers whichever it finds and offers the engine picker only when both are installed. A machine with neither shows a full-screen setup card offering both installs.
- VS Code 1.138+ for the extension host.
- Morse reuses each engine's own configuration: pi's models, credentials, tools and sessions under
~/.pi; OpenCode's providers, agents and sessions in its server.
npm install -g @supanadit/morse-web
morse start ▲ Morse started
│
◆ port 4399 (PID: 20880)
│
● visit: http://127.0.0.1:4399/
● logs: morse logs
│
└ daemon running — the terminal can be closed
morse start --port 3020, morse status, morse logs --follow, morse stop, morse restart. Add --lan
to bind 0.0.0.0 (the UI has no auth — trusted networks only, or put an authenticating proxy in front), and
-f to stay in the foreground for systemd or Docker.
morse update installs the latest release and restarts. The same thing is a button: start the host with
MORSE_SELF_UPDATE=1 and the sidebar's "Update available" row installs and reloads for you. It is off by
default, and only answers the machine the host runs on.
Install it from the VS Code Marketplace or from Open VSX — the registry VSCodium, Cursor, Windsurf, code-server and Theia install from — or build the VSIX yourself:
npm install
npm run package
code --install-extension dist/morse.vsixThen open the Morse view in the activity bar. The full step-by-step for both hosts — Marketplace, local
tarballs, npm link, settings and troubleshooting — is in docs/INSTALL.md.
| Document | Contents |
|---|---|
docs/INSTALL.md |
Installing both hosts: marketplaces (VS Code + Open VSX), VSIX, npm/tarball, npm link, troubleshooting |
docs/CONFIGURATION.md |
VS Code settings and the browser host's environment variables |
docs/DEVELOPMENT.md |
Build/dev commands, F5, ?mock=1, and the pipeline checks |
docs/ARCHITECTURE.md |
The two hosts, packages, ports and the layering rules |
docs/FRONTENDS.md |
The frontend contract and how to add a React/Svelte/Vue one |
docs/PACKAGING.md |
How the browser host becomes one npm package, and how to publish it |
docs/RELEASING.md |
Cutting a semver release: bump, tag, CI publish of the VSIX and npm package |
docs/STATUS.md |
What is implemented, and what is not built yet |
MIT © 2026 Supan Adit Pratama


