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

@ipulsehq/pulsecalendar-cli

v0.5.0

Published

Command line interface for PulseCalendar: log in once on your device, read your agenda (events from all your calendars), find free time, create/move/delete events, and manage work tasks.

Readme

@ipulsehq/pulsecalendar-cli

Command line interface for PulseCalendar. Log in once on your device with a browser, then read your agenda, find free time, create/move/delete events and manage work tasks from your terminal (or from tools like Claude Code).

Built for AI assistants: every read command supports --json, accepts relative dates ("today", "tomorrow", "+3d", "tomorrow 09:00"), and the agenda expands recurring events into concrete occurrences so an agent can answer "what's on my calendar?" without understanding RRULEs.

It also respects your PulseCalendar settings: new events land on your default calendar and use your default duration, free uses your configured working hours, weekend visibility and week start. Override any of these with flags.

Install

npm install -g @ipulsehq/pulsecalendar-cli

This installs two equivalent binaries: pulsecalendar and the short alias pulsecal.

Log in

pulsecalendar login

This opens your browser, signs you in through iPulse (OAuth with loopback PKCE, same flow as the PulseEnv CLI), and stores tokens in ~/.pulsecalendar/credentials.json. Only iPulse admin accounts can use the CLI (PulseCalendar is an internal tool), and your account must have signed in to the PulseCalendar web app at least once.

Access tokens are short-lived and refreshed automatically via the stored refresh token; you only need to log in again when the refresh token expires (30 days of inactivity).

To point at a non-production instance:

pulsecalendar login --url http://localhost:3000
# or set it for the whole session:
export PULSECALENDAR_URL=http://localhost:3000
# the OAuth issuer can be overridden too:
export PULSECALENDAR_ISSUER=https://ipulse.one

Read your agenda

pulsecalendar agenda                       # today
pulsecalendar agenda --tomorrow
pulsecalendar agenda --week                # current week (Mon-Sun)
pulsecalendar agenda --month
pulsecalendar agenda --days 7              # next 7 days
pulsecalendar agenda --from 2026-07-01 --to 2026-07-07
pulsecalendar agenda --calendar <id>      # one calendar only
pulsecalendar agenda --week --json        # full details for an AI assistant

Calendars you've turned off (hidden) in PulseCalendar are excluded, just like in the web app. Pass --include-hidden to show them, or --calendar <id> to target one specific calendar regardless of its visibility.

Recurring events are expanded into individual occurrences within the range by default (pass --no-expand to get the raw master events with their RRULE). --json includes every detail: description, location, attendees, status, timezone, colour, the calendar id and name, and recurringEventId/isOccurrence for expanded occurrences.

list events is an alias for agenda.

Agenda options:

| Flag | Description | | --- | --- | | --from <date> | Range start (ISO, or today/tomorrow/+3d) | | --to <date> | Range end (inclusive) | | --days <n> | Number of days from --from or today | | --today / --tomorrow | Single day (today is the default) | | --week / --month | Current week (Mon-Sun) / calendar month | | --calendar <id> | Only events from this calendar id | | --search <text> | Filter by title, description or location | | --include-hidden | Also include calendars you turned off | | --no-expand | Do not expand recurring events | | --json | Output as JSON |

List your calendars

Your personal calendar, location/shared calendars and any connected Google/ iCloud/Microsoft/CalDAV accounts:

pulsecalendar calendars
pulsecalendar calendars --json

Use the printed calendar id with agenda --calendar, free --calendar and create event --calendar.

Create a calendar event

pulsecalendar create event --title "Lunch with client" \
  --start "tomorrow 12:00" --duration 60 --location "Café Central, Amsterdam"

pulsecalendar create event -t "Sprint review" \
  --start 2026-07-01T14:00 --end 2026-07-01T15:00 --calendar <id>

pulsecalendar create event -t "Day off" --start 2026-07-04 --all-day

New timed events that overlap something already on your calendar print a non-blocking warning (turn it off with --no-conflict-check).

| Flag | Description | Default | | --- | --- | --- | | -t, --title | Event title (required) | — | | -s, --start | Start (ISO or relative, required) | — | | -e, --end | End (ISO or relative) | start + duration | | --duration <minutes> | Used when --end is omitted | your settings (60) | | --all-day | All-day event | — | | -l, --location | Location | — | | -d, --description / --description-file | Description (file - = stdin) | — | | --calendar <id> | Target calendar | your default calendar | | --no-conflict-check | Skip the overlap warning | — | | --json | Output the created event as JSON | — |

Your next event

pulsecalendar next                 # next 3 upcoming events
pulsecalendar next --limit 1       # just the next one
pulsecalendar next --days 7 --json

Find free time

Find open slots within working hours, in your local timezone. All-day events (e.g. holidays) count as busy by default. Weekends are skipped unless you ask for them.

pulsecalendar free --tomorrow                       # gaps tomorrow
pulsecalendar free --week --min 60                  # 1h+ slots this week
pulsecalendar free --days 5 --work-start 08:00 --work-end 18:00
pulsecalendar free --week --json                    # for an AI to pick a slot

| Flag | Description | Default | | --- | --- | --- | | range flags | Same as agenda (--today/--week/--days/--from...) | today | | --work-start <HH:mm> / --work-end <HH:mm> | Working hours | your settings (09:00 / 17:00) | | --min <minutes> | Minimum slot length to report | 30 | | --include-weekends | Include Saturday and Sunday | your settings | | --ignore-all-day | Don't treat all-day events as busy | off | | --calendar <id> | Only consider this calendar as busy | all | | --json | Output slots as JSON | — |

Show, reschedule or delete an event

Get the event id from agenda --json (or next --json), then:

pulsecalendar show event <id>                       # full details
pulsecalendar show event <id> --json

pulsecalendar update event --id <id> --start "tomorrow 15:00" --end "tomorrow 16:00"
pulsecalendar update event --id <id> --shift 15     # move 15 min later (-15 = earlier)
pulsecalendar update event --id <id> --title "New title" --location "Room 2"

pulsecalendar delete event --id <id>

For recurring events the change applies to the whole series (the CLI tells you when that's the case).

| update event flag | Description | | --- | --- | | --id <id> | Event id (required) | | -t, --title / -l, --location / -d, --description | Edit fields | | -s, --start / -e, --end | New start/end (ISO or relative) | | --shift <minutes> | Move the whole event by N minutes (+later, -earlier) | | --calendar <id> | Move to another calendar | | --json | Output the updated event as JSON |

Create a task

pulsecalendar create task \
  --title "Agent: collect disk I/O metrics" \
  --product pulseguard \
  --priority medium \
  --type development \
  --category feature_request \
  --description "Add per-disk read/write throughput and IOPS to the agent."

Long descriptions can be read from a file (or stdin with -):

pulsecalendar create task --title "..." --product pulseguard --description-file ./task.md
cat task.md | pulsecalendar create task --title "..." --description-file -

Options:

| Flag | Description | Default | | --- | --- | --- | | -t, --title | Task title (required) | — | | -p, --product | general, pulseguard, pulsefiles, pulseqr, pulsecalendar, pulsesupport, pulsemail, ipulse | pulseguard | | -d, --description | Markdown description | — | | --description-file | Read description from a file (- = stdin) | — | | --priority | high, medium, low | medium | | --status | not_started, in_progress, ready_for_test, done | not_started | | --type | one or more of general, development, marketing | development | | --category | one or more of bug, refinement, feature_request | — | | --relation-number | linked customer relation number | — | | --due | due date (ISO) | — | | --json | print the created task as JSON | — |

List tasks

pulsecalendar list tasks
pulsecalendar list tasks --status in_progress
pulsecalendar list tasks --search agent --include-done
pulsecalendar list tasks --json

Other commands

pulsecalendar whoami    # show the logged-in account
pulsecalendar logout    # remove the stored token

How auth works

The CLI is a public OAuth client (pulsecalendar-cli) on the iPulse identity provider, using authorization code + PKCE with a loopback redirect (same pattern as gh auth login and the PulseEnv CLI):

  1. The CLI starts a one-shot HTTP server on 127.0.0.1:47655.
  2. It opens https://ipulse.one/api/oauth/authorize in your browser with a PKCE challenge.
  3. iPulse signs you in and redirects back to http://127.0.0.1:47655/callback with an authorization code.
  4. The CLI exchanges the code (plus PKCE verifier) for access and refresh tokens and stores them locally.

The PulseCalendar API verifies these RS256 tokens against the iPulse JWKS and maps your iPulse account to your PulseCalendar user by e-mail. New tasks are assigned to you by default, with priority medium, type development, status not_started and the current sprint, so AI agents can create a task with just a --title.

Develop

npm install
npm run dev -- create task --title "test" --product pulseguard   # run from source via tsx
npm run build                                                    # emit dist/