a marlin leaping out of the ocean, majestically, at 64 colors

~*~ marlin ~*~

fast, durable terminal agents that SWIM between clients  πŸŸ  built in Zig

current release: v0.2.2

⚑ recommended installer (macOS + Linux):
curl -fsSL https://marlin.wtf/install.sh | sh

prefer Homebrew? brew install jespern/tap/marlin

β˜…β˜…β˜… WELCOME to marlin.wtf β˜…β˜…β˜… native agent β˜… Claude Code + Codex guests β˜… daemon-owned sessions β˜… real shell sessions β˜… pause + resume β˜… screenshots β˜… live work tree β˜… scriptable CLI β˜… durable plans β˜… SSH remote β˜… MCP + hooks + skills + plugins β˜… written in ZIG β˜…β˜…β˜…

>> what IS marlin??

marlin is a daemon-native terminal AI agent harness and session multiplexer. Its own agent runs native models; installed Claude Code and Codex agents can run beside it as guests using their existing vendor logins. The daemon owns the structured sessions while the TUI, web UI, and headless CLI remain thin clients.

Close a terminal and the turn keeps running. Reattach later, reach it through SSH, mosh, or your tailnet, or compose it with ordinary shell commands. The transcript, plans, status, approvals, diagnostics, and full tool results are still thereβ€”and inspectable without opening SQLite.

GARAGE PICK If Marlin were a car, it would be a first-generation Honda NSX: supercar fast, Honda reliable, usable every day, and direct enough that the driver always knows what the machine is doing. No touchscreen maze, no ornamental controls. Just a small, deliberate machine that starts every time and wants to be driven hard.

DEVELOPMENT PREVIEW Marlin is already self-hosting and useful for real work, but it is not a stable 1.0 product. The native agent, Claude Code and Codex guest sessions, structured multiplexer, scriptable inspection CLI, extension platform, durable plans, child delegation, review councils, SSH remote client, phone web app, daemon-owned shell sessions, and durable pause/resume are built. Current work is concentrated on hardening edges, diagnostics, and performance. Config and protocol details may still move.

>> what's NEW HOT!!

v0.2.2 Β· 2026-11-15

  • the phone app, off Tailscale: put the web companion behind any reverse proxy and pair a phone once with a six-digit code (/web pair, or p on the Web tab); unpairing cuts its live streams at once. [web] listen, hosts, and proxy replace tailscale = true, which is now ignored: see docs/MOBILE.md
  • the phone app, like the TUI: the TUI's colors, tool rows, and "Ran N commands" folds; questions, approvals, and Plan offers answered from the phone; image attachments; a multi-line composer with one draft per session; status with context, credits, and cwd; session marks; and it never scrolls away from what you're reading
  • dictation: tap the mic in the phone app, and the clip is transcribed on your Mac with /voice's local engine, into the composer for review
  • remote MCP servers: Streamable HTTP servers, OAuth sign-in with /mcp login, and MCP servers that plugins bring
  • Muse Code joins Claude Code and Codex as a guest agent (muse/default)
  • a user profile: ~/.config/marlin/profile.md reaches every agent, native or guest, fresh each turn
  • shells: with Ghostty installed, shells report their commands and exit codes to the agent; bells, notifications, and progress reach you from background tabs; tabs take the title their program sets; links and color queries work; and a shell cut off by a crash or /shutdown says what it was running
  • guests: context gauge and /compact for Claude Code and Codex, and live output from their subagents and background commands
  • small things: !c copies the last reply's prose (!co the tool output), marlin watch streams a session read-only, asked questions stay in the transcript with their answer, and private GitHub plugin marketplaces clone through gh
  • changed default: the paced 60 fps stream reveal is now opt-in (/config pacing on); replies still render line by line
  • fixes: Claude Code /compact no longer hangs, recaps and the context gauge survive tab switches, reattach, and restarts, and CLI output redirected to a file keeps every line
  • release on GitHub
v0.2.1 Β· 2026-11-08
  • security: the web bridge refused opening and typing into shells, but a browser on the loopback web UI could still list running shells and attach to one to read it. Every shell message is now refused
  • screenshots, painted the way Ghostty paints: Marlin draws the PNG itself with Ghostty's own font code, so box drawing and blocks match Ghostty pixel for pixel; !ss takes one, and JetBrains Mono is fetched on first use instead of being built in
  • tabs: a dim ❯ or $ before each tab's number tells agent sessions from shells
  • guests: a missing working directory is reported as such, not as a missing binary
  • release on GitHub
v0.2.0 Β· 2026-11-07
  • shell sessions: !! turns any session into a login shell on the daemon host, emulated by libghostty-vt. Shells survive detaching, quitting, reconnects, and restarts; scrollback, Vim normal mode, / search, the mouse, full-screen programs, and Kitty images all work. Ctrl+B reaches Marlin's keys, and Ctrl+D hands the session back with the shell's output in its transcript
  • screenshots: Alt+S or /screenshot [slim] copies a PNG of exactly what Marlin rendered
  • durable pause + resume: /pause [all] [--force] suspends a session and its children once their workers stop, the pause survives reboots, and /resume picks the work back up
  • live Markdown streaming: replies render line by line as they arrive, with a paced 60 fps reveal; a finished reply looks exactly like its stream
  • steering: queued steering stays visible, and steering messages can carry images
  • timestamps: hover any message or tool output to see when it happened
  • remote polish: the status line names the daemon's host, and /cwd completes paths on that host
  • guests: Codex questions use the picker, recoverable Codex failures continue on their own, guest runtime limits are per session, and guest login failures stay visible until retried
  • small things: bracketed pastes arrive as one paste, Ctrl+N opens in the current tab's directory, session permissions and input history persist, /rename titles stick, and /exit plus /shutdown are new
  • under the hood: ported to Zig 0.17, with terminal emulation on libghostty-vt 1.0
  • release on GitHub
v0.1.7 Β· 2026-10-16
  • reproducible releases: release binaries rebuild byte for byte and are certified with shadybin
  • copying: wrapped lines copy as their source, not as the screen drew them
  • bridged prompts: guest approvals and questions wait for the human instead of timing out
  • release on GitHub
v0.1.6 Β· 2026-10-16
  • guest work in the tree: Claude Code background jobs and subagents show up in the work tree, with their output inspectable
  • skills + handovers: portable skills, plugin completion, and validated handover briefings; DeepSeek's inline tool markup becomes real tool calls
  • polish: elapsed times read 8m 12s everywhere, staged images stay with their tab's draft, and Claude Code and Codex sessions shut down more reliably
  • release on GitHub
v0.1.5 Β· 2026-09-22
  • web companion: integrated, with persistent controls, access logs, Web Push, and a better mobile composer
  • LAN discovery: marlin discover finds running Marlin daemons nearby
  • questions: interactive multiple-choice questions and durable model-switch notes
  • terminal: shell-style /cwd completion, better word navigation and SSH prompts, and a moon rocket screensaver
  • tracing: persistent OpenTelemetry controls with guest tool and model spans
  • release on GitHub

Older releases are on GitHub.

>> what works TODAY

Developer-first TUIVim navigation, multiline editing, Ctrl+N for a new session in the current tab's directory, command completion, OSC52 copy, hover timestamps, Markdown that renders as it streams, syntax, diffs, reasoning, and foldable tool output. Alt+S copies a screenshot.
Shell sessions!! turns a session into a login shell that lives in the daemon, emulated by libghostty-vt. It keeps running through detaches and restarts, with scrollback, Vim normal mode, search, full-screen programs, and Kitty images. Ctrl+D hands the session back, the shell's output kept in its transcript.
Pause + resume/pause suspends a session tree once its workers stop, or every session with all. Pauses are durable, so they survive a daemon reboot; /resume continues the work.
Durable execution plansThe active step stays pinned in a timed two-column table with live progress and child activity. Completed plans close into scrollback; revisions survive reboot and compaction.
Real multiplexerDurable concurrent sessions, a clickable configurable tab strip, short stable handles, /sessions, per-session view state, and rolled-up child activity.
Actionable stateRunning, approval, error, and child status are typed protocol events, not guesses scraped from a terminal. !c copies the last reply; !co the last complete tool result.
Remote without reinventionmarlin --remote host carries the structured protocol over SSH, the status line names the daemon's host, and /cwd completes paths over there. marlin web is a daemon-managed loopback UI, on by default (/web disable turns it off), that a phone reaches through your own HTTPS proxy after pairing once with a code from /web.
Context that admits realityInline output caps, full content-addressed blobs, pruning, compaction, usage accounting, and durable reconnect replay.
Self-hosting loopHeadless runs, steering, approvals, interruption, automatic client reconnect, and coordinated /reboot --build while developing Marlin inside Marlin.
Live work treeCtrl+S or marlin top shows every session with its live work underneath: children, guest subagents, running commands, and background jobs. Enter opens a job's live output; x kills, a archives down a list.
MCP as a productIsolated health, daemon-owned add/remove/restart/reload, per-tool policy, durable image results, and one schema + approval path.
Permissions that enforceScrubbed tool environments, protected-path read refusals, capture-time secret redaction, managed network filtering, and canary-verified kernel shell sandboxing on macOS (Seatbelt) and Linux (Landlock) with safe fallback.
Claude Code + Codex guestsRun the official claude binary or stable codex app-server protocol as first-class multiplexed sessions using their existing logins. Guest permission prompts and questions share marlin's approval bar, background jobs and subagents show up in the work tree, and switching a session between native, Claude Code, and Codex models carries a validated handover briefing.
Skills + pluginsAgent Skills bundles are discovered from project .marlin/skills and .agents/skills plus your user skill directories, and invoked as slash commands. marlin plugin marketplace add and install import Claude Code plugin marketplaces, their skills and their MCP servers.
Scriptable by designmarlin run works headlessly; ls, search, and inspect --json expose daemon-owned state for shell scripts without screen scraping or SQLite queries.
Children + review councilstask and task_batch create up to eight durable, attachable, read-only children. Named councils fan questions across models for parent synthesis.
Image-aware sessionsCtrl+V or /attach uploads signed image data through the client boundary, stores it by content hash, and maps it to native provider vision blocks. Images can steer a running turn, too.
Fast parallel toolsConsecutive tools marked parallel_safe really run concurrently, with at most eight workers. Durable results stay in provider-call order.
Provider choiceOpenRouter-first model catalog, built-in web search/fetch, and OpenAI-compatible and Anthropic paths, with per-session model and reasoning effort.
Local voice dictation/voice setup adds optional push-to-talk or toggle dictation with whisper.cpp or parakeet-mlx. Audio stays at the client edge, and transcripts land in the composer for review before submission.

>> take it for a swim

$ curl -fsSL https://marlin.wtf/install.sh | sh
$ export OPENROUTER_API_KEY=...
$ marlin run "why is my build broken"
# ...the daemon keeps the structured session...
$ marlin             # attach the TUI
$ marlin --remote devbox # same TUI, carried over SSH
$ marlin ls          # short stable handles, including children
$ marlin inspect 63df --json # metadata, state, plan, blocks, diagnostics
$ marlin search "permission denied" # search durable transcripts
$ marlin attach 63df # any unique prefix (minimum four)

# installed vendor agents can join the same multiplexer:
$ marlin run --model codex/default "review this patch"

# inside the TUI:
/council new core   # pick models, then choose Done
/review core audit this design before I ship it

The installer downloads the matching tagged release for macOS or Linux on aarch64 or x86_64, verifies its SHA-256 checksum, and installs it in ~/.local/bin without sudo. Homebrew also works: brew install jespern/tap/marlin. Tracking main instead? Clone the repository and run zig build with Zig 0.17.

>> development STATUS

trackwhere it isstatus
M0–M3agent loop, daemon, TUI, context engine, self-hosting rebootβœ… BUILT
M3.5permissions + secret boundary (reads refused, secrets redacted, macOS+Linux sandbox)βœ… ENFORCED
M4structured session multiplexerβœ… VERIFIED
M5managed MCP, executable tools, hooks, skillsβœ… PRODUCTIZED
M6adurable child sessions + bounded task fan-outβœ… VERIFIED
M6bnamed multi-model councils + durable reviewer sessionsβœ… SHIPPED
M6cSSH-carried remote clients + tailnet web UIβœ… SHIPPED
nowcancellation, reconnect, extension diagnostics, dogfood, and performanceπŸ”¨ HARDENING
laterworkspace snapshots, isolation, leases, land/discardπŸ“‹ EVIDENCE FIRST

The source-of-truth details live in the milestones and the active M6 execution plan.

>> edges we're still sharpening (honesty zone)

>> sign my guestbook... i mean, links

SOURCE on GH made w/ ZIG RELEASES ARCHITECTURE

one handcrafted HTML file. the fish rejected React.