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

@marcfargas/pi-heartbeat

v0.0.1

Published

Non-blocking timers and heartbeats for pi agents — stop using sleep

Readme

@marcfargas/pi-heartbeat

Non-blocking timers and heartbeats for pi agents.

pi-heartbeat replaces blocking sleep waits with timers that return immediately, so the agent can pause work without freezing the session.

What is pi?

Pi is an AI coding agent CLI (@mariozechner/pi-coding-agent).

You run AI models in an interactive terminal, and the agent executes tools/commands while you chat with it. In that environment, bash calls like sleep 60 block the active turn and prevent interaction until the command finishes.

This extension gives the agent non-blocking waiting primitives (timer, heartbeat) so it can schedule follow-ups and return to idle immediately.

Why this extension?

Without this extension, waits are usually implemented with shell sleep, polling loops, or long-running turns. That causes:

  • blocked chat while waiting
  • poor UX for long builds/deploys
  • brittle polling logic in bash

With pi-heartbeat:

  • waits are non-blocking
  • timers can be canceled
  • follow-up messages include explicit context about what to check next

Install

pi install npm:@marcfargas/pi-heartbeat

Or add to your settings.json:

{
  "packages": ["npm:@marcfargas/pi-heartbeat"]
}

Prerequisites

  • pi installed and working
  • A pi session where the agent can call tools
  • Extension installed via pi install or settings.json

Tools

timer

One-shot wake-up after N seconds.

timer(seconds: 60, message: "Check if build #42 finished — run gh run view 42")
timer(seconds: 120, message: "Retry deploy check", id: "deploy-check-2")
  • returns immediately (non-blocking)
  • wakes the agent once when the timer expires
  • supports multiple simultaneous timers
  • optional id for named cancellation

heartbeat

Periodic wake-up every N seconds until stopped.

heartbeat(action: "start", interval_seconds: 30, message: "Check deploy status")
heartbeat(action: "status")
heartbeat(action: "stop")
  • wakes the agent repeatedly with the provided message
  • only one heartbeat can be active at a time
  • starting a new heartbeat replaces the previous one

/cancel-timer

Manual timer/heartbeat control from chat.

/cancel-timer            # list active timers
/cancel-timer <id>       # cancel specific timer
/cancel-timer heartbeat  # stop heartbeat
/cancel-timer all        # cancel all timers + heartbeat

Use this when you need immediate control without waiting for the next trigger.

When to Use

| Scenario | Before (blocks) | After (non-blocking) | |----------|------------------|----------------------| | Wait for build | sleep 60 && gh run view 42 | timer(60, 'Check build #42') | | Monitor deploy | while true; do sleep 30; check; done | heartbeat(start, 30, 'Check deploy') | | Rate-limited API | sleep 10 between calls | timer(10, 'Resume API calls') |

How It Works

User: "Start the build and let me know when it's done"

Agent: calls timer(seconds: 60, message: "Check build status")
       -> tool returns immediately
       -> agent tells user "I'll check in 60s"
       -> session stays interactive

[60 seconds later]

Timer fires -> pi triggers a new agent turn
-> agent wakes with the timer message in context
-> agent runs the follow-up check
-> if needed, schedules another timer/heartbeat

vs. sleep

| | sleep 60 | timer(60) | |---|---|---| | Chat blocked? | ✅ Yes | ❌ No | | User can interact? | ❌ No | ✅ Yes | | Cancellable? | Kill process | /cancel-timer | | Multiple waits? | Sequential | Concurrent | | Wake-up context? | Shell state only | Explicit message/context |

Limits

  • timer
    • range: 1–3600 seconds
    • supports multiple simultaneous timers
    • optional named id for cancellation
  • heartbeat
    • interval: 10–3600 seconds
    • only one active heartbeat at a time

Sleep Interceptor

This package also intercepts sleep in bash and blocks it only when sleep is the only or last command in a call.

  • sleep 60blocked (only command)
  • npm run build && sleep 60blocked (sleep is last)
  • sleep 5 && npm startallowed (sleep is a startup delay before real work)

Disable interception with:

PI_SLEEP_INTERCEPTOR=0

Best Practices

  • Put actionable context in timer messages (what to check, what command to run)
  • Choose reasonable intervals (don’t poll every 10s for long operations)
  • Stop heartbeats when done (they continue until explicitly stopped)
  • Use chained timers for progressive backoff: 30s -> 60s -> 120s

Development

npm test           # vitest run
npm run typecheck  # tsc --noEmit
npm run lint       # eslint

License

MIT