A lightweight, mobile-first viewer and controller for AI coding agents.
Open any Claude Code session on your phone. Read the conversation. Send messages. Watch the terminal. Resume old sessions or spawn new ones — instantly.
The entire app is 6 files. Point Claude (or any AI agent) at this repo and tell it what you want:
- "Add a cost tracker that shows tokens and dollars per session"
- "Add push notifications when an agent needs my attention"
- "Show me a diff view when Claude edits a file"
- "Add a dark/light theme toggle"
- "Group consecutive tool calls into a collapsible block"
- "Add Codex support — here's how their session files work"
- "Add a search bar that filters across all sessions"
- "Show a green typing indicator when Claude is responding"
- "Add keyboard shortcuts — j/k to navigate sessions, Enter to open"
No abstractions to learn. No plugin API to read. One server file, one app shell, one message renderer. You describe it, the agent builds it.
Feather is designed to diverge. Fork it, make it yours, share what you build.
# Fork on GitHub, then:
git clone https://github.com/YOU/feather.git && cd feather
npm install && npm start
# hack awayPulling from other forks:
# Add someone's fork as a remote
git remote add phil https://github.com/phil/feather.git
git fetch phil
# See what they've been up to
git log phil/main --oneline
# Grab specific commits
git cherry-pick <sha>
# Or merge everything
git merge phil/mainContributing back:
Open a PR to inceptel/feather from your fork. Or don't — your fork is yours.
You're running Claude Code on a remote machine. You want to check on it from your phone, your iPad, another laptop. You want to send a follow-up message without SSH-ing in. You want to see the conversation rendered beautifully — like a texting app, not a terminal dump.
Feather reads Claude's raw JSONL session files, streams updates via SSE, and connects to tmux sessions via WebSocket terminals. No database. No build pipeline beyond Vite. Just node server.js.
Feather has a built-in dashboard for auto instances — long-running self-improvement loops that iterate on a goal in the background. Each instance is a directory at ~/auto-NAME/ with a run.sh (the loop), a program.md (the spec), and a results.tsv (the keep/revert/crash log). The Feather UI lets you start, stop, retarget, and inspect each loop without ever touching a terminal.
Loops are driven by pipelines — JSON definitions in templates/auto/ that list the phases (designer / worker / verifier / simplifier / …) and which engine runs each one. Three ship by default:
| Pipeline | Phases | Engine |
|---|---|---|
simple |
1 | claude only — for trivial goals |
all-claude |
5 + 1/10 reviewer | claude only — full design / impl / verify / simplify cycle |
claude-codex |
6 + 1/10 reviewer | claude design + reviewer, codex for impl/verify/simplify |
Drop a new <name>.json into templates/auto/ and it becomes selectable via pipeline: "<name>" on POST /api/auto/instances.
Click the Auto tab in the sidebar to see all your loops, sorted by recent activity:
Click one to open a full detail view — stats, current iteration, controls, recent log:
Scroll down for the worker session list (each iteration's worker chat is one click away) and the rendered program spec:
Workers tag themselves with AUTO_WORKER=TRUE so they're filtered out of the main session list — you reach them through the Auto tab instead. + New auto spins up a fresh ~/auto-NAME/ directory and a linked main-chat session in one click.
Feather ships two Claude Code skills under skills/. Symlink them into your Claude skills dir to use from any chat:
ln -sf "$(pwd)/skills/auto" ~/.claude/skills/auto
ln -sf "$(pwd)/skills/feather" ~/.claude/skills/feather/auto— start, stop, focus, and inspect auto instances viacurlagainst/api/auto/*./feather— manage the running Feather server (status, logs, quick links, deploy).
npm install inceptel/feather
cd node_modules/feather && npm startOr from source:
git clone https://github.com/inceptel/feather.git && cd feather
npm install # installs deps + builds frontend automatically
npm start # → Feather on http://localhost:4870┌─────────────────────────────────────────┐
│ iPhone / Browser │
│ SolidJS SPA │
│ ├── MessageView (markdown, bubbles) │
│ ├── Terminal (xterm.js + WebSocket) │
│ └── Chat input (auto-grow textarea) │
└──────────┬──────────────────────────────┘
│ HTTP + SSE + WS
▼
┌──────────────────────────────────────────┐
│ Express server │
│ ├── JSONL parser (parseMessage) │
│ ├── Session discovery (2-phase scan) │
│ ├── SSE broadcaster (byte-offset IDs) │
│ ├── fs.watch (inotify, per-directory) │
│ ├── tmux manager (spawn/resume/send) │
│ └── WebSocket terminal (node-pty) │
└──────────┬──────────────────────────────┘
│ filesystem
▼
~/.claude/projects/<hash>/<session>.jsonl
tmux sessions: feather-<8chars>
| File | Purpose |
|---|---|
server.js |
Entire backend — API, SSE, WebSocket, JSONL parsing, tmux |
frontend/src/App.tsx |
UI shell — sidebar, header, tabs, input bar |
frontend/src/api.ts |
REST + SSE client, types |
frontend/src/components/MessageView.tsx |
Chat bubbles with markdown rendering |
frontend/src/components/Terminal.tsx |
xterm.js + WebSocket terminal |
frontend/src/index.tsx |
SolidJS mount point |
- No database. Read JSONL directly. The filesystem is the source of truth.
- No polling.
fs.watch→ SSE push. Client generates session UUID upfront (ClOrdId pattern). - tmux as the process manager. Every Claude session runs in a named tmux session. Terminal tab attaches to it. Chat input sends keystrokes via
send-keys/paste-buffer. - Two-phase session discovery. Stat-only scan + sort by mtime → read first 4KB of top N for titles. 7000+ sessions in 75ms.
- Byte-offset SSE IDs. Enables resumable streams and gap-free message delivery.
- Mobile-first.
--vhviewport fix, safe-area insets,-webkit-overflow-scrolling: touch, PWA meta tags.
cd ~/feather
npm run deploy # stamps version.json, builds frontend, restarts serverBoth backend (/api/health) and frontend (tab bar) show the same version timestamp.
sudo cp infra/feather.supervisor.conf /etc/supervisor/conf.d/feather.conf
supervisorctl reread && supervisorctl updatesudo cp infra/feather.service /etc/systemd/system/
sudo systemctl enable --now featherhandle /feather { redir /feather/ permanent }
handle /feather/api/* {
uri strip_prefix /feather
reverse_proxy localhost:4870 {
flush_interval -1 # required for SSE
}
}
handle /feather/* {
uri strip_prefix /feather
reverse_proxy localhost:4870
}
Backend: express, node-pty, ws Frontend: solid-js, @xterm/xterm, @xterm/addon-fit, marked, dompurify
Elastic License 2.0 — free to use, modify, and distribute. Cannot be offered as a hosted service.


