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

@kud/ding-cli

v1.0.2

Published

A tiny macOS alarm/timer CLI — set a relative or absolute time, get a notification and a sound when it fires

Readme

TypeScript Node.js npm MIT

A tiny macOS alarm/timer CLI — set a relative or absolute time, get a notification and a sound when it fires

FeaturesQuick StartCLI ReferenceDevelopment

Originally built to remember when Claude's usage quota resets — ding 5h "quota is back" and forget about it.


🌟 Features

  • Relative and absolute times5h, 90m, 1h30m, 30s, 14:30, 2:30pm, 9am; absolute times already past today roll to tomorrow
  • 🔔 Desktop notifications — zero-dependency setup; ships with node-notifier which vendors its own terminal-notifier, no brew install required
  • 🔊 Built-in alarm presets — six synthesised sounds (beep, digital, radar, bell, siren, chime), macOS Clock ringtones (e.g. Radial, Daybreak, Arpeggio), macOS system sounds, or any audio file via afplay
  • 🧙 Interactive wizardding with no arguments launches a tabbed TUI (When · Message · Sound · Notify · Mode · Review); press Space on the Sound step to preview before choosing
  • 🔗 Click-to-open notifications--open https://claude.ai makes the notification banner a shortcut to any URL
  • 🖥 Foreground and detached modes — live countdown with progress bar by default; --detach backgrounds the process and returns the prompt immediately

🚀 Quick Start

Install globally:

npm install -g @kud/ding-cli

Or run without installing:

npx @kud/ding-cli 5h "quota is back"

Set a timer and watch the countdown:

$ ding 90m "tea is ready"
ding → 16:37:22 · tea is ready
01:29:58 ▸ tea is ready

When it fires, the terminal rings (loops the alarm) until you press any key to dismiss, and a desktop notification pops up.


📖 CLI Reference

ding <time> [message] [options]

Time formats

| Format | Example | Meaning | | ------------------- | -------- | ------------------------------------------ | | Relative — hours | 5h | 5 hours from now | | Relative — minutes | 90m | 90 minutes from now | | Relative — seconds | 30s | 30 seconds from now | | Relative — compound | 1h30m | 1 hour 30 minutes from now | | Bare number | 45 | 45 minutes from now | | 24-hour clock | 14:30 | fires at 14:30 today (or tomorrow if past) | | 12-hour clock | 2:30pm | fires at 14:30 | | Hour only | 9am | fires at 09:00 |

Options

| Flag | Alias | Description | | ----------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | --detach | -d | Background the process; prints fire time then returns the prompt | | --sound <value> | -s | Alarm preset (beep digital radar bell siren chime), macOS Clock ringtone name (e.g. Daybreak; quote names with spaces like "Milky Way"), macOS system sound name (e.g. Glass), or path to an audio file. Default: bell | | --no-sound | | Disable alarm sound entirely | | --no-notify | | Disable desktop notification | | --title <text> | | Notification title (default: ding) | | --subtitle <text> | | Notification subtitle | | --icon <path> | | Absolute path to a custom notification icon image | | --open <url> | | URL to open when the notification banner is clicked | | --notify-sound <name> | | Notification banner sound (e.g. Glass, Ping) — distinct from --sound, which plays via afplay | | --icons <mode> | | Icon set: nerd (default, requires Nerd Font), emoji, or ascii. Also set via DING_ICONS env var | | -i / --interactive | | Force-launch the interactive wizard | | --help | -h | Show help | | --version | -V | Show version |

Examples

# Relative timer with a message
ding 90m "tea is ready"

# Absolute time
ding 14:30 "stand-up"

# Fires at 9 am — rolls to tomorrow if 9 am has already passed
ding 9am

# Open claude.ai when the notification is clicked
ding 5h "quota is back" --open https://claude.ai --subtitle "Anthropic"

# Background the process, return the prompt immediately
ding 5h "quota is back" --detach

# Silent notification (no alarm sound)
ding 30m "check the oven" --no-sound

# macOS Clock alarm ringtone (played locally via afplay; quote names with spaces)
ding 5h "wake" --sound Daybreak
ding 5h "wake" --sound "Milky Way"

# Notification banner's own macOS sound (separate from the afplay alarm)
ding 30m "stand-up" --notify-sound Glass

# Custom audio file
ding 20m "deploy done" --sound ~/Downloads/alert.aiff

# Use emoji icons (no Nerd Font required)
ding 5m "test" --icons emoji

# Or set permanently in your shell profile
export DING_ICONS=emoji

Recipe: ring when Claude's usage quota resets

ding was born to time Claude's 5-hour usage window — but instead of guessing 5h, read the exact reset time from ccusage, which parses Claude Code's local logs. Pipe its active-block remainingMinutes straight into ding:

mins=$(ccusage blocks --active --json --offline | node -e 'const {blocks=[]}=JSON.parse(require("node:fs").readFileSync(0));const a=blocks.find(b=>b.isActive);process.stdout.write(String(a?.projection?.remainingMinutes??""))')
[ -n "$mins" ] && ding "${mins}m" "Claude quota is back 🎉"

--offline keeps it fast (no network), and remainingMinutes is already relative, so there is no timezone maths to get wrong.

Interactive wizard

Running ding with no time argument (or with -i) launches a tabbed wizard:

ding  When · Message · Sound · Notify · Mode · Review

Navigate between tabs with / . On the Sound step, use / to browse presets, macOS Clock ringtones, and system sounds, and press Space to preview a sound before confirming with .

Icon sets

The countdown display and fired state use glyphs from the active icon set:

| Mode | Activate | Requires | | ------- | ------------------------------------- | -------------------------------------------------------------- | | nerd | default | a Nerd Font-patched terminal font | | emoji | --icons emoji or DING_ICONS=emoji | any modern terminal | | ascii | --icons ascii or DING_ICONS=ascii | nothing |

--icons takes precedence over DING_ICONS. If your font is not Nerd Font-patched, add export DING_ICONS=emoji to your shell profile.

Foreground mode (default)

Without --detach, the terminal renders a live countdown. When the timer fires it rings continuously until you press any key:

$ ding 5m "quota is back"
ding → 16:42:00 · quota is back
04:59:58 ▸ quota is back

Detach mode

$ ding 5h "quota is back" --detach
ding → 21:00:00 (detached)
$

The process runs silently in the background and fires the notification and alarm at the target time — no terminal required.


🔧 Development

ding-cli/
├── src/
│   ├── index.ts          # CLI entry point and argument definitions
│   ├── countdown.ts      # Foreground countdown rendering loop
│   ├── detach.ts         # Background process spawning
│   ├── icons.ts          # Icon sets (nerd / emoji / ascii)
│   ├── notify.ts         # Desktop notification wrapper
│   ├── parse-time.ts     # Relative and absolute time parsing
│   ├── preview-sound.ts  # Sound preview during wizard
│   ├── sounds.ts         # Alarm presets (WAV synthesis) + system sound resolution
│   ├── ui/               # TUI primitives (tabs, footer hints)
│   └── wizard/           # Interactive wizard (Ink/React)
└── dist/                 # Compiled output (tsup → ESM)

Scripts

| Command | Description | | --------------------- | -------------------------------------- | | npm run dev | Run from TypeScript source via tsx | | npm run build | Compile to dist/ with tsup | | npm run build:watch | Watch mode compilation | | npm run typecheck | TypeScript type-check without emitting | | npm run lint | ESLint | | npm run format | Prettier |

Setup

git clone https://github.com/kud/ding-cli.git
cd ding-cli
npm install
npm run dev -- 5s "test alarm"

After npm link, the ding binary resolves to the compiled dist/index.js (run npm run build first).


🏗 Tech Stack

| Package | Role | | ------------------------------------------------------------ | --------------------------------------------------------- | | ink | React renderer for the terminal | | @inkjs/ui | Text input and select components | | citty | CLI argument parsing | | node-notifier | macOS desktop notifications (vendors terminal-notifier) | | chalk | Terminal colour output | | tsup | ESM build | | tsx | TypeScript execution for development |


MIT © kud — Made with ❤️