macOS only (for now) — lomon currently relies on macOS-specific APIs (osascript folder picker, Terminal.app / iTerm integration). Linux and Windows support is tracked in #1.
A local-only web dashboard for watching every Claude Code session running on your machine — at a glance, in real time, with no terminal switching.
If you regularly run two or more claude sessions in parallel (subagents, multiple worktrees, long-running autonomous tasks), lomon is the dashboard that tells you what each one is doing right now.
This is not a shared service. Each person clones the repo and runs their own instance on their own machine. The backend binds to
127.0.0.1, reads files only under~/.claude/, and never sends anything off your machine. There's no auth, no multi-user model, no central deployment — the data lomon shows is your private Claude session content, which never needs to leave your machine.
- Live session list — every Claude Code session currently running on your machine, sorted by most recent activity. Sessions older than 7 days roll up into an "older" group.
- Per-session event stream — click into any session to see its full history (user prompts, assistant messages, tool calls, tool results, errors) updating live as the agent works.
↓ latestsnaps you back to the tail when you've scrolled up. - Subagent grouping — Task-tool subagents nest under their parent session with a
N subagents ▸expansion showing each as a compact 2-line summary (branch + last activity). - Send messages from the browser — type into any session's detail page and the message is injected via
claude --print --resume <id>. Multi-stage send indicator (uploading → sending → ✓ sent), image paste, and a quick-message form on each session row. - ▶ continue in terminal — pick up any session in iTerm or Terminal.app with the cwd + resume args pre-typed.
- 24-hour history — past sessions and events in SQLite, searchable by keyword and event type.
- Light + dark themes, compact / fully-formatted preview toggle, configurable font size.
- macOS (Ventura or later recommended)
- Node.js 22+ (the backend uses modern ESM and native modules — older Node versions will fail to build
better-sqlite3) - Xcode Command Line Tools on macOS, for the native
better-sqlite3compile:xcode-select --install claudeCLI installed and on your$PATH— needed to send messages from the browser- Claude Code session files in the standard location:
~/.claude/projects/<encoded-cwd>/<session-id>.jsonland the process registry at~/.claude/sessions/<pid>.json(default for recent Claude Code versions)
git clone https://github.com/betterup/lomon-os.git
cd lomon-os
npm install
npm run devThen open http://localhost:5173 in your browser.
The first npm install compiles better-sqlite3 natively (~30 seconds). Subsequent installs are instant. npm run dev starts both the backend (Fastify on 127.0.0.1:7878) and the frontend dev server (Vite on 5173) concurrently, with colored log prefixes.
Stop: Ctrl-C once.
Don't expose the backend port over the network or behind a reverse proxy. It has no authentication and exposes your Claude session history — including conversation transcripts and tool calls — to anyone who can reach it.
The default page. Each running Claude session appears as a row:
- Project name, short session id, status pill (active / idle / ended), elapsed time, current git branch, freshness cue
- Last activity preview (most recent tool call, assistant message, etc.)
- Per-row actions:
✉ message · → details · ▶ continue · × delete - Subagents (Task-tool invocations) appear under their parent as a
N subagents ▸pill — click to expand inline - Header hint about polling cadence: idle sessions rescan every 2 min; long-idle drop to 10 min
Click any session row:
- Header: project, session id, branch, start time, elapsed, status, cost when known
- Full event stream with day-by-day separators
↓ latestbutton (lower-right) when you've scrolled up — snaps to the tail- Message input at the bottom — type to send to that session via
claude --print --resume. Paste an image and it goes along too. - Subagent detail pages disable the message input and explain why (subagents can't be
--resumed directly).
Top-nav tab. Shows past sessions and events from SQLite — useful for "what did that session do an hour ago?" Supports keyword search and event-type filter.
Top-nav tab. Configure:
| Setting | Effect |
|---|---|
terminalApp |
Terminal (default) or iTerm — which macOS app lomon opens when you click ▶ continue |
baseFontSize |
Root font-size in pixels (10–24). Previews immediately; click save to persist. |
Persisted to ~/.lomon/settings.json. Backend re-reads on every request; no restart needed.
● <op> running <elapsed>pill — visible while ≥1 lomon-launched Terminal window is open; hover for the full list.⛁ <size>button — hover for cache stats (event count, history rows, oldest event age); click to wipehistory.db(two-step confirm).- Preview toggle — compact / fully-formatted last-activity preview on each row.
- Theme toggle — light / dark.
lomon doesn't proxy or intercept Claude Code. It just watches the files Claude already writes:
| What | Where |
|---|---|
| Live session events | tails ~/.claude/projects/<slug>/<sessionId>.jsonl |
| Subagent events | tails ~/.claude/projects/<slug>/<parent-id>/subagents/agent-*.jsonl |
| Process liveness | watches ~/.claude/sessions/<pid>.json (each running claude writes one) |
| Terminal-window lifecycle | each lomon-launched window writes a temp /tmp/lomon-launcher-<token>.sh with trap 'rm -f "$0"' EXIT; the backend polls file existence every 1.5s to know when the inner command finished |
A SQLite database at ~/.local/share/lomon/history.db persists past events so the History view survives backend restarts. Events older than 24h are deleted hourly; the ⛁ clear button runs wal_checkpoint(TRUNCATE) + VACUUM to shrink the file on demand.
Each browser tab subscribes to a server-sent-events stream (/api/stream) carrying normalized events, session liveness updates, and terminal-job lifecycle messages. New events appear in the UI within a few hundred milliseconds of being written to disk.
All settings are on the Settings page in the UI (persisted to ~/.lomon/settings.json). The following environment variables are also available — they override the file:
| Variable | Default | Effect |
|---|---|---|
LOMON_PORT |
7878 |
Backend HTTP port (the Vite dev server is always on 5173) |
- Local only. The backend binds explicitly to
127.0.0.1. Nothing leaves your machine. - Read-only against Claude's files. lomon never modifies your session JSONL files or process registry. (Exceptions: the "send message" feature spawns
claude --print --resume, whose output is appended by Claude, not by lomon. The⛁ clearbutton deletes lomon's ownhistory.dbcache — never anything under~/.claude/.) - Image uploads from the browser are staged at
/tmp/lomon-uploads/<sessionId>/and referenced as@<path>in the prompt. Cleared on reboot. - Terminal launches use AppleScript via
osascript(not shell injection). Each launch writes a temp script to/tmp/lomon-launcher-*.shthat self-deletes on exit. - No telemetry. No outbound network requests except the local SSE stream between frontend and backend.
- First
npm installcan fail onbetter-sqlite3without a C++ toolchain. Fix:xcode-select --installand retry. - Sending a message to an actively-writing session can race with the running process (two concurrent appenders on the same JSONL). Wait for the status pill to show
idlebefore sending. The UI shows a "session is busy" force-retry prompt if it detects the race up front. - Crash-leaked registry files: if a
claudeprocess is killed withkill -9, its~/.claude/sessions/<pid>.jsonmay not be cleaned up. lomon defends against this withlsof-based liveness checks before reporting a session as active. - History retention is hardcoded at 24h. Events older than that are deleted by an hourly purge job.
- iTerm Automation permission — first time you trigger an iTerm launch from lomon, macOS prompts for Automation access. If you decline, terminal launches silently fail; the backend logs the
osascriptstderr at WARN level.
lomon/
├── backend/ Fastify server, JSONL watcher, SQLite, SSE
├── frontend/ Vite + React web UI
├── packages/types/ Shared TypeScript types (backend + frontend)
Issues and PRs are welcome. See CONTRIBUTING.md for more details.