Motty
原生桌面 SSH 工作台:终端、SFTP/SCP、端口转发、VNC 与 RDP 远程桌面、AI 助手都在一个窗口里。Go 编写,没有 Electron,空闲时保持安静。免费开源,支持 macOS、Windows 和 Linux。
Translation pending
A beautiful web-based UI for Claude Code & Codex
Translation pending
Developer toolsTypeScript · CSSGitHub @jakemorSelf-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
Loading the full README. The saved excerpt is shown below.
A beautiful web UI for the Claude Code & Codex CLIs
If Bun isn't installed, install it first:
That's it. Kanna opens in your browser at localhost:3210.Read the full README ↗bun install -g kanna-code
If Bun isn't installed, install it first:
curl -fsSL https://bun.sh/install | bash
Then run from any project directory:
kanna
That's it. Kanna opens in your browser at localhost:3210.
Browser (React + Zustand)
↕ WebSocket
Bun Server (HTTP + WS)
├── WSRouter ─── subscription & command routing
├── AgentCoordinator ─── multi-provider turn management
├── ProviderCatalog ─── provider/model/effort normalization
├── QuickResponseAdapter ─── structured queries with provider fallback
├── EventStore ─── JSONL persistence + snapshot compaction
└── ReadModels ─── derived views (sidebar, chat, projects)
↕ stdio
Claude Agent SDK / Codex App Server / cursor-agent / grok CLI (local processes)
↕
Local File System (~/.kanna/data/, project dirs)
Key patterns: Event sourcing for all state mutations. CQRS with separate write (event log) and read (derived snapshots) paths. Reactive broadcasting — subscribers get pushed fresh snapshots on every state change. Multi-provider agent coordination with tool gating for user-approval flows. Provider-agnostic transcript hydration for unified rendering.
Embedded terminal support uses Bun's native PTY APIs and currently works on macOS/Linux.
Install Kanna globally:
bun install -g kanna-code
If Bun isn't installed, install it first:
curl -fsSL https://bun.sh/install | bash
Or clone and build from source:
git clone https://github.com/jakemor/kanna.git
cd kanna
bun install
bun run build
kanna # start with defaults (localhost only)
kanna --port 4000 # custom port
kanna --no-open # don't open browser
kanna --password <secret> # require a password before loading the app
kanna --share # create a public quick tunnel + terminal QR
kanna --cloudflared <token> # run a named Cloudflare tunnel from a token
Default URL: http://localhost:3210
By default Kanna binds to 127.0.0.1 (localhost only). Use --host to bind a specific interface, or --remote as a shorthand for 0.0.0.0:
kanna --remote # bind all interfaces — browser opens localhost:3210
kanna --host dev-box # bind to a specific hostname — browser opens http://dev-box:3210
kanna --host 192.168.1.x # bind to a specific LAN IP
kanna --host 100.64.x.x # bind to a specific Tailscale IP
When --host <hostname> is given, the browser opens http://<hostname>:3210 automatically. Other machines on your network can connect to the same URL:
Use --password to require a launch password before the app or websocket can connect:
kanna --password my-secret
bun run dev --password my-secret
Kanna verifies the password once, then sets a browser-session cookie. The password itself is not stored in the browser.
When password protection is enabled, the backend requires authentication for API routes and /ws. The SPA shell still loads, /health remains public for restart detection, and the same in-app password screen is used in both dev and production.
Use --share to create a temporary public trycloudflare.com URL and print a terminal QR code:
kanna --share
kanna --share --port 4000
kanna --cloudflared <token>
--share is incompatible with --host and --remote. It does not open a browser automatically.
Without a token, it prints:
QR Code:
...
Public URL:
https://<random>.trycloudflare.com
Local URL:
http://localhost:3210
With --cloudflared <token>, Kanna runs cloudflared tunnel run --token <token> --url <local-url>.
If Kanna can detect the public hostname from cloudflared output, it prints the same QR/public/local block.
If not, it keeps the tunnel running, warns that no public hostname was detected, and prints the local URL so you can use the hostname already configured for that tunnel in Cloudflare.
bun run dev
This is the beginning of the README. Read the rest at the original. Read the full README ↗