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

@snevins/nudge

v0.2.1

Published

Sequential reminder queue engine

Readme

nudge

nudge is a tiny sequential reminder queue engine. It creates UUID queues, checks them (exit codes for gating), advances them (next), and auto-cleans up completed queues (default: archive).

Install

Requires Node 22.13.0+.

pnpm add -g @snevins/nudge

Quick start (wrapper-style)

ID="$(nudge queue "Run migrations" "Update changelog")"

nudge "$ID"          # exit 1 until complete
nudge next "$ID"
nudge next "$ID"     # completes + archives by default
nudge "$ID"          # now exists:false (and archived:true)

Storage

nudge picks a root directory automatically:

  • inside a git repo: .git/nudge/
  • outside a git repo: ./.nudge/

If a git repo is detected but .git/nudge/ is not writable, nudge falls back to ./.nudge/ at the repo root.

Layout:

NUDGE_ROOT/
  nudge.sqlite

Commands

nudge version

Print the current installed nudge version.

nudge version
nudge --version

nudge queue <reminder...>

Create a new queue (UUID v4 generated).

nudge queue "Run migrations" "Update changelog"
nudge queue --json "Run migrations"
nudge queue -- "-starts-with-dash"

nudge <queueId>

Check a queue.

  • exit 1 when pending reminders exist
  • exit 0 when missing or complete
nudge <queueId>
nudge <queueId> --json

nudge next <queueId>

Acknowledge the next unacked item and advance cursor sequentially.

On completion, cleanup runs automatically (default: archive).

If the queue is already complete but still marked active in the SQLite store (e.g., a crash between final write and cleanup), calling nudge next <queueId> again applies the cleanup policy (unless --cleanup keep).

Archiving is idempotent: once a completed queue is marked archived in the SQLite store, later check / next calls continue returning archived:true.

In human mode (no --json):

  • prints the acked reminder text when an item is acknowledged
  • exits 1 when it advances the queue (an item was acknowledged)
  • exits 0 when missing or already complete (no-op)
  • prints nothing when missing or already complete
nudge next <queueId>
nudge next <queueId> --json
nudge next <queueId> --cleanup archive|delete|keep

nudge clear <queueId>

Delete active queue state (idempotent; does not purge archive).

nudge clear <queueId>
nudge clear <queueId> --json

nudge --all

List active queues.

  • exit 1 when any pending exists
  • exit 0 when none are pending
nudge --all
nudge --all --json

Ordering: --all output is sorted by queueId ascending for stability.

Exit codes (gating API)

  • 0: missing or complete (nudge <queueId>); none pending (nudge --all); next no-op (missing/already complete); success (queue, clear)
  • 1: pending reminders exist (nudge <queueId> / nudge --all); next advanced (acked an item)
  • 2: error (invalid UUID, lock timeout, IO/corrupt state)

JSON output

--json makes stdout stable JSON (no extra stdout text). By default:

  • queue, check, next: full snapshot including items
  • --all: summary only (no items)

All timestamp fields (createdAt, updatedAt, ackAt) are RFC3339 strings (e.g. 2026-03-04T20:00:00.000Z).

Full snapshot schema (queue, check, next)

{
  "queueId": "uuid",
  "createdAt": "2026-03-04T20:00:00.000Z",
  "updatedAt": "2026-03-04T20:00:00.000Z",
  "cursor": 0,
  "done": 0,
  "total": 2,
  "complete": false,
  "next": "Run migrations",
  "items": [
    { "index": 0, "text": "Run migrations", "createdAt": "2026-03-04T20:00:00.000Z", "ackAt": null },
    { "index": 1, "text": "Update changelog", "createdAt": "2026-03-04T20:00:00.000Z", "ackAt": null }
  ]
}

Missing queue (check)

{ "queueId": "uuid", "exists": false, "archived": true }

(archived is only present when a matching archived queue exists in the SQLite store.)

next action envelope

{
  "action": "next",
  "acked": { "index": 0, "text": "Run migrations", "ackAt": "2026-03-04T20:05:00.000Z" },
  "cleanup": { "policy": "archive", "action": "archived" }
}

When present, cleanup means a cleanup action was applied (most commonly on completion).

clear output

{ "queueId": "uuid", "action": "clear", "removed": true }

--all output

{
  "queues": [
    { "queueId": "uuid", "done": 1, "total": 2, "complete": false, "next": "Update changelog", "updatedAt": "2026-03-04T20:06:00.000Z" }
  ],
  "anyPending": true
}

JSON errors

When --json is set and an error occurs (exit code 2), stdout is:

{ "error": { "code": "IO_ERROR", "message": "..." } }

Known error.code values:

  • INVALID_UUID
  • LOCK_TIMEOUT
  • CORRUPT_STATE
  • IO_ERROR
  • USAGE_ERROR
  • INTERNAL_ERROR

Environment

NUDGE_LOCK_TIMEOUT_MS overrides the lock acquisition timeout (default: 5000).

Development

This repo uses pnpm (see pnpm-lock.yaml). The repo requires Node 22.13.0+ and includes .nvmrc for nvm use.

nvm use
pnpm install
pnpm test
pnpm run build

Manual Verification

Build first:

pnpm run build

Verify the default archive flow:

CLI="$PWD/dist/src/index.js"
TMP_DIR="$(mktemp -d)"
mkdir -p "$TMP_DIR/.git"

ID="$(
  cd "$TMP_DIR" &&
  node "$CLI" queue "Run migrations" "Update changelog"
)"
test -f "$TMP_DIR/.git/nudge/nudge.sqlite"

(
  cd "$TMP_DIR" &&
  node "$CLI" "$ID" --json &&
  node "$CLI" next "$ID" --json &&
  node "$CLI" next "$ID" --json &&
  node "$CLI" "$ID" --json
)

Expected:

  • the SQLite file exists at .git/nudge/nudge.sqlite
  • the first check shows complete: false
  • the second next returns cleanup: { "policy": "archive", "action": "archived" }
  • the final check returns { "exists": false, "archived": true }

Verify delete cleanup:

CLI="$PWD/dist/src/index.js"
TMP_DIR="$(mktemp -d)"
mkdir -p "$TMP_DIR/.git"

ID="$(
  cd "$TMP_DIR" &&
  node "$CLI" queue "One"
)"

(
  cd "$TMP_DIR" &&
  node "$CLI" next "$ID" --json --cleanup delete &&
  node "$CLI" "$ID" --json
)

Expected:

  • next returns cleanup: { "policy": "delete", "action": "deleted" }
  • the final check returns { "exists": false } without archived: true

Verify fallback storage outside git:

CLI="$PWD/dist/src/index.js"
TMP_DIR="$(mktemp -d)"

ID="$(
  cd "$TMP_DIR" &&
  node "$CLI" queue "Outside git"
)"
test -f "$TMP_DIR/.nudge/nudge.sqlite"

(
  cd "$TMP_DIR" &&
  node "$CLI" "$ID" --json
)

Git hook (optional)

If you want “block pushes when any pending queue exists in this repo”:

cp hooks/pre-push .git/hooks/pre-push
chmod +x .git/hooks/pre-push