Skip to content

illegalstudio/lazyagent

Repository files navigation

lazyagent

GitHub Downloads License: MIT Product Hunt

A terminal UI, macOS menu bar app, and HTTP API for monitoring all your coding agents — Claude Code, Cursor, pi, and OpenCode — from a single place. No lock-in, no server, purely observational.

Inspired by lazygit, lazyworktree, and pixel-agents.

Why lazyagent?

Unlike other tools, lazyagent doesn't replace your workflow — it watches it. Launch agents wherever you want (terminal, IDE, desktop app), lazyagent just observes. No lock-in, no server, no account required.

⭐ If lazyagent is useful to you, consider starring the repo — it helps others discover it!

Terminal UI

lazyagent TUI

macOS Menu Bar App

lazyagent macOS tray

HTTP API

lazyagent API playground

How it works

lazyagent watches session data from coding agents to determine what each session is doing. No modifications to any agent are needed — it's purely observational.

Supported agents:

  • Claude Code CLI — reads JSONL from ~/.claude/projects/*/
  • Claude Code Desktop — same JSONL files, enriched with session metadata (title, permissions) from ~/Library/Application Support/Claude/claude-code-sessions/
  • Cursor — reads SQLite from ~/Library/Application Support/Cursor/User/globalStorage/state.vscdb
  • pi coding agent — reads JSONL from ~/.pi/agent/sessions/*/
  • OpenCode — reads SQLite from ~/.local/share/opencode/opencode.db

Use --agent claude, --agent pi, --agent opencode, --agent cursor, or --agent all (default) to control which agents are monitored. Agents can also be enabled/disabled in the config file. Pi sessions are marked with a π prefix, Cursor with C, OpenCode with O, and Desktop sessions with a D prefix in the session list.

From the JSONL stream it detects activity states with color-coded labels:

  • idle — Session file exists but no recent activity
  • waiting — Claude responded, waiting for your input (with 10s grace period to avoid false positives)
  • thinking — Claude is generating a response
  • compacting — Context compaction in progress
  • reading / writing / running / searching / browsing / spawning — Tool-specific activities

It also surfaces:

Info Source
Working directory JSONL
Git branch JSONL
Claude version JSONL
Model used JSONL
Is git worktree git rev-parse
Main repo path (if worktree) git worktree
Message count (user/assistant) JSONL
Token usage & estimated cost JSONL
Activity sparkline (last N minutes) JSONL
Last file written JSONL
Recent conversation (last 5 messages) JSONL
Last 20 tools used JSONL
Last activity timestamp JSONL
Session source (CLI / Desktop) Desktop metadata
Desktop session title Desktop metadata
Permission mode (Desktop) Desktop metadata
Custom session name ~/.config/lazyagent/session-names.json

Three interfaces, one binary

lazyagent ships as a single binary with three interfaces:

TUI macOS Menu Bar HTTP API
Interface Terminal (bubbletea) Native menu bar panel (Wails v3 + Svelte 5) REST + SSE
Launch lazyagent lazyagent --tray lazyagent --api
Dock icon N/A Hidden (accessory) N/A
Sparkline Unicode braille characters SVG area chart JSON data
Theme Terminal colors Catppuccin Mocha (Tailwind 4) N/A

All three share internal/core/ — session discovery, file watcher, activity state machine, cost estimation, and config. You can combine them freely: lazyagent --tui --tray --api.

Install

Homebrew

brew tap illegalstudio/tap
brew install lazyagent

Go (TUI only)

go install github.com/illegalstudio/lazyagent@latest

Build from source

git clone https://github.com/illegalstudio/lazyagent
cd lazyagent

# TUI only (no Wails/Node.js needed)
make tui

# Full build with menu bar app (requires Node.js for frontend)
make install   # npm install (first time only)
make build

macOS note

On first launch, macOS may block the binary. Go to System Settings → Privacy & Security, scroll down and click Allow Anyway, then run it again.

Usage

lazyagent                        Launch the terminal UI (monitors all agents)
lazyagent --agent claude         Monitor only Claude Code sessions
lazyagent --agent pi             Monitor only pi coding agent sessions
lazyagent --agent opencode       Monitor only OpenCode sessions
lazyagent --agent cursor         Monitor only Cursor sessions
lazyagent --agent all            Monitor all agents (default)
lazyagent --api                  Start the HTTP API (http://127.0.0.1:7421)
lazyagent --api --host :8080     Start the HTTP API on a custom address
lazyagent --tui --api            Launch TUI + API server
lazyagent --tray                 Launch as macOS menu bar app (detaches)
lazyagent --tray --api           Launch tray + API server (foreground)
lazyagent --tui --tray --api     Launch everything
lazyagent --help                 Show help

TUI

Keybindings

Key Action
/ k Move up / scroll up (detail)
/ j Move down / scroll down (detail)
tab Switch focus between panels
+ / - Adjust time window (±10 minutes)
f Cycle activity filter
/ Search sessions by project path
o Open session CWD in editor (see below)
r Rename session (empty name resets)
q / ctrl+c Quit

macOS Menu Bar App

lazyagent --tray

The tray process detaches automatically — your terminal returns immediately. The app lives in your menu bar with no Dock icon. Click the tray icon to toggle the panel.

Keybindings

Key Action
/ k Move up
/ j Move down
+ / - Adjust time window (±10 minutes)
f Cycle activity filter
/ Search sessions
r Rename session (empty name resets)
esc Close detail / dismiss search

Right-click menu

  • Show Panel — open the session panel
  • Refresh Now — force reload all sessions
  • Quit — exit the app

HTTP API

lazyagent --api

Starts a read-only HTTP API server on http://127.0.0.1:7421 (default port, with automatic fallback if busy).

Endpoint Description
GET /api Interactive playground (open in browser)
GET /api/sessions List visible sessions (?search=, ?filter=)
GET /api/sessions/{id} Full session detail
PUT /api/sessions/{id}/name Rename session ({"name": "..."}, empty resets)
DELETE /api/sessions/{id}/name Remove custom name
GET /api/stats Summary stats (total, active, window)
GET /api/config Current configuration
GET /api/events SSE stream for real-time updates

To expose on the network (e.g. for a mobile app):

lazyagent --api --host 0.0.0.0:7421

Full API documentation: docs/API.md

Editor support

Pressing o (TUI) or the Open button (app) opens the selected session's working directory in your editor.

Cursor sessions automatically open in Cursor IDE (if the cursor CLI is installed). If not installed, the standard editor flow below is used.

Configuration Behavior
Both $VISUAL and $EDITOR set A picker popup asks which one to use (TUI only)
Only $VISUAL set Opens directly as GUI editor
Only $EDITOR set Opens directly as TUI editor (suspends the TUI)
Neither set Shows a hint to configure them
# Example: add to ~/.zshrc or ~/.bashrc
export VISUAL="code"   # GUI editor (VS Code, Cursor, Zed, …)
export EDITOR="nvim"   # TUI editor (vim, nvim, nano, …)

Configuration

lazyagent reads ~/.config/lazyagent/config.json (created automatically with defaults on first run):

{
  "window_minutes": 30,
  "default_filter": "",
  "editor": "",
  "launch_at_login": false,
  "notifications": false,
  "notify_after_sec": 30,
  "agents": {
    "claude": true,
    "cursor": true,
    "opencode": true,
    "pi": true
  }
}
Field Default Description
window_minutes 30 Time window for session visibility (minutes)
default_filter "" Default activity filter (empty = show all)
editor "" Override for $VISUAL/$EDITOR
launch_at_login false Auto-start the menu bar app at login
notifications false macOS notifications when a session needs input
notify_after_sec 30 Seconds before triggering a "waiting" notification
agents all true Enable/disable individual agent providers

Architecture

lazyagent/
├── main.go                     # Entry point: dispatches --tui / --tray / --api / --agent
├── internal/
│   ├── core/                   # Shared: watcher, activity, session, config, helpers
│   │   └── provider.go         # SessionProvider interface + Multi/Live/Pi/OpenCode/Cursor providers
│   ├── model/                  # Shared types (Session, ToolCall, etc.)
│   ├── claude/                 # Claude Code JSONL parsing, desktop metadata, session discovery
│   ├── cursor/                 # Cursor IDE session discovery from state.vscdb
│   ├── pi/                     # pi coding agent JSONL parsing, session discovery
│   ├── opencode/               # OpenCode SQLite parsing, session discovery
│   ├── api/                    # HTTP API server (REST + SSE)
│   ├── ui/                     # TUI rendering (bubbletea + lipgloss)
│   ├── tray/                   # macOS menu bar app (Wails v3, build-tagged)
│   └── assets/                 # Embedded frontend dist (go:embed)
├── frontend/                   # Svelte 5 + Tailwind 4 (menu bar app UI)
│   ├── src/
│   │   ├── App.svelte
│   │   ├── lib/                # SessionList, SessionDetail, Sparkline, ActivityBadge
│   │   └── bindings/           # Auto-generated Wails TypeScript bindings
│   └── app.css                 # Tailwind 4 @theme (Catppuccin Mocha)
├── docs/                       # Documentation
│   └── API.md                  # Full HTTP API reference
└── Makefile

Development

# Install frontend deps (first time)
make install

# Full build (TUI + tray)
make build

# Build TUI only (no Wails/Node.js needed)
make tui

# Quick dev cycle (rebuild + run tray)
make dev

# Clean all artifacts
make clean

Requirements

  • Go 1.25+
  • Node.js 18+ (for frontend build)
  • macOS (for the menu bar app — TUI works on any platform)

Roadmap

v0.1 — Core TUI

  • Discover all Claude Code sessions from ~/.claude/projects/
  • Parse JSONL to determine session status
  • Detect worktrees
  • Show tool history
  • FSEvents-based file watcher with debouncing
  • Fallback 30s polling

v0.2 — Richer session info

  • Conversation preview in detail panel (last 5 messages, User/AI labels)
  • Last file written with age
  • Filter sessions by activity type
  • Search sessions by project path
  • Time window control (show last N minutes)
  • Color-coded activity states with grace periods
  • Memory-efficient single-pass JSONL parsing
  • Activity sparkline graph in session list
  • Token usage and cost estimation in detail panel
  • Animated braille spinner for active sessions
  • o key to open session CWD in editor
  • Rename sessions with persistent custom names (r key)
  • Display file diff for last written file

v0.3 — macOS menu bar app

  • Core library extraction (internal/core/)
  • Shared config system (~/.config/lazyagent/config.json)
  • Wails v3 + Svelte 5 + Tailwind 4 frontend
  • System tray with attached panel (frameless, translucent, floating)
  • Real-time session updates via FSEvents + event push
  • SVG sparkline, activity badges, conversation preview
  • Keyboard shortcuts (j/k, /, f, +/-, r, esc)
  • Open in editor from detail panel
  • Dynamic tray icon (active session count)
  • macOS notifications when session needs input
  • Launch at Login
  • Code signing & notarization
  • DMG distribution
  • Homebrew cask

v0.4 — HTTP API

  • REST API server (--api flag)
  • Session list, detail, stats, config endpoints
  • Server-Sent Events (SSE) for real-time push updates
  • Interactive API playground (/api in browser)
  • Default port with automatic fallback (7421–7431)
  • Custom bind address (--host)
  • Combinable with TUI and tray (--tui --tray --api)
  • Session rename endpoints (PUT/DELETE /api/sessions/{id}/name)

v0.5 — Multi-agent support

  • pi coding agent session discovery (~/.pi/agent/sessions/)
  • Pi JSONL parser (tree-structured format → shared Session struct)
  • --agent flag (claude, pi, all)
  • MultiProvider merging sessions from multiple agents
  • Agent type indicator (π prefix in list, Agent row in detail)
  • Pi tool name normalization (snake_case → PascalCase)
  • Multi-directory file watcher
  • Cost estimation for Gemini and GPT model families
  • Claude Code Desktop support (title, permissions, source badge)
  • Shared session types extracted to internal/model

v0.6 — OpenCode support

  • OpenCode session discovery from SQLite (~/.local/share/opencode/opencode.db)
  • --agent opencode flag
  • Polling-based refresh (5s interval, no file watcher needed)
  • Tool name normalization and activity mapping
  • Subagent detection via parent_id

v0.7 — Cursor support

  • Cursor session discovery from state.vscdb (composerData + bubbleId entries)
  • --agent cursor flag
  • WAL-based cache invalidation for real-time updates
  • CWD inference from file URIs when workspace URI is unavailable
  • Cursor tool name normalization (Read_file_v2, Glob_file_search, etc.)
  • Open in Cursor IDE (with fallback if CLI not installed)
  • Per-agent enable/disable in config (agents map)

Future ideas

  • Outbound webhooks on status changes
  • Multi-machine support via shared config / remote API
  • TUI actions: kill session, attach terminal
  • Session history browser (browse past conversations)