npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

marmonitor

v0.2.6

Published

tmux status bar monitor for AI coding agents — track Claude Code, Codex, Gemini sessions, tokens, and phases in real time

Readme


Why marmonitor?

Running multiple AI coding agents in tmux is now the norm — Claude Code refactoring your backend, Codex writing tests in another pane, Gemini reviewing docs in a third. But as sessions multiply, you hit the same wall:

  • You switch to a pane only to find the agent has been waiting for allow for 10 minutes
  • You forget which window has the Codex session you were just working with
  • You have no idea how many tokens you've burned across sessions

There's no dashboard for this. You're alt-tabbing between panes, checking each one manually.

marmonitor fixes this. One line in your tmux.conf, and your status bar becomes a live control panel for every AI session on your machine.

What it does

tmux statusline — always visible at the bottom of your terminal:

  • Agent counts (Cl 12, Cx 2, Gm 1) — how many sessions are running
  • Phase alerts (⏳ 1, 🤔 2, 🔧 1) — which sessions need attention
  • Numbered pills (1 ⏳Cl my-project allow, 2 •Cx api-server 6m) — jump to any session with Option+1~5

Attention priority — sessions that need your input come first:

  • permission (allow waiting) is always #1 — you need to approve
  • 🤔 thinking (AI responding) is #2 — result coming soon
  • Then most recently active sessions, so you can quickly return to what you were working on

Quick jump — press Option+1 to jump directly to the #1 attention session's tmux pane. No searching through windows.

Full statusmarmonitor status shows everything:

Zero instrumentation — no API keys, no agent plugins, no code changes. marmonitor reads local process info and session files from the outside. Two commands to get started: npm install -g marmonitor then marmonitor setup tmux.

Built for the tmux + AI multi-session workflow. If you run 5+ AI coding sessions daily across different projects, marmonitor turns context-switching from guesswork into a glance at your status bar.

The problem

None of the major AI coding agents expose an external API for session introspection. There's no claude sessions list, no webhook when a session changes state. To show you live token counts, phase, and lastResponseAt, marmonitor has to read and interpret each agent's internal data formats — which are completely different across agents, undocumented, and subject to change.

But the harder problem isn't parsing files. It's reliably binding a live OS process to the right session file — and keeping that binding correct as sessions evolve.

Why binding is hard

A naïve approach — "find the agent process, read the newest session file" — breaks under common real-world conditions:

  • /clear in Claude Code creates a new session UUID and a new JSONL file while the PID stays the same. Without re-mapping, marmonitor would keep reading the old file and report stale tokens and a frozen lastResponseAt.
  • Stale PID metadata — Claude writes ~/.claude/sessions/{pid}.json with the current session ID, but after /clear this file can lag behind the actual new session for a window of time.
  • Multiple sessions sharing a cwd — when you run two Claude sessions in the same project directory, mtime-based file selection silently picks the wrong JSONL, misattributing one session's activity to another.
  • Delayed file creation — a session file may not exist on disk yet when the process is first detected, requiring provisional binding with promotion once the file appears.

Any of these failures corrupts downstream metrics: token usage, phase detection, and lastResponseAt all read from the bound file.

The binding pipeline

For every detected agent process, marmonitor resolves a chain of five steps:

PID
 └─ Identity Resolver     → session identity (sessionId or thread index)
     └─ File Binding       → session file path  (direct or provisional)
         └─ Reconciliation → stale/clear correction when needed
             └─ Binding Cache    → in-memory, current binding only
                 └─ Binding History  → disk registry, per-session accumulation

Each agent traverses this chain differently:

| | Identity Resolver | File Binding | Reconciliation | |--|--|--|--| | Claude Code | ~/.claude/sessions/{pid}.jsonsessionId | {sessionId}.jsonl (direct) or mtime-proximity match (provisional) | chooseStaleSessionOverride() detects /clear and stale pid metadata | | Codex | cwd + processStartedAt matched against SQLite thread index | Rollout JSONL or SQLite row, via binding registry keyed on pid + processStartedAt | Freshness correction via binding registry TTL | | Gemini | cwd → resolved project dir under ~/.gemini/tmp/ | Latest chats/session-*.json by mtime | Lightweight — single active session per project dir |

Why this matters

The binding layer is what makes the numbers in your status bar trustworthy. A direct binding means the file path was confirmed from session metadata — marmonitor won't swap it without evidence. A provisional binding is held until a direct file appears, then promoted automatically. Reconciliation only overrides when specific conditions are met (mtime lead, metadata confirmation, active file guard) — not on every scan.

This design is also the reason marmonitor can correctly track sessions across /clear, restarts, and parallel sessions in the same project — scenarios where simpler monitors silently fall back to wrong data.

Supported Agents

| Agent | Detection | Session Enrichment | Phase Tracking | |-------|-----------|-------------------|----------------| | Claude Code | Native binary | Tokens, timestamps, model | thinking, tool, permission, done | | Codex | Binary + cmd fallback | Tokens, timestamps, model | thinking, tool, done | | Gemini | cmd fallback | Tokens, timestamps, model | thinking, tool, done |

Install

1. Install marmonitor

npm install -g marmonitor

2. Set up tmux integration

marmonitor setup tmux

This adds the marmonitor-tmux plugin to your ~/.tmux.conf. Then press prefix + I inside tmux to activate.

After upgrading marmonitor, run:

marmonitor update-integration

This checks whether your tmux integration also needs a TPM/plugin update.

If you updated the TPM plugin with prefix + U but click actions or popup keybindings still behave like the old version, re-apply the plugin in the running tmux server:

tmux run-shell ~/.tmux/plugins/marmonitor-tmux/marmonitor.tmux

This mainly affects existing tmux sessions after a plugin upgrade. Fresh installs via prefix + I usually load the current bindings immediately.

set -g @plugin 'mjjo16/marmonitor-tmux'

Requires tpm.

git clone https://github.com/mjjo16/marmonitor-tmux ~/.tmux/plugins/marmonitor-tmux

Add to ~/.tmux.conf:

run-shell ~/.tmux/plugins/marmonitor-tmux/marmonitor.tmux
git clone https://github.com/mjjo16/marmonitor.git
cd marmonitor
npm install && npm run build
npm link

Quick Start

Start the daemon

marmonitor runs as a background daemon that scans your AI sessions every 2 seconds:

marmonitor start        # Start the daemon
marmonitor stop         # Stop the daemon
marmonitor restart      # Restart (e.g. after npm update)

The daemon must be running for all other commands to work. marmonitor setup tmux starts it automatically.

tmux shortcuts

| Shortcut | Action | |----------|--------| | prefix + a | Attention popup — choose a session to review | | prefix + j | Jump popup — pick a session to jump to | | prefix + y | Copy the latest AI assistant turn from the active pane | | prefix + m | Dock — compact monitor pane | | Option+1~5 | Direct jump to attention session #1~5 | | `Option+`` | Jump back to previous pane |

CLI commands

marmonitor status       # Full session inventory
marmonitor attention    # What needs your input?
marmonitor activity     # What did each session do? (tool calls + tokens)
marmonitor copy-latest-turn   # Copy the latest AI/user turn from the active tmux pane
marmonitor watch        # Live full-screen monitor
marmonitor jump-back    # Return to pane before last jump
marmonitor help         # All commands and options

Activity log

Track what your AI sessions actually did — file edits, bash commands, tokens used:

marmonitor activity                  # Today's activity
marmonitor activity --pid 1234       # Filter by PID
marmonitor activity --session abc    # Filter by session ID
marmonitor activity --days 3         # Last 3 days
marmonitor activity --json           # JSON output

Activity is collected automatically by the daemon and stored in ~/.config/marmonitor/activity-log/ (7-day retention).

Phase Icons

| Icon | Phase | Meaning | |------|-------|---------| | ⏳ | permission | AI requesting tool approval — user input needed | | 🤔 | thinking | AI generating a response | | 🔧 | tool | Approved tool executing | | ✅ | done | Response complete, awaiting next instruction |

Status Labels

| Label | Meaning | |-------|---------| | [Active] | CPU activity detected | | [Idle] | Process alive, no recent activity | | [Stalled] | No activity for extended period | | [Dead] | Session file exists but process is gone | | [Unmatched] | AI process found but no matching session |

tmux Plugin

The marmonitor-tmux plugin handles all tmux setup automatically:

  • 2nd status line with agent badges and attention pills
  • Key bindings for popup, jump, latest-turn copy, and dock
  • Option+1~5 direct jump

All settings are customizable via @marmonitor-* options. See the plugin README for details.

Badge styles

tmux badges and terminal text output can share one style via integration.tmux.badgeStyle.

  • basic — default colored pills
  • basic-mono — monochrome pills with Powerline borders
  • block — filled background badges without Powerline separator glyphs
  • block-mono — monochrome filled badges without Powerline separator glyphs
  • text — plain colored text, no filled background
  • text-mono — grayscale text only

The currently active tmux pane is also highlighted in the attention pill row so it is easier to see which session belongs to the focused window.

Alerts

marmonitor includes an alert system for important runtime signals such as critical token/context usage and guard-triggered risk events.

Useful commands:

marmonitor alerts
marmonitor alerts on
marmonitor alerts off
marmonitor alerts tokens on
marmonitor alerts tokens off
marmonitor alerts notify on
marmonitor alerts notify off

Desktop notifications can be enabled separately from alert collection, and token/context alerts can be silenced without turning off security alerts. After changing alert settings, restart the daemon to apply them:

marmonitor restart

Configuration

Config is loaded from (first found wins):

  1. $XDG_CONFIG_HOME/marmonitor/settings.json
  2. ~/.config/marmonitor/settings.json
  3. ~/.marmonitor.json
# View current config path and values
marmonitor settings-path
marmonitor settings-show

# Generate a starter config
marmonitor settings-init --stdout

Example Config

{
  "display": {
    "attentionLimit": 10,
    "statuslineAttentionLimit": 5
  },
  "status": {
    "stalledAfterMin": 20,
    "phaseDecay": {
      "thinking": 20,
      "tool": 30,
      "permission": 0,
      "done": 5
    }
  },
  "integration": {
    "tmux": {
      "badgeStyle": "basic",
      "keys": {
        "attentionPopup": "a",
        "jumpPopup": "j",
        "dockToggle": "m",
        "directJump": ["M-1", "M-2", "M-3", "M-4", "M-5"]
      }
    }
  }
}

Uninstall

marmonitor uninstall-integration    # Remove tmux settings + restore status bar
npm uninstall -g marmonitor         # Remove CLI

Safety

  • Read-only by default — observes only, never modifies your sessions
  • No network — zero outbound connections, all data stays local
  • Conservative defaults — all integrations are opt-in
  • tmux-first — terminal-native WezTerm/iTerm2 surfaces are currently paused

Changelog

See CHANGELOG.md for release history and breaking changes.

Contributing

See CONTRIBUTING.md for setup, commit conventions, and PR guidelines. For architecture details, see ARCHITECTURE.md.

Known Limitations

  • Pane jump requires tmux
  • WezTerm / iTerm2 native bars are paused for now; tmux is the supported surface
  • Gemini permission detection is limited due to Ink TUI architecture
  • Phase detection relies on heuristics — accuracy varies by agent
  • macOS first; Linux support is untested

License

MIT — MJ JO