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

@townspot/cli

v0.1.4

Published

TownSpot operator and agent CLI.

Readme

TownSpot CLI

TownSpot operator and agent CLI package.

Install

For published npm installs:

npm install -g @townspot/cli
townspot

Running townspot with no command opens the human operator home screen (Town Square). On a real terminal it follows with a numbered next-move menu; Enter defaults to the first recommended action. Use townspot help or townspot --json help for the full command reference.

What It Can Do

The CLI is an authenticated operator tool for TownSpot event sourcing and admin work. It is safe to give to a trusted local editor when that editor is a TownSpot admin assigned to specific towns. It is also used by agent tools such as Claude/Codex when they need machine-readable JSON output.

Main workflows:

  • Sign in through the browser and store a refreshable local terminal session.
  • List towns and inspect the towns the signed-in admin can manage.
  • Resolve venues by name, match them to a town polygon, and optionally create the venue.
  • List, add, update, and inspect event sources for assigned towns.
  • Create sourcing runs so a batch of agent writes can be audited together.
  • Preflight duplicates by venue/source before writing events.
  • Create events from structured fields or from a source URL extraction.
  • Update event emoji, categories, times, recurrence, and RDATEs.
  • Soft-delete events with an explicit --confirm <uuid> guard.
  • Read action receipts for accessible runs/events.

It does not bypass server authorization. The CLI sends the browser-login bearer token to TownSpot APIs, and the server decides what the signed-in user can do.

Permissions

TownSpot has two admin roles for CLI purposes:

  • super_admin: global operator. Can perform platform setup and unrestricted admin work.
  • admin: town-scoped operator. Can work only inside towns/zones assigned to that admin account.

Authentication levels:

| Level | Who | What works | | --- | --- | --- | | No login | Anyone | townspot help, public towns list, public venues search, local sources parse-date | | Signed-in non-admin | TownSpot user without admin record | Auth commands only; admin commands fail with 403 | | Town admin | Active admin assigned to one or more towns | Source, venue, sourcing-run, receipt, and event operations inside assigned towns | | Super admin | Active super_admin | All town-admin operations plus country, region, town creation/visibility, global setup, and unrestricted diagnostics |

Town admin boundary:

| Area | Town admin can do | Town admin cannot do | | --- | --- | --- | | Towns | List assigned admin towns with towns admin-list | Create towns, hide/show towns, activate/deactivate towns | | Venues | Search venues; resolve and create venues inside assigned towns | Create or edit venues outside assigned towns; change venue multi-town membership | | Sources | List/add/update sources in assigned towns; view source-linked events | Run unrestricted global URL checks or hard-delete source provenance | | Events | Create/update/delete events in assigned towns; update recurrence; run duplicate preflight for accessible venues | Move events to venues outside assigned towns; edit events in unassigned towns | | Runs/receipts | Create/get/finish sourcing runs for assigned towns; query receipts by accessible run or event | Query global receipts by arbitrary source URL/status/tool unless super admin | | Platform setup | None | Countries, regions, launch-country, town creation, admin management |

Super admin-only commands:

townspot countries upsert ...
townspot regions upsert ...
townspot launch country ...
townspot towns create ...
townspot towns set-active ...
townspot towns set-hidden ...
townspot sources check-url --url <url>

Town admin-safe commands, when scoped to an assigned town/event/venue:

townspot towns admin-list
townspot venues resolve --query <name> --zone-id <id> --create --confirm-production
townspot sources list --zone-id <id>
townspot sources add --url <url> --zone-id <id>
townspot sources update --id <source_id> ...
townspot sources events --id <source_id>
townspot events runs create --label <label> --zone-id <id>
townspot events open-url --url <url> --zone-id <id> --venue-id <venue_id> --run-id <run_id>
townspot events create --title <title> --zone-id <id> --venue-id <venue_id> ...
townspot events set-emoji --event-uuid <uuid> --emoji <emoji>
townspot events set-categories --event-uuid <uuid> --category <category>
townspot events set-times --event-uuid <uuid> --start <local> --end <local> --timezone <iana>
townspot events set-rrule --event-uuid <uuid> --rrule <RRULE> --timezone <iana>
townspot events set-rdates --event-uuid <uuid> --rdate <local> --timezone <iana>
townspot events delete --uuid <uuid> --confirm <same uuid>

Read-only or local commands:

townspot help
townspot auth login
townspot auth import --payload <encoded-session>
townspot auth status
townspot auth token --header
townspot towns list --country-code ES
townspot venues search --query "Venue name" --country-code ES
townspot sources parse-date --text "next Friday 7pm" --default-year 2026

Agent Usage

Use --json whenever Claude, Codex, or another agent is calling the CLI. JSON mode returns parseable success/error payloads and stable action names.

townspot --json auth status
townspot --json towns admin-list --country-code ES
townspot --json events runs create --label "Poblenou weekly source pass" --zone-id 123

The normal sourcing loop for a town admin is:

  1. townspot auth login
  2. If the browser cannot reach the agent-owned localhost callback, run the townspot auth import --payload ... command shown in the browser.
  3. townspot towns admin-list --country-code ES
  4. townspot events runs create --label "Poblenou weekly source pass" --zone-id <zone_id>
  5. townspot sources list --zone-id <zone_id>
  6. townspot venues resolve --query "<venue>" --zone-id <zone_id> --create --confirm-production
  7. townspot events preflight --venue-id <venue_id> --source-url <url>
  8. townspot events open-url --url <url> --zone-id <zone_id> --venue-id <venue_id> --run-id <run_id>
  9. townspot events receipts --run-id <run_id>
  10. townspot events runs finish --run-id <run_id> --status completed --report-json '{"created":3,"skipped":2}'

For production writes, keep --confirm-production on venue creation. For duplicate exceptions, use --allow-possible-duplicate only after checking receipts/preflight output.

Entrypoints

The web repo compatibility entrypoint remains:

npm run townspot -- <command>

The package workspace entrypoint is:

npm --workspace @townspot/cli exec townspot -- <command>

The package-local binary is still useful while developing:

node packages/townspot-cli/bin/townspot.mjs <command>

For local shell testing:

cd packages/townspot-cli
npm link
townspot --json help

Boundary

This package should stay a narrow client over authenticated TownSpot server workflows.

  • Do not write directly to the database.
  • Do not silently fall back to static admin-token routes.
  • Keep event creation, recurrence, venue resolution, provenance, duplicate checks, and quotas server-backed.
  • Keep machine/agent CLI behavior separate from human operator UX.
  • Use --json for agent mode; every command should return parseable success/error payloads.
  • Do not expose destructive source hard-delete from the CLI. Source provenance must be preserved server-side.
  • Country and region setup commands are service-backed wrappers. Use launch country for the first country plus first region, then add hyperlocal towns with towns create or the town editor.
  • Town setup commands are server-backed wrappers. towns create deliberately sends only name, countryCode, and optional polygon data; slug generation, coordinates, activation defaults, permissions, and audit logging belong to the server.

Japan baseline:

townspot launch country \
  --country-code jp \
  --name Japan \
  --currency-code JPY \
  --default-locale ja-JP \
  --timezone Asia/Tokyo \
  --flag 🇯🇵 \
  --region-name Tokyo

Package Checks

Run these from the web repo root before touching release/distribution:

npm run townspot-cli:test
npm run townspot-cli:smoke
npm run townspot-cli:pack

The package-local equivalents are:

cd packages/townspot-cli
npm run test:unit
npm run smoke
npm run pack:check

Package-local npm test is intentionally a dependency-free smoke test so it still works from an installed or packed CLI. Use npm run test:unit in the monorepo for the Jest command suite. townspot-cli:release-check is the real npm release gate. It runs the unit suite, smoke test, pack dry-run, and npm publish dry-run without publishing:

npm run townspot-cli:release-check

The release gate also enforces the package metadata needed for first-class npm publication:

  • publishConfig.access must stay public
  • publishConfig.provenance must stay true

Runtime Config

The CLI reads runtime config in this order:

  • process env
  • repo-root .env.local
  • repo-root .env

Supported environment variables:

  • NEXT_PUBLIC_SITE_URL
  • NEXT_PUBLIC_API_BASE_URL
  • NEXT_PUBLIC_SUPABASE_URL
  • NEXT_PUBLIC_SUPABASE_ANON_KEY
  • NO_COLOR
  • CI

The auth session is stored at:

~/.config/townspot/agent-session.json

That file contains the browser-login handoff session and is refreshed in place with the stored refresh token. The CLI writes it with mode 0600.

Release

First-time local validation:

npm run townspot-cli:release-check

Release path:

  1. Bump packages/townspot-cli/package.json.
  2. Push main.
  3. Create and push a tag that exactly matches the package version. The recommended path is to tag origin/main directly so you release the current remote main tip, for example townspot-cli-v0.1.0.
  4. Let .github/workflows/publish-townspot-cli.yml publish with npm provenance.

Example:

git fetch origin main
git tag townspot-cli-v0.1.0 origin/main
git push origin townspot-cli-v0.1.0

The workflow requires NPM_TOKEN in GitHub Actions secrets. It runs the same workspace publish dry-run as CI, rejects tag/version mismatches, requires the tagged commit to already be contained in origin/main, and then publishes with --access public --provenance. That ancestor check avoids false failures if main advances after the release tag is pushed.

Exit Codes

  • 0: success
  • 1: unknown error
  • 2: validation failure (validation_failed, unknown_command)
  • 3: auth failure (auth_failed)
  • 4: duplicate blocked (duplicate_blocked)
  • 5: quota/rate-limit blocked (quota_blocked)
  • 6: server error (server_error)
  • 7: extraction uncertain (extraction_uncertain)