Herdr UI
Herdr의 TUI가 뛰어나며, 창을 통해 추가되는 기능
코딩 에이전트가 의미를 그림으로 보여주고 이미지로 질문하며 대화 옆에서 변경 사항과 리뷰를 안내합니다
Your coding agent draws what it means, asks you with pictures, and walks you through its changes and reviews, right beside the conversation.
개발 도구TypeScript · CSSGitHub @sodre90온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
A canvas for your coding agent. It draws what it means, asks you with pictures, and walks you through its changes and reviews, right beside the conversation. Desktop app for macOS and Linux.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗See what your coding agent means.
Mirador runs your coding agents (Claude Code, opencode and pi) and gives them a canvas beside the conversation. On the canvas they draw what they mean, ask you with pictures, walk you through code, and hand you code reviews you can walk through. It runs on your own computer, with your own agent settings.
▶ Watch the trailer (2:33) · Website
curl -fsSL https://github.com/sodre90/mirador/releases/latest/download/install.sh | sh
That installs the desktop app on a Mac with Apple Silicon, or on Linux (x64 or arm64), and starts it. On Windows (x64, experimental), irm https://github.com/sodre90/mirador/releases/latest/download/install.ps1 | iex in PowerShell does the same. It runs the Claude Code, opencode or pi you already have. More ways to get it.
A mirador is a lookout: the place you climb to see the whole landscape at once.
Coding agents changed the pace of our work. In a few minutes an agent reads a codebase, changes ten files and explains what it did in a long stream of text. Writing code is no longer the slow part. We are: reading what the agent did, understanding it and reviewing it fast enough to stay in control.
And we do that reading in a terminal. A terminal is a wall of text scrolling by: tool calls, diffs and explanations, all in one font, all at the speed the agent types. But people understand pictures far faster than text. A sequence diagram explains a request path at a glance, where the same in prose takes a page. A mockup settles a layout question in a second, where three paragraphs describing the options don't.
Mirador was born from that gap. It keeps everything that makes a coding agent powerful (the real Claude Code, opencode and pi, with your own settings, hooks, extensions and MCP servers) and gives the agent a canvas next to the conversation:
Understanding gets faster. Reviewing gets far, far faster. And you stay the one who decides.
Mirador is a tool for developers, built by a developer, to make our lives easier in the AI era: the agents are fast, and this is how we keep up with them.
The agent renders a page on the canvas: a diagram, a mockup, a chart, a comparison, a 3D scene. Pages are self-contained HTML in a sandbox, with Mermaid, D3 and three.js built in and working offline. If a page throws a script error, the agent is told and fixes it. Every page stays in the conversation's canvas history.
Instead of a numbered list of options in text, the agent asks on the canvas: a question, an optional page explaining it, and up to eight options with a preview each. You click one, or type your own answer when the agent allows it, and add a note if you like. Several questions come at once, a page each, with a review before you send. The answer goes back to the agent, either as the tool's result or as your next message.
Instead of a long summary in text, the agent walks you through the code on the canvas: how something works, or what it just changed. A tour is a short summary and steps in the order the code runs, each with its lines. When it shows a change, the changed lines are marked and a Files tab holds the diff. Ask the agent about any lines, or open them in IntelliJ IDEA.
The agent publishes its code review as a page you work through, not a wall of comments:
Keep or drop each finding, reword it, ask the agent about any lines, and open them in IntelliJ IDEA. Then post the findings you kept to the GitHub pull request as your pending review.
Mirador runs on macOS (Apple Silicon), Linux (x64 and arm64) and Windows (x64, experimental), and in any browser on your network. Android and iOS apps are coming.
curl -fsSL https://github.com/sodre90/mirador/releases/latest/download/install.sh | sh
The script downloads the latest release for your computer, installs it and starts it. Run it again to update.
~/Applications, which needs no admin rights. Quit a Mirador running from there first.sudo apt-get or sudo dnf; on other distributions the script names them. The app goes in ~/.local/share/com.sodre90.mirador, with an entry in your applications menu.Windows (x64, experimental), in PowerShell:
irm https://github.com/sodre90/mirador/releases/latest/download/install.ps1 | iex
The app goes in %LOCALAPPDATA%\com.sodre90.mirador, and starts. To run the script again, quit Mirador from its tray icon first, with Run host in the background off.
The app carries Mirador and the Bun it runs on, so it doesn't require Bun or a checkout. It runs the agents you have installed: Claude Code (curl -fsSL https://claude.ai/install.sh | bash, or irm https://claude.ai/install.ps1 | iex on Windows), opencode and pi (npm install -g @earendil-works/pi-coding-agent, on Node 22.19 or later). The script tells you when none of them is there.
With Homebrew, on macOS or Linux:
brew install --cask sodre90/tap/mirador
The app updates itself, so brew upgrade leaves it alone. On Linux, Homebrew doesn't install the libraries the app needs; it prints the apt and dnf commands for them. brew uninstall --cask mirador quits the app and removes it (on Linux, turn off Run host in the background first), and --zap also removes its window's data. Your conversations in ~/.mirador stay.
By hand, from the releases:
macOS: Mirador-macos-arm64.zip. The app is signed with a Developer ID and notarized by Apple:
ditto -x -k Mirador-macos-arm64.zip ~/Applications
open ~/Applications/Mirador.app
Linux: Mirador-linux-x64-Setup.tar.gz or Mirador-linux-arm64-Setup.tar.gz (uname -m says which). It needs glibc 2.36 or newer (Ubuntu 24.04, Debian 12, Fedora 37 or later), GTK 3, WebKitGTK 4.1 and the Ayatana AppIndicator library (details):
sudo apt install libgtk-3-0 libwebkit2gtk-4.1-0 libayatana-appindicator3-1 librsvg2-2 # Debian, Ubuntu
sudo dnf install gtk3 webkit2gtk4.1 libayatana-appindicator-gtk3 librsvg2 # Fedora
mkdir mirador-setup && tar -xzf Mirador-linux-*-Setup.tar.gz -C mirador-setup && mirador-setup/installer
The installer starts Mirador, and puts it in your applications menu.
Windows: Mirador-windows-x64-Setup.zip. Extract it and run Mirador-Setup.exe. The app is not signed yet, so SmartScreen warns when the installer first runs: More info, then Run anyway. The installer installs without a click, then waits at "Installation complete" for Close, and starts Mirador.
Signing in: Mirador runs the claude on your PATH (or in ~/.local/bin, /opt/homebrew/bin or /usr/local/bin; on Windows in %USERPROFILE%\.local\bin), or the program set in Settings › Agents, so it uses the sign-in and version you already have. Without a sign-in, a conversation offers Log in, which opens that Claude Code's own sign-in in a terminal tab. For opencode, install opencode and Mirador finds it. For pi, install it (npm install -g @earendil-works/pi-coding-agent) and Mirador finds it on your PATH; Log in opens pi itself in a terminal tab, where /login signs in.
bun install
bun start
Open the http://127.0.0.1:4600/auth?code=… link the host prints; it signs one browser in with a cookie, works once, and expires after 10 minutes. bin/mirador sign-in makes a new link for the next browser. Ctrl+C stops the host, and the agents with it.
Windows support is new and experimental: expect rough edges, and please report what breaks in an issue.
Shells: as Claude Code does, Mirador runs ! commands, the status line, the pre-launch command and the sign-in tab in Git Bash (CLAUDE_CODE_GIT_BASH_PATH, else where Git is installed), or in PowerShell when there is no Git Bash. Terminal tabs open PowerShell: PowerShell 7 when it is installed, else Windows PowerShell.
The mirador command: PowerShell and cmd run bin\mirador.cmd, and Git Bash runs the bin/mirador script beside it; to run mirador from a checkout, put its bin folder on your PATH. mirador.cmd goes through cmd, which reads &, %…% and " in its arguments as its own, so a PowerShell script the agent runs pipes such text in instead, as UTF-8 for accents and symbols:
$OutputEncoding = [Text.UTF8Encoding]::new($false)
'Build done: 3 warnings & 1 "flaky" test' | mirador message
In Git Bash, any text arrives as typed.
The data folder, %USERPROFILE%\.mirador, is kept to your account, SYSTEM and Administrators at every host start, as chmod 700 keeps it to you on macOS and Linux. Access someone gave the folder itself stays, and the host warns about it when it starts.
Before you uninstall, turn off Run host in the background and Open at login: uninstalling doesn't remove them yet.
show: the agent renders a page next to the conversation: diagrams, mockups, charts, comparisons, 3D scenes.light-dark().ask: a question with 2 to 8 options, each with a description and an optional HTML preview, plus an optional page explaining the question. The option the agent recommends is tagged Recommended.+/− counts and the same buttons.tour: the agent walks you through code without reviewing it: a title, a summary and steps in the order the code runs, each anchored to its lines. It explains how something works, or shows what a task changed.HEAD for uncommitted work), the steps mark added and removed lines, and a Files tab shows the diff, new files included. Mirador keeps the files the tour was made from in the folder's git repository, under refs of its own, so Show the rest of the file works on older tours too, for each repository's newest 100 tours; your branches, history and staging area are untouched.review: the agent publishes a review of base...head in a checkout, like a pull request: a title, a verdict, a summary, a tour of the code flow and findings. The diff comes from git, so the agent never pastes code.+/− counts, commit range, the summary (Markdown, tables included), the flow as a list and the findings by severity.a asks the agent with the code attached and o opens IDEA at that line. Ask and update the review (⌘Enter) has the agent republish when its answer changes anything.gh (GitHub Enterprise too). You submit it on GitHub. Findings outside the pull request's diff stay in the review, marked as such, and GitHub refusals are reported per finding.
gh auth login --hostname <host>. Mirador uses the account gh has active there, so a work GitHub Enterprise and your personal github.com each post as their own account.~/.claude (settings, hooks, MCP servers; claude-notifier is muted for Mirador's sessions), opencode with ~/.config/opencode (providers, agents, plugins, MCP servers, and its permission settings: Mirador forces nothing, so with opencode's defaults most tools run without asking). opencode is found on PATH, else in /opt/homebrew/bin, /usr/local/bin or ~/.opencode/bin. pi with ~/.pi/agent (settings, models, extensions, skills), through pi-acp, which Mirador carries; pi is found on PATH. pi support is new and experimental.OPENCODE_CONFIG=…, or inline OPENCODE_CONFIG_CONTENT='{…}'), or pi with another agent folder (PI_CODING_AGENT_DIR=…) or another pi (PI_ACP_PI_COMMAND=…).
KEY=value, -u KEY and # comment, so the lines of a claude_env=( … ) alias paste as they are.logs/<agent>-<name>-<id>.log). Saving a profile with a changed environment or pre-launch command restarts its agent.[Image #n] where the caret is, and shows as a chip while it uploads. Deleting the marker drops the image, and a pasted image you never send is deleted from the host.@ paths: completes workspace files, folder by folder, as well as absolute and ~ paths, anywhere in the message./ commands: the agent's commands plus Mirador's /clear and /login. Tab writes one out, Enter runs one that takes no arguments, Esc closes the list./plugin, /hooks, /permissions, /memory, /status, /help and the other commands Claude Code shows only in its own terminal open a terminal tab running Claude Code with the conversation's profile.! shell commands: run in the workspace's folder with your login shell. The output shows inline with Run/Stop, and goes to the agent with your next message unless you drop it.{{parameters}}: Templates sends one or inserts it, with a form for the parameters. Or press ⌘J in the message box: typing narrows the list, Enter puts the template in at the caret with its first value selected, and Tab / Shift+Tab go through its values. Add, edit and delete them in Settings → Conversations; Deep PR review, Start on a ticket and Code tour come with Mirador, and a template added to Mirador later shows up once on an existing install too.⌘⇧Space anywhere in the window, also while a canvas page has focus. A tap listens until you pause or tap again, a hold until you let go, and Esc cancels. What you said goes in at the caret, or is sent at once with Send right away. It works in the desktop app, which asks for the microphone once, in a browser, and in another machine's Mirador in the rail, through that machine's speech recognition.statusLine command, exactly as Claude Code would; opencode and pi conversations keep the built-in one.⌃`.⌃` shows or hides them and ⌘⇧↓ focuses them; the palette also opens a tab, splits, and fills the window with the terminal. ⌘+ and ⌘− change their font size (11 to 24 px).⌘D splits right and ⌘⇧D down, ⌥⌘←→↑↓ move between splits, ⌘[/⌘] go to the previous or next split, ⌘T opens a tab, ⌘⇧[/⌘⇧], ⌘1…⌘9 and ⌃1…⌃9 switch tabs, and ⌘⇧↩ zooms the focused split (Show all brings the others back). In Chrome, ⌘T, ⌘W, ⌘⇧[/⌘⇧] and ⌥⌘←→ stay Chrome's.⌘W closes the focused shell, and a middle click closes a tab. Either asks first while a command runs: Enter ends it, and so does ⌘W again when ⌘W asked; Esc keeps it.⌘←, ⌘→, ⌘⌫, ⌥←, ⌥→, and ⌘K clears for good.⌘F (Ctrl+Shift+F on Linux and Windows, where Ctrl+F stays the shell's) searches the focused split's scrollback. Every match is highlighted. Enter goes to the match further up, Shift+Enter further down. Match case, whole word and regular expression are toggles, as in VS Code. Esc, or ⌘W in the desktop app, closes it and puts the cursor back in the shell.Ctrl+Shift+C and Ctrl+Shift+V copy and paste, and Ctrl+C stays the interrupt.mirador when-done: instead of polling a job it started in the background, the agent runs mirador when-done --pid <pid> "<message>" (or --container <name> for Docker and Podman, and --host <user@host> for a job on another machine, over ssh) and ends its turn, which then neither notifies you nor marks the conversation Done. When the job ends, the message arrives as your next message, so the agent carries on; with --no-resume only you get notified. Agents can also call the canvas server's when_done tool, which does the same; opencode's agents use that, as their commands carry no session id, and so do pi's.
tail -f) or the container's logs, until it ends. Clicking again shows the same tab. Ctrl+C closes the tab and leaves the job running.mirador message "<text>" (or text on stdin) sends text to the agent's conversation as your next message: at once if the agent is idle, else queued. It shows as From a script. It finds the conversation by the session id every command the agent runs inherits (CLAUDE_CODE_SESSION_ID from Claude Code, PI_SESSION_ID from pi), with the MIRADOR_URL and MIRADOR_SCRIPT_TOKEN Mirador gives its agents. opencode's commands carry no session id, so they, and anything else, need --session <agent session id>. The script token survives restarts, and unknown sessions or empty messages are refused with the reason.mirador approve. With no page or app of the machine open, its host shows the request through notify-send where libnotify is installed, and the notification's Open Mirador signs in a browser there. The list shows which devices are connected, with how many pages each has open (or in the background, while only its app listens for notifications), and where they connect from, including the Tailscale login. Revoke any of them at once.tailscale serve for both ports itself. Over the network, with no address — Mirador serves HTTPS itself on its own port, with a certificate authority of its own (download mirador-ca.pem) or your certificate (MIRADOR_TLS_CERTIFICATE, MIRADOR_TLS_KEY). Or only on this machine.Settings… opens a dialog of pages (Up/Down switch between them). Each page says whether a setting is kept in this browser or on the host.
Hovering almost any control explains what it does behind the scenes, together with its keyboard shortcut.
| Keys | What they do |
|---|---|
⌘K | The palette: any conversation, new conversation, continue a session, rewind or undo a turn's files, workspace colour and group, rename, canvas and terminal, layout reset, machines, search, settings, restart the host |
⌥↑ ⌥↓ / ⌥⇧↑ ⌥⇧↓ | Previous or next conversation / workspace |
⌥1…⌥9 | The n-th conversation of the current workspace |
⌥T / ⌥⇧T | New conversation / add a workspace |
⌘\ / ⌃` | Show or hide the canvas / the terminals |
⌘⇧← ⌘⇧→ ⌘⇧↓ | Focus the message box / the canvas / the terminal |
⌘F / ⌘⇧F | Find in the conversation (in a terminal, in its output) / search everywhere |
⌘J | In the message box, find a prompt template and put it in |
⌘⇧Space | Dictate: a tap listens until you pause, a hold until you let go |
⌘+ ⌘− / ⌘0 | Text size bigger or smaller / back to 100% (in a terminal, its font size) |
⌘R / ⌘⇧R | Reload the page / restart the host |
? | Every shortcut, terminal keys included |
Off macOS, Ctrl stands in for ⌘ and Alt for ⌥. The ⌥ bindings go by physical key, so they work on layouts where ⌥ types characters, but they then shadow those characters (e.g. ⌥1…9 on the Hungarian layout). They also work while a canvas page has focus, except those that create or restart something: a page the agent wrote can't start conversations.
A native window around Mirador, for macOS, Linux and Windows (full details).
⌘W closes the open dialog, else the focused terminal's shell, and asks before it closes the window. The menu has the Mirador version and the host's status, a newer version when there is one, Open, Restart host, Run host in the background, Open at login and Quit. On a Linux desktop without a tray, Desktop app… in the sidebar has the same menu.notify-send).⌘R reloads the page with the UI code as it is now (the bundle rebuilds when web/ or shared/ changes), also in the desktop window.host/ or shared/ changed, a banner offers a restart (also ⌘⇧R, or Restart the host in the palette). The host stops working agents' turns the way Stop does, re-executes itself in the same process (so the desktop app, launchd or your terminal keeps seeing the same host), and then asks those agents to continue. Terminal shells start again, under the output they had. Queued messages and waiting marks survive any restart, and open pages reload by themselves.bun run dev hot-reloads the UI, for working on web/.mirador sign-in prints a one-time sign-in link for a browser on this machine. mirador invite prints a one-time invite code (and a link once the machine has an address). mirador approve lets in a device that asked to join. mirador devices lists devices, even while Mirador is stopped. mirador when-done waits for a job, and mirador message sends the agent's conversation a message. Put bin/mirador on your PATH with a link: ln -s "$PWD/bin/mirador" ~/.local/bin/mirador.MIRADOR_PORT (default 4600; canvas assets use the next port), MIRADOR_CANVAS_PORT, MIRADOR_DATA_DIR (default ~/.mirador), MIRADOR_NETWORK and MIRADOR_NETWORK_PORT, MIRADOR_PUBLIC_ORIGIN and MIRADOR_PUBLIC_CANVAS_ORIGIN, MIRADOR_TLS_CERTIFICATE and MIRADOR_TLS_KEY, MIRADOR_BUN.config.json (address and network), and agent logs under logs/.bun run typecheck
bun run test # unit tests
bunx playwright test # e2e: a real Claude Code on haiku against your model server, opencode and pi against a scripted fake model (installed Google Chrome on macOS, Playwright's Chromium elsewhere)
MIRADOR_E2E_MINIMAL_ENV=1 bunx playwright test e2e/agent-flow.spec.ts # host started with a bare environment
MIRADOR_EXPERIMENT=1 MIRADOR_TEST_MODEL=default MIRADOR_TEST_EFFORT=default bunx playwright test e2e/experiment-unprompted.spec.ts
MIRADOR_SCREENSHOTS=1 bunx playwright test e2e/readme-screenshots.spec.ts # retakes this README's screenshots from a demo
The e2e specs' Claude Code never uses your Claude login, and keeps its settings and sessions in each test host's own folder, out of your ~/.claude. Specs that wait for a real reply need a model server that speaks the Anthropic API: export LLM_SERVER_URL and LLM_SERVER_KEY, or write them to ~/.config/mirador/e2e-model-server.env. Without one, those specs fail. The experiment and the screenshots above are the exceptions: they run on your login and ~/.claude.
On Linux, from any machine with Docker (MIRADOR_LINUX_ARCH=x64 or arm64, default this machine's; the other one runs emulated and slowly):
scripts/linux-test.sh # type check, unit and e2e tests in Ubuntu 24.04
scripts/linux-desktop.sh # builds the desktop app's installer, installs it and checks it starts, opens at login and stays single-instance
MIRADOR_LINUX_RELEASE=1 scripts/linux-desktop.sh # the same for the release installer, which carries Mirador
Build the arm64 release installer on an x64 Linux machine too: in Docker on Apple Silicon, Electrobun's toolchain crashes (see desktop/README.md).
A release is made with three goals, each when the one before has been checked. Write the notes into dist/release-notes-x.y.z.md first:
make release VERSION=x.y.z LINUX_HOST=user@host # in a worktree of its own: names the release, runs every test, builds and checks every app, and leaves a draft on GitHub whose files are checked against dist/x.y.z
make publish VERSION=x.y.z # publishes the draft as the latest release
make tap VERSION=x.y.z # pushes its Homebrew cask to the tap
An x.y.0 release is made from main and starts the branch release/x.y.x at its commit. A patch, x.y.1 and on, is made from that branch, so a fix goes out without what main gained since: commit it on main, cherry-pick it onto release/x.y.x, then make release VERSION=x.y.z.
After the gate the Linux, Windows and macOS builds run at once, and each makes its update files as soon as it is in. A step that fails names the steps to go on from once it is fixed (FROM=step, or FROM=step,step with the failed step of each build). The Windows app is built by the Windows release workflow on GitHub's Windows runner, which make release starts for the release's commit, waits for, and downloads from. The workflow's e2e survey runs a third of the suite on each of three runners at once, and going on from the windows step after a red run runs only its failed jobs again. WINDOWS=no makes a release without it and without install.ps1. Every app carries the Bun .bun-version names, the one the checks run on: a release build refuses any other, and the gate refuses to run on another. The rest it builds with the goals below, which can also be run alone. The release assets go to dist/ (make help lists the goals):
make macos # the macOS app carrying Mirador, zipped (on a Mac)
make macos-signed # the same, signed with your Developer ID and notarized by Apple (see desktop/README.md)
make linux # both Linux release installers, built and checked as above (on an x64 Linux machine)
make linux-remote LINUX_HOST=user@host # from a Mac: make linux on that machine, with the installers and update files copied back
make update-files # what the apps fetch to update themselves, with patches from the last 5 releases (on a Mac, after the builds)
make checksums # install.sh and install.ps1 copied in with them, and the SHA-256 of all of it, for the release notes
make cask # the Homebrew cask for the sodre90/homebrew-tap tap, with the SHA-256 of the macOS zip and the Linux installers
Layout: host/ (Bun server, ACP client, canvas MCP server, SQLite store), web/ (React UI bundled by Bun), shared/ (types and logic both sides use), desktop/ (the Electrobun app), site/ (the website, assembled with the README's screenshots by bun scripts/build-site.ts and published to GitHub Pages by .github/workflows/site.yml), e2e/ (Playwright specs), tests/ (unit tests), spike/ (throwaway feasibility spike, see spike/FINDINGS.md). Work is tracked in beads (bd ready).
MIT, see LICENSE.
1–5 tabs, j/k changes, n/p findings, f files, a ask, o open in IDEA.CLAUDE_CONFIG_DIRXDG_DATA_HOMEPI_CODING_AGENT_DIR~/.pi/pi-acp~/.claude/sessions, or the profile's CLAUDE_CONFIG_DIR). The turns you take in the terminal join the conversation once the terminal is idle, and the agent goes on from them./clear starts the agent afresh while the transcript stays on screen. It works queued, and across restarts./login) opens the agent's own sign-in in a terminal tab, with the conversation's profile.~/.mirador/voice, and nothing you say leaves the Mac. Whisper large-v3 turbo hears you; a Gemma 4 voice model translates and sums up, from those that fit in half the Mac's memory (E4B, 12B or 26B-A4B); Kokoro reads English replies, and OmniVoice Hungarian ones, under a licence that allows only non-commercial use. A model loads when first needed, in 5 to 15 seconds, and unloads after 30 minutes unused. Models on this Mac lists what is on disk, and removes what you no longer use./audio/transcriptions), the voice model (/chat/completions) and the reply voice (/audio/speech, with one of its voices). The voice model can also call a profile's Anthropic or OpenAI API with its keys, without starting its agent. On Linux and Windows, voice uses these.