Skip to content

inceptel/feather

Repository files navigation

Feather

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.

Make it yours

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.

Fork and share

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 away

Pulling 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/main

Contributing back:

Open a PR to inceptel/feather from your fork. Or don't — your fork is yours.

Why

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.

/auto — autonomous improvement loops

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:

Auto sidebar

Click one to open a full detail view — stats, current iteration, controls, recent log:

Auto detail — top

Scroll down for the worker session list (each iteration's worker chat is one click away) and the rendered program spec:

Auto detail — bottom

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.

Slash commands

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 via curl against /api/auto/*.
  • /feather — manage the running Feather server (status, logs, quick links, deploy).

Quick start

npm install inceptel/feather
cd node_modules/feather && npm start

Or 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

Architecture

┌─────────────────────────────────────────┐
│  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>

Files

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

Design decisions

  • 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. --vh viewport fix, safe-area insets, -webkit-overflow-scrolling: touch, PWA meta tags.

Deploying changes

cd ~/feather
npm run deploy    # stamps version.json, builds frontend, restarts server

Both backend (/api/health) and frontend (tab bar) show the same version timestamp.

Deployment

supervisord

sudo cp infra/feather.supervisor.conf /etc/supervisor/conf.d/feather.conf
supervisorctl reread && supervisorctl update

systemd

sudo cp infra/feather.service /etc/systemd/system/
sudo systemctl enable --now feather

Reverse proxy (Caddy)

handle /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
}

Dependencies

Backend: express, node-pty, ws Frontend: solid-js, @xterm/xterm, @xterm/addon-fit, marked, dompurify

License

Elastic License 2.0 — free to use, modify, and distribute. Cannot be offered as a hosted service.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors