Skip to content

betterup/lomon-os

Repository files navigation

lomon

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.


What it gives you

  • 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. ↓ latest snaps 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.

Requirements (macOS only)

  • 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-sqlite3 compile: xcode-select --install
  • claude CLI 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>.jsonl and the process registry at ~/.claude/sessions/<pid>.json (default for recent Claude Code versions)

Quick start

git clone https://github.com/betterup/lomon-os.git
cd lomon-os
npm install
npm run dev

Then 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.


Using it

Live view

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

Session detail

Click any session row:

  • Header: project, session id, branch, start time, elapsed, status, cost when known
  • Full event stream with day-by-day separators
  • ↓ latest button (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).

History view

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.

Settings

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.

Header utilities

  • ● <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 wipe history.db (two-step confirm).
  • Preview toggle — compact / fully-formatted last-activity preview on each row.
  • Theme toggle — light / dark.

How it works

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.


Configuration

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)

Privacy & safety

  • 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 ⛁ clear button deletes lomon's own history.db cache — 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-*.sh that self-deletes on exit.
  • No telemetry. No outbound network requests except the local SSE stream between frontend and backend.

Known caveats

  • First npm install can fail on better-sqlite3 without a C++ toolchain. Fix: xcode-select --install and 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 idle before sending. The UI shows a "session is busy" force-retry prompt if it detects the race up front.
  • Crash-leaked registry files: if a claude process is killed with kill -9, its ~/.claude/sessions/<pid>.json may not be cleaned up. lomon defends against this with lsof-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 osascript stderr at WARN level.

Layout

lomon/
├── backend/         Fastify server, JSONL watcher, SQLite, SSE
├── frontend/        Vite + React web UI
├── packages/types/  Shared TypeScript types (backend + frontend)

Contributing

Issues and PRs are welcome. See CONTRIBUTING.md for more details.


License

MIT

About

A local monitor for watching every Claude Code session running on your machine — at a glance, in real time, with no terminal switching.

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors