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

agent-resumer

v0.6.0

Published

Local auto-resume supervisor for AI coding-agent terminals: detect Claude Code, Codex CLI, OMX, OpenCode, and managed-command limits, wake the original tmux pane, and verify recovery.

Readme

agent-resumer

agent-resumer is a local auto-resume supervisor for AI coding-agent terminals. It watches Claude Code, Codex CLI, OMX, and OpenCode local session state, detects usage-limit/rate-limit reset signals, waits until the provider reset/backoff window, and resumes the original terminal pane when it can.

agent-resumer is not a rate-limit bypass. It only retries after a provider-declared reset time, a retry-after window, or a bounded fallback backoff.

What changed in the current UX

The preferred path is now tmux same-pane resume:

  1. agent-resumer runs as a background watcher.
  2. Shell shims let you keep typing normal commands such as claude, codex, and opencode.
  3. If those commands run inside tmux, the shim records the current $TMUX_PANE.
  4. watch links the transcript session to that pane.
  5. When the reset time arrives, agent-resumer sends continue to the original pane with tmux send-keys and flashes a confirmation banner on that pane so you can see it happened.
  6. If no safe visible pane is known, it does not silently start a background agent; use --headless or agent-resumer resume when you explicitly want that.

This means the original Claude/Codex/OpenCode screen can continue instead of a hidden detached process doing work elsewhere.

Confirming a resume happened:

  • Every pane resume flashes a tmux display-message banner on the resumed pane (agent-resumer ▸ resumed <id>). Disable it with --no-pane-banner or AGENT_RESUMER_PANE_BANNER=0.
  • Set focusOnResume (config), --focus-on-resume, or AGENT_RESUMER_FOCUS_ON_RESUME=1 to also switch your tmux view to the resumed pane. Off by default so a resume never steals focus from what you are doing.
  • Notifications (--notify) name where the resume landed — resumed in pane %N or resumed headless (background) — log: <path> — so a background resume is never indistinguishable from a visible one.

If several tmux/purplemux panes share the same working directory, agent-resumer stays conservative. A watch tick reports safeBlocked: true, candidateCount, candidateDetails, a diagnoseCommand, and one bindCommands entry per candidate pane instead of sending continue to a guessed pane. Bind the correct pane once, or restart the agent through the shim so future sessions are recorded automatically.

Additional pane safety guards:

  • Shims now remember the tmux socket/server from $TMUX; watch/diagnose/resume reuse that socket instead of assuming the default tmux server.
  • Background services read AGENT_RESUMER_TMUX_SOCKETS (comma/newline-separated socket paths). The installed launchd wrapper populates it from standard tmux socket directories plus one-hop $HOME/.*/tmux.sock sockets, so tmux-compatible wrappers work without product-specific socket paths in agent-resumer itself.
  • Weak stored pane bindings expire after paneBindingTtl (config file, seconds), --pane-binding-ttl <ms>, or AGENT_RESUMER_PANE_BINDING_TTL_MS unless the pane still has strong agent evidence.
  • --strict-pane-echo or AGENT_RESUMER_STRICT_PANE_ECHO=1 refuses to send pane input when capture-pane cannot verify the prompt.
  • A pane-send failure (including a pane that vanished mid-send) is reported as resume_failed and retried — it is never silently turned into a background/headless resume. Explicit headless stays --headless / resume.
  • cwd matching uses realpath when possible, so symlinked worktrees match their real tmux cwd.
  • agent-resumer doctor --json checks shim PATH order, warns about shell functions that call absolute agent binaries and bypass shims, and reports whether tmux is installed (when absent it notes that same-pane resume is disabled and points to explicit --headless/resume usage plus how to install tmux).

Fastest safe path

For the normal product experience, let agent-resumer manage tmux for you:

npm install -g agent-resumer
agent-resumer install-shims --force --auto-tmux
agent-resumer service install
agent-resumer doctor --json
exec $SHELL -l

After that, run your agent normally:

claude
# or
codex
# or
omx
# or
opencode

If you are already inside tmux, the shim records the current $TMUX_PANE when available and never opens a nested tmux session just because --auto-tmux is enabled. Wrapper environments that expose $TMUX but not $TMUX_PANE still run the real CLI directly; they simply skip pane registration until a pane id is available. If you are outside tmux, the opt-in --auto-tmux shim opens a managed tmux session, runs the agent inside it, attaches you there, and lets the normal pane registry capture the new pane. You do not have to start tmux manually.

For a read-only dry run with no shims/service:

npm install -g agent-resumer
agent-resumer --version
agent-resumer watch --once --dry-run --json

The advanced path is more complex because it intentionally tracks which exact tmux/purplemux pane belongs to each agent session. The moving parts are:

  • shell shim PATH order (claude, codex, omx, opencode should resolve through ~/.agent-resumer/shims first),
  • existing shell functions or wrappers that may bypass PATH by calling absolute binaries,
  • tmux socket/server identity, especially with cmux/purplemux or multiple tmux servers,
  • pane binding confidence when several panes share the same cwd,
  • daemon state in ~/.agent-resumer/state.json, locks, and resume verification windows.

The complexity buys safety: if the right pane is ambiguous, agent-resumer reports candidates and refuses to guess instead of typing continue into the wrong terminal.

Windows and WSL

WSL is the recommended Windows story today. If Claude/Codex/OMX/OpenCode, tmux, and the transcripts all live inside the same WSL distro, agent-resumer behaves like it does on Linux. install-shims --auto-tmux can create and attach managed tmux sessions inside that distro.

What is not the same thing as WSL support: native PowerShell/CMD sessions, Windows GUI app terminals, or ConPTY-first desktop integrations. Those can still use agent-resumer run <engine> -- <command...> experimentally, but pane-aware same-terminal recovery is designed around tmux-compatible environments.

Comparison with nearby OSS

| Tool | Main model | Strong at | agent-resumer difference | | --- | --- | --- | --- | | dennis-lynch/claude-code-auto-resume | Claude Code hook sleeps until reset then returns {"continue": true} | Simple Claude-only hook | agent-resumer watches multiple engines and verifies recovery after a resume action. | | FusionCube18712/claude-codex-auto-resume | PTY passthrough wrapper for Claude/Codex/Gemini/generic commands | Cross-platform wrapper UX, Go binaries | agent-resumer does not require every session to start inside a wrapper; it can map existing local transcripts back to safe tmux panes. | | agent-auto-resume (aar) | daemon + PTY managed commands | Claude/Codex/Antigravity managed-command flow | agent-resumer is stricter about original-pane binding, same-cwd ambiguity, and false recovery claims. | | primeline-ai/claude-tmux-orchestration | tmux worker orchestration | Parallel Claude worker management | agent-resumer is not an orchestrator; it focuses on rate/usage-limit recovery for existing local sessions. | | ccs / Claude session registries | name/list/resume Claude sessions | Human-friendly Claude session lookup | agent-resumer adds reset parsing, scheduling, pane resume, fallback resume, and verification. |

Why not just use a wrapper?

Wrappers are great when every agent process starts through that wrapper. agent-resumer is optimized for the messier local reality:

  • you already have long-running Claude/Codex/OMX/OpenCode sessions,
  • a shell function or cmux/purplemux pane may be involved,
  • multiple panes may share the same cwd,
  • a resume command can launch but still be rate-limited,
  • sending input to the wrong pane is worse than doing nothing.

So agent-resumer favors fail-closed supervision over eager retries. resume_sent is not treated as recovered until there is evidence.

Demo

Run a local no-network demo that parses a fake Claude reset, writes a temporary state file, and prints the scheduler decision and isolated state:

scripts/demo-local.sh

To record it as a terminal demo:

asciinema rec /tmp/agent-resumer-demo.cast --command './scripts/demo-local.sh'
# optional if you have agg installed:
# agg /tmp/agent-resumer-demo.cast docs/demo.gif

Experimental managed-command engines

agent-resumer run <engine> -- <command...> can now be used with engines that do not have a transcript watcher yet, including generic, gemini, and antigravity/agy style CLIs:

agent-resumer run gemini -- gemini "continue the task"
agent-resumer run antigravity -- agy run
agent-resumer run generic -- my-agent-cli --work

For these engines, agent-resumer parses common reset signals such as RESOURCE_EXHAUSTED, rate_limit_error, quota exceeded, and try again in .... After the reset window, it replays the original command in the original cwd. This is intentionally labeled experimental: it is reset-aware command replay, not a provider-specific session-ID resume contract.

Supported agents

| Agent | Observed local state | Preferred resume | Fallback resume | | --- | --- | --- | --- | | Claude Code | ~/.claude/projects/<project>/<session-id>.jsonl | tmux send-keys <pane> continue Enter | claude -p --resume <session-id> --output-format json <prompt> | | Codex CLI | ~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl | tmux send-keys <pane> continue Enter | codex exec resume <uuid> --json <prompt> | | OMX | Codex-shaped local session files | tmux send-keys <pane> continue Enter | codex exec resume <uuid> --json <prompt> | | OpenCode | ~/.local/share/opencode/opencode.db | tmux send-keys <pane> continue Enter | opencode run -s <session-id> --dir <cwd> --format json <prompt> | | Managed command (generic, gemini, antigravity) | agent-resumer run <engine> -- <command...> state | command replay in original cwd | command replay in original cwd |

OpenCode discovery uses the sqlite3 command. If sqlite3 is unavailable, OpenCode sessions are skipped.

Install

Recommended install

curl -fsSL https://raw.githubusercontent.com/voidmatcha/agent-resumer/main/scripts/install.sh | bash

The installer:

  • installs the npm package globally
  • installs tmux with Homebrew when available and missing
  • installs shell shims for claude, codex, omx, and opencode
  • adds a dedupe-safe ~/.agent-resumer/shims block to your shell profile
  • installs the background service

Restart your shell after install so the managed PATH block can remove duplicate shim entries and put one shim path first.

Then keep using the normal commands:

claude
codex
opencode

CLI only

This installs only the CLI. It does not start a background service and does not install pane-aware shims unless you run install-shims yourself.

npm install -g agent-resumer
agent-resumer --version
agent-resumer --help

Background service

Use the service when agent-resumer should keep watching after the terminal closes.

agent-resumer service install
agent-resumer service status

npm-only install

npm install -g agent-resumer
agent-resumer --version
agent-resumer install-shims --force --auto-tmux
agent-resumer service install

By default, install-shims adds a managed PATH block for ~/.agent-resumer/shims to your shell profile. On shell startup, that block removes duplicate agent-resumer shim entries and puts one shim path first. Use --no-profile if you only want the shim files. If you skip install-shims, agent-resumer can still detect limits, but background resumes require explicit --headless/resume and it will not reliably know which tmux pane to wake.

Existing shell functions and aliases

Existing shell functions can still work. For example, this kind of wrapper is compatible:

claude () {
  local override
  override="$(serena prompts print-cc-system-prompt-override 2>/dev/null)"
  if [ -n "$override" ]; then
    command claude --system-prompt="$override" "$@"
  else
    command claude "$@"
  fi
}

Why: command claude bypasses the shell function but still resolves claude through PATH. If the agent-resumer shim directory is first in PATH, that function calls the shim, and the shim forwards all arguments to the real Claude binary after recording $TMUX_PANE.

Wrappers that call an absolute binary path, such as /opt/homebrew/bin/claude, bypass PATH shims. Change those wrappers to command claude ... or manually register/bind the pane.

Check resolution with:

type -a claude
whence -p claude  # zsh
command -v claude

Commands

agent-resumer watch --once --json
agent-resumer watch --watch --interval 30000 --quiet
agent-resumer status --json
agent-resumer diagnose claude:<session-id> --json
agent-resumer resume claude:<session-id> --json
agent-resumer bind claude:<session-id> --pane %42 --json
agent-resumer install-shims --force --auto-tmux
agent-resumer service status

Useful flags:

  • --headless skips tmux pane resume and explicitly uses the headless path.
  • --pane-prompt <text> changes the text sent to interactive panes; default: continue.
  • --prompt <text> changes the headless resume prompt.
  • --quiet suppresses routine no-op loop logs.
  • --json prints machine-readable output.

Pane binding model

agent-resumer stores pane metadata in ~/.agent-resumer/state.json:

{
  "panes": {
    "%42": {
      "engine": "claude",
      "cwd": "/project",
      "source": "shim"
    }
  },
  "sessions": {
    "claude:abc": {
      "engine": "claude",
      "sessionId": "abc",
      "cwd": "/project",
      "pane": "%42",
      "paneSource": "shim"
    }
  }
}

Binding confidence, from strongest to weakest:

  1. tmux-title-session — multiple same-cwd panes can be disambiguated by matching the tmux pane title against recent transcript/user-task text.
  2. tmux-capture — watcher found a same-cwd pane whose captured screen content looks like the target agent TUI (Claude/Codex/OMX/OpenCode). This can repair a stale or wrong manual binding and reports correctedFrom.
  3. shim — command started through the installed shim while $TMUX_PANE was set.
  4. manual — you explicitly ran agent-resumer bind <session> --pane <pane>; capture evidence can still override it if it clearly points to a different same-cwd agent pane.
  5. tmux-passive — watcher found exactly one matching tmux pane by engine command and cwd.
  6. tmux-title — watcher found exactly one wrapped agent pane where cwd matches and pane_title exactly equals the cwd basename (for tmux/purplemux panes whose current command appears as node or a version string).
  7. headless fallback — no safe pane was known.

If passive detection finds multiple equal-confidence candidate panes, agent-resumer does not guess. It reports an ambiguous pane action and, for same-cwd ambiguity, skips headless fallback by default so a detached resume does not leave the visible pane unchanged. For already-running pre-shim sessions, watch captures only same-cwd candidate panes, caches captures for the tick, and prefers panes whose visible content matches the target agent.

Pane sends use a handshake: agent-resumer pastes the prompt, verifies that capture-pane can see it, then presses Enter. If the pane does not echo the input, the action fails as pane_input_not_visible rather than reporting a false launch.

How it works

observe local state → map tmux pane → classify limit → schedule reset → send continue to pane → fallback headless → verify recovery
  1. Observe — scans active Claude/Codex JSONL transcripts and OpenCode SQLite rows.
  2. Map pane — uses shim registrations, manual binds, or safe passive tmux detection.
  3. Classify — detects structured usage-limit/rate-limit signals.
  4. Schedule — stores resumeAt using provider reset time plus buffer or fallback backoff.
  5. Resume — sends continue to the original tmux pane first; if unavailable, launches the headless resume command.
  6. Verify — marks resume_sent after a pane/headless launch and only marks running/recovered after later transcript activity proves recovery.

Claude statusLine reset timestamps

Claude Code statusLine JSON can expose machine-readable subscription windows:

  • rate_limits.five_hour.resets_at
  • rate_limits.seven_day.resets_at

Configure Claude Code to call:

{"statusLine":{"type":"command","command":"agent-resumer statusline --quiet"}}

When a later Claude transcript says a limit was hit but omits a reset time, agent-resumer can use the saved statusLine reset timestamp. Monthly spend caps (/usage-credits) are kept separate because they are user-configured billing limits and may not expose a reliable reset timestamp.

Monthly spend caps

Claude monthly spend-cap messages such as:

You've hit your monthly spend limit.
/usage-credits to adjust your monthly spend limit.

are probeable but not exactly schedulable unless Claude exposes a reset time or the user changes the cap. agent-resumer keeps them in a retryable state and will try the same-pane resume path when due, but it will not claim recovery until transcript activity proves the session resumed.

Service

agent-resumer service install
agent-resumer service start
agent-resumer service stop
agent-resumer service status
agent-resumer service uninstall
  • macOS: user launchd service com.voidmatcha.agent-resumer
  • Linux/WSL2: user systemd timer agent-resumer.timer

State and logs

  • State: ~/.agent-resumer/state.json
  • Detached resume logs: ~/.agent-resumer/resume-logs/
  • Config: ~/.agent-resumer/config.json

Existing tmux / purplemux panes

install-shims is still the most reliable path because it records the exact $TMUX_PANE when claude, codex, or opencode starts. watch also has a recovery path for sessions that were already running before the shim was installed: it lists live tmux panes, maps each pane cwd to Claude's ~/.claude/projects/<encoded-cwd>/ transcripts, scans matching transcript tails for limit signals, and then uses transcript title / last-prompt hints to choose the correct pane.

Useful checks:

agent-resumer watch --once --json
agent-resumer diag <claude-session-uuid> --json
agent-resumer diagnose --json   # summarize every tracked session when you do not know the id

If several panes share the same cwd and no transcript title or prompt hint identifies the right pane, agent-resumer stays conservative instead of guessing. In that case, bind once with agent-resumer bind claude:<uuid> --pane %12 or restart the agent through the shim.

tmux can recycle pane ids after panes are closed. If a previously bound pane was reused for a different agent, run agent-resumer diag <uuid> --json and re-bind to the currently visible pane before relying on the watcher.

Safety notes

  • agent-resumer only sends the configured pane prompt, default continue, after the scheduler says the session is due.
  • It avoids passive pane guesses when multiple panes match, and in multi-pane same-cwd workspaces it only sends to tmux when the pane has strong session/title evidence or a single exact engine command match.
  • It does not bypass provider limits or modify provider accounts.
  • Use --headless if you explicitly want background/headless behavior for a command.

License

Apache-2.0