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

@staywire/cli

v0.1.0

Published

sw — command-line client for the Staywire booking API: bookings, rooms, availability blocks, guests, day sheet, revenue stats and property config.

Downloads

21

Readme

sw — the Staywire CLI

A complete terminal client for the Staywire v1 API: bookings, rooms, blocks, guests, the day sheet, revenue stats, property config, API keys, webhooks, logs and the WRP parity registers.

It exists so that operators and agents drive Staywire through one audited, self-documenting surface instead of hand-rolled curl invocations — which is how Authorization headers end up in shell history and how a PATCH lands on the wrong booking.

Install

From npm (recommended)

npm install -g @staywire/cli
sw --help

That puts sw on your $PATH. The package has zero runtime dependencies — it is a single compiled bundle against Node's built-ins and global fetch — so the install is instant and pulls nothing transitive. Requires Node >= 22.

Per-project instead of global:

npm install --save-dev @staywire/cli
npx sw bookings list

Or run it without installing at all:

npx -y @staywire/cli bookings list

From this repo (contributors)

pnpm --filter @staywire/cli sw bookings list     # tsx, straight from source

To get a sw binary on $PATH from a working copy:

pnpm --filter @staywire/cli build
cd apps/cli && npm link

⚠️ A linked sw points at dist/, which is gitignored. A fresh clone has no dist/ — build before linking. And the linked binary does not pick up source edits until you rebuild, so use pnpm --filter @staywire/cli sw <args> while developing or you will be running yesterday's CLI.

On SBTM01 the link lives under the nvm v24 prefix (~/.nvm/versions/node/v24.14.1/bin/sw), which is on the default PATH.

Quick start

sw bookings list
sw day-sheet
sw stats revenue --granularity week
sw help bookings

Configuration

| What | Flag | Env | Fallback | |---|---|---|---| | API key | --key <key> | STAYWIRE_API_KEY | macOS keychain -a sbtm01 -s sblabs-v2-STAYWIRE_MIRROR_API_KEY | | API base | --base <url> | STAYWIRE_API_URL | https://staywire-api.vercel.app |

The keychain fallback is the SB Labs host convention. It is best-effort and silent when unavailable, so the CLI behaves identically on a machine that only exports the env var. To seed it:

security add-generic-password -a sbtm01 -s sblabs-v2-STAYWIRE_MIRROR_API_KEY -w '<key>'

Safety model

This CLI points at production guest data by default, and it is routinely driven by agents. Three rules follow from that:

  1. Reads run freely. list, get, show, revenue, payments need nothing.
  2. Writes refuse without --yes. Any command that mutates exits 3 with a message unless you pass --yes. There is deliberately no interactive prompt fallback — a prompt that a non-TTY caller auto-answers is worse than no prompt at all.
  3. --dry-run previews any write. It prints the exact method, URL and body that would be sent, then exits 0 without touching the API.
# refuses — exit 3
sw bookings patch <id> --check-out 2026-08-29

# shows the request, sends nothing — exit 0
sw bookings patch <id> --check-out 2026-08-29 --dry-run

# actually writes
sw bookings patch <id> --check-out 2026-08-29 --yes

Exit codes

| Code | Meaning | |---|---| | 0 | success (including --dry-run) | | 1 | API error, or a bad argument | | 2 | unknown group or verb | | 3 | write refused — --yes not given |

Global flags

| Flag | Short | Effect | |---|---|---| | --json | -j | emit the raw API payload instead of a table — pipe into jq | | --yes | -y | authorise a write | | --dry-run | -n | print the request a write would send, then exit | | --verbose | -v | trace each HTTP call to stderr | | --help | -h | help for the command's group |

Flags accept --flag value or --flag=value. Short booleans bundle (-jy). -- stops flag parsing, so values that look like flags survive.

Clearing a nullable field

Fields the API models as nullable (door_code, check_in_time, check_out_time, notes, special_requests, phone) take the literal string null to clear them. Omitting the flag leaves the field untouched — the two are not the same thing:

sw bookings patch <id> --door-code 4821 --yes   # set
sw bookings patch <id> --door-code null --yes   # clear, back to property default
sw bookings patch <id> --check-in-time 13:00 --yes   # leaves door_code alone

Commands

Run sw help <group> for per-verb flags. Groups:

| Group | Verbs | |---|---| | bookings | list get patch cancel no-show resend payments refund | | rooms | list get create patch delete | | blocks | list create patch delete | | guests | list get | | day-sheet | show (bare sw day-sheet works) | | stats | revenue | | settings | get patch | | policies | show | | notifications | get patch test | | keys | list create revoke | | webhooks | list create delete | | logs | requests events emails | | parity | show |

Worked examples

# Today's arrivals and departures
sw day-sheet

# A specific date, as JSON
sw day-sheet --date 2026-08-27 --json

# Bookings in a window
sw bookings list --from 2026-08-01 --to 2026-09-01

# One booking in full
sw bookings get c8f67671-db39-4ccf-bebb-aeca566a9415

# Extend a stay by a night, previewing first
sw bookings patch <id> --check-out 2026-08-29 --dry-run
sw bookings patch <id> --check-out 2026-08-29 --yes

# Per-stay times and access code in one call
sw bookings patch <id> --check-in-time 13:00 --door-code 4821 --yes

# Weekly revenue, occupancy and ADR
sw stats revenue --granularity week --from 2026-07-01 --to 2026-09-01

# Block a room for maintenance
sw blocks create --room-id <uuid> --start 2026-09-01 --end 2026-09-05 \
  --reason "deep clean" --yes

# Pipe into jq
sw bookings list --json | jq '.bookings[] | select(.door_code == null) | .reference'

Interaction with the WRP bridge

Staywire mirrors WebRezPro, and staywire-wrp-shadow pushes SW-side edits back to WRP. A sw bookings patch that changes dates is therefore not local — the bridge's detector picks it up within one poll cycle (~5 min) and composes a push_reservation_v2 modify against WRP. Consequences worth knowing:

  • Date changes on a mapped booking propagate to WRP. Room moves are refused by the bridge composer (no room-number→type mapping yet) and stay SW-only.
  • The bridge audits every push to data/wrp-writeback.jsonl in the shadow repo, including dry runs. That file is the record of what actually reached WRP.
  • sw parity show reads the parity registers — the surface of known SW↔WRP gaps.

sw --dry-run only gates the Staywire call. It has no effect on the bridge, because the bridge reacts to committed SW state, not to your terminal.

Development

pnpm --filter @staywire/cli sw <args>   # run from source via tsx
pnpm --filter @staywire/cli typecheck
pnpm --filter @staywire/cli test
pnpm --filter @staywire/cli build

Commands live in src/commands.ts as a flat registry. Help text is generated from that registry, so adding a verb updates sw help automatically — there is no second place to edit. src/commands.test.ts asserts the invariant that keeps the safety model honest: every write verb sets mutates: true.