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

@gravity-rail/cli

v0.21.0

Published

Gravity Rail CLI — manage workspaces from the command line

Readme

@gravity-rail/cli

Command-line interface for Gravity Rail — manage workspaces, AI assistants, conversations, workflows, and 40+ resource types from your terminal.

gr workflows list -w $WORKSPACE
gr chats list -w $WORKSPACE -o json | jq '.[].summary'
gr members create -w $WORKSPACE --data '{"first_name":"Jane","email":"[email protected]"}' --allow-write

Installation

npm install -g @gravity-rail/cli
# or one-shot
npx @gravity-rail/cli --help

Requires Node.js 18+.

The published gr binary is a single self-contained file. Runtime dependencies only list packages that exist on the public npm registry (@gravity-rail/sdk). Build-only monorepo packages such as @gravity-rail/sandbox (used when compiling code-interpreter bundles) stay in devDependencies so npx / npm install -g do not try to fetch them.

Authentication

OAuth (interactive)

gr login                    # opens browser for OAuth authorization
gr whoami                   # verify your identity
gr logout                   # clear cached credentials

gr login runs authorization code + PKCE (S256) against Gravity Rail's pinned first-party OAuth client, discovered from the server's /.well-known/oauth-authorization-server document. That client is public: it has no client secret, because a CLI distributed to end users cannot keep one (RFC 8252 §8.5). PKCE, not a shared secret, is what protects the exchange.

A self-hosted server old enough not to advertise a first-party client falls back to RFC 7591 dynamic client registration, which does issue this installation its own confidential client. Both kinds of profile refresh normally; nothing needs to be re-authorized when a server gains the pinned client, though the next gr login on that profile will switch to it.

Multi-account profiles

Like aws --profile / gh auth switch, the public CLI supports multiple named accounts:

gr auth login --name work       # OAuth into a named profile (also sets it current)
gr auth login --name personal
gr auth list                    # list profiles for the current --env
gr auth switch --name personal  # change the default profile
gr auth logout --name work      # clear one profile

# Per-invocation selection (does not change the stored default)
gr whoami --profile work
gr tasks list -w $WORKSPACE --profile personal
export GRAVITY_RAIL_PROFILE=work

gr login / gr logout remain as shortcuts for the active profile (or --name).

Local monorepo / QA (Gravity Rail developers): after provisioning, import dev tokens into the same profile store (this replaces the old --realm flag):

yarn gr auth import-dev                 # or: python scripts/sync_gr_cli_profiles.py
yarn gr whoami --profile superadmin
yarn gr tasks list --profile acme-demo/acme-admin   # auto-sets -w

Workspace/member names use one slash (workspace/member). Provisioning auto-syncs profiles; re-run import after re-seed. Worktree API ports get isolated credential files.

Credential store (security)

| Item | Detail | | --------------- | ------------------------------------------------------------------------------------------- | | Location | ~/.gr-cli/credentials-<env>.json (e.g. credentials-prod.json) | | Directory mode | 0700 on ~/.gr-cli | | File mode | 0600 on credential files | | Contents | OAuth client id (+ secret only for a dynamically registered client) + tokens, and/or token-only dev profiles (+ optional workspace UUID) | | Not stored | GRAVITY_RAIL_API_KEY (process environment only; always overrides profiles) | | Name validation | Profiles allow name or workspace/member; env names are allowlisted | | Logging | CLI code never writes token or secret values to stdout/stderr |

Security review notes: tokens never leave the local filesystem except on HTTPS calls to the Gravity Rail API. There is no cloud sync of CLI credentials. Rotate by gr auth logout --name <profile> (or deleting the store file) and logging in again. Multi-user machines should rely on OS home-directory isolation plus the 0600/0700 modes. Do not commit ~/.gr-cli into repositories or bake it into container images.

Profile resolution order for a command:

  1. GRAVITY_RAIL_API_KEY (if set — skips the store entirely)
  2. --profile <name> (or --account)
  3. GRAVITY_RAIL_PROFILE
  4. currentProfile in the credential store (from gr auth switch / last login)
  5. Profile name default

API Key (non-interactive)

export GRAVITY_RAIL_API_KEY=your-api-key
gr tasks list -w $WORKSPACE

Useful for scripts, CI/CD, and automation. Create scoped keys from workspace settings or via @gravity-rail/sdk. API keys are not written into the profile store.

Organizations that require SSO

Workspaces in an SSO-enforced organization need an org-scoped session in addition to your account login. When you run a gr command against such a workspace after gr login, the CLI opens your browser once to complete the organization's SSO, captures the resulting session over a local 127.0.0.1 callback, and caches it under your profile — subsequent commands reuse it silently until it expires. No token is ever placed in a URL.

For non-interactive use (CI, scripts, code-interpreter sandboxes, or any machine with no browser), org SSO cannot run; use an API key instead — API keys are exempt from the org SSO gate:

export GRAVITY_RAIL_API_KEY=your-api-key   # set GRAVITY_RAIL_NO_BROWSER=1 to force the API-key hint

Command Pattern

gr <domain> <action> [options]
gr <domain> <sub-resource> <action> [options]
gr tasks list -w $WORKSPACE                            # list tasks
gr tasks get -w $WORKSPACE --id 42                     # get specific task
gr tasks create -w $WORKSPACE --data '{"name":"New"}' --allow-write  # create
gr chats labels list -w $WORKSPACE                     # sub-resource

Every domain supports --help:

gr --help               # all domains
gr tasks --help         # task commands
gr chats labels --help  # sub-resource commands

Write Safety

The CLI is read-only by default. Any command that creates, updates, or deletes data requires the --allow-write flag:

# Reads — no flag needed
gr members list -w $WORKSPACE
gr workflows get -w $WORKSPACE --id 5

# Writes — must opt in
gr members create -w $WORKSPACE --data '{"first_name":"Test"}' --allow-write
gr tasks delete -w $WORKSPACE --id 42 --allow-write

This prevents accidental mutations when exploring production data or running under automation.

Output Formats

Output adapts to context: human-readable tables in interactive terminals, JSON when piped.

# Table (default in TTY)
gr tasks list -w $WORKSPACE

# JSON (default when piped, or explicit)
gr tasks list -w $WORKSPACE -o json

# JSONL (one object per line — great for streaming)
gr tasks list -w $WORKSPACE -o jsonl

# Pipe to jq
gr members list -w $WORKSPACE -o json | jq '.[].email'

--jq — filter without a pipe

--jq runs the filter against the JSON the CLI just produced, so the input is valid by construction and there is no pipeline to get wrong. It implies -o json.

gr tasks list -w $WORKSPACE --jq 'length'
gr workflows get -w $WORKSPACE --id 3 --jq '{id, name}'

Prefer it over | jq in scripts and agent tooling: a mistake in the filter is reported as a filter error, rather than surfacing as a parse error about output you cannot see. It needs the jq binary on PATH.

Chain commands

gr chats list -w $WORKSPACE -o json | jq '.[0].id' | xargs -I{} gr chats get -w $WORKSPACE --id {}


## Data Input

Pass data for create/update operations via inline JSON, file, or stdin:

```sh
# Inline JSON
gr tasks create -w $WORKSPACE --data '{"name":"My Task"}' --allow-write

# From file
gr workflows create -w $WORKSPACE --file workflow.json --allow-write

# From stdin (pipe)
echo '{"name":"Piped Task"}' | gr tasks create -w $WORKSPACE --allow-write
cat member.json | gr members update -w $WORKSPACE --id 42 --allow-write

Global Options

| Flag | Description | | --------------------------- | -------------------------------------------- | | --api-url <url> | Override API base URL | | --profile <name> | Named account profile (alias: --account) | | -w, --workspace <uuid> | Workspace UUID (required for most commands) | | -o, --output-format <fmt> | Output format: json, jsonl, table | | -v, --verbose | Verbose output to stderr | | --allow-write | Required for create/update/delete operations | | --id <id> | Entity ID (for get/update/delete) | | -d, --data <json> | Inline JSON payload | | -f, --file <path> | Read JSON payload from file | | --help | Show help | | --version | Show version |

Environment Variables

| Variable | Description | | --------------------------- | -------------------------------------------------------------- | | GRAVITY_RAIL_API_KEY | API key for non-interactive authentication | | GRAVITY_RAIL_PROFILE | Default named credential profile | | GRAVITY_RAIL_API_URL | Override API base URL (default: https://api.gravityrail.com) | | GRAVITY_RAIL_FRONTEND_URL | Override frontend URL (default: https://app.gravityrail.com) |

Exit Codes

| Code | Meaning | | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 0 | Success | | 1 | General error | | 2 | Authentication required (run gr login or set GRAVITY_RAIL_API_KEY) | | 3 | A human-in-the-loop (HITL) interrupt requires out-of-band action before the operation can continue | | 4 | No assistant reply — a --message turn made tool calls but returned no final summary, or an inference error occurred with no final message (side effects may have been applied) |

UI choices (present_choice_list / render_ui) are handled in the terminal when stdin is a TTY: the CLI parses OpenUI markup into an arrow-key picker (ChoiceButtons) or field-by-field form prompts, then resumes the chat with your selection. Manager (gr manage) and Concierge (gr concierge chat) share this path. When stdin is not a TTY, those interrupts resume with an empty value (the agent handles the missing response). Unsupported HITL types still exit 3 with the JSON contract below.

When a concierge command run with --message (non-interactive mode) hits a HITL interrupt the CLI cannot resolve on its own, it exits 3 and writes a single machine-readable JSON object to stdout:

{
   "error": "hitl_interrupt",
   "message": "A human-in-the-loop interrupt requires out-of-band action before the operation can continue.",
   "resume": { "chatId": 42, "chatUuid": "…", "interruptId": "int-abc" },
   "interrupt": { "type": "stripe_checkout", "interrupt_id": "int-abc", "url": "…" }
}

The interrupt object is intentionally limited to routing fields (type, interrupt_id, and a redirect url when present); the raw server payload is not forwarded, as it may contain sensitive data. Use resume.chatUuid / resume.interruptId to continue the flow out-of-band (e.g. in the web app).

Commands

Core

| Domain | Description | | ------------- | -------------------------------------------------------------------------- | | tasks | Workflow tasks — CRUD, archive, clone | | chats | Conversations — CRUD, labels, filters, messages, export, summaries | | members | Contacts and team — CRUD, labels, filters, roles, fields, import/export | | workspaces | Workspace management — CRUD, features, themes, invitations, export/import | | workflows | Conversational workflows — CRUD, notes, contributors, templates, analytics | | agents | Autonomous AI members — CRUD, archive | | assistants | AI personas — CRUD with model and voice configuration | | assignments | Task-based conversations — CRUD, messages, tools |

Data & Content

| Domain | Description | | ---------------- | ----------------------------------------------------------------------- | | data-types | Schema-driven forms and records — CRUD, field indexing, computed fields | | files | Documents and folders — CRUD, sharing, semantic search, labels | | sites | Customer portals — CRUD, pages, menus, web crawling | | events | Automation rules — triggers, CEL conditions, delayed actions, webhooks | | calendars | Scheduling — calendars, events, event types, availability, Google sync | | qualifications | Skills evaluation — requirements, submissions, scoring | | queries | Unified Query Engine — fields, validate, preview, run, syntax reference |

Global (no workspace)

| Domain | Description | | ---------------------- | --------------------------------------------------------------- | | concierge | Global Concierge — interactive chat, PSTN --call, SMS --sms | | account verify-phone | Verify your account phone (required before concierge outbound) |

Communication

| Domain | Description | | -------------------- | ------------------------------------------------------------------------- | | phone-numbers | Voice and SMS phone numbers — provisioning, calls, messages | | recordings | Call recordings — list chunks, get a presigned download URL, save the WAV | | inboxes | Email inboxes — threads, attachments, routing | | operator-groups | Live operator routing — groups, presence, strategies | | notification-rules | Alert configuration — event-based notifications |

Integrations

| Domain | Description | | ------------------ | -------------------------------------------------------------------------------------------------- | | discord-bots | Discord bot management — slash commands, threads, account linking | | slack-apps | Slack app management — installations, threads, accounts | | fhir-connections | FHIR healthcare connections — patients, practitioners, encounters | | patientsync | PatientSync PSTN-transfer connection — configure / status / delete (singleton per workspace) | | documo-fax | Documo (mFax) inbound fax — install / configure / setup / verify / status / faxes | | app-connections | Platform app integrations | | monday | Monday.com — boards, columns, webhooks |

Platform

| Domain | Description | | ----------------- | --------------------------------------------------------------- | | api-keys | API key management — workspace and global scopes | | subscriptions | Subscription management | | reports | Usage reports — AI tokens, voice minutes, SMS, storage | | ai-models | Available AI models (no workspace required) | | features | Feature registry (no workspace required) | | custom-toolkits | Custom tool definitions | | mcp-servers | MCP server connections | | milestones | Goal tracking | | supervisors | AI supervisor management | | access-grants | Temporary access delegation | | pronunciations | Voice pronunciation overrides | | apps | OAuth app management | | oauth | OAuth provider connections | | auth | Two-factor authentication, credentials, and password management | | org | Organization membership, invitations, and org domains |

Recipes

Export all chats as JSON

gr chats list -w $WORKSPACE -o json > chats.json

List chat messages with pagination

# Default returns up to 100 messages (API max)
gr chats messages list -w $WORKSPACE --id $CHAT_ID

# Paginate with --limit and --offset
gr chats messages list -w $WORKSPACE --id $CHAT_ID --limit 50 --offset 100

Filter chats by type

# Only manager (operator-side) chats, sorted most-recent-first.
gr chats list -w $WORKSPACE --chat-type manager

Assign and link a phone number to a workspace

# Assign a phone number from the org pool to a workspace…
gr org phone-numbers assign --org-uuid $ORG_UUID --phone-number-id $PN_ID --workspace-uuid $WORKSPACE --allow-write

# …then enable it (link inboxes, voice config) so it can place/receive calls.
gr phone-numbers link -w $WORKSPACE --id $PN_ID --allow-write

Manage pronunciations from the workspace context

# `pronunciations` resolves the org from -w; you don't need --org-uuid.
gr pronunciations list -w $WORKSPACE
gr pronunciations create -w $WORKSPACE --term "GravityRail" --respelling "GRA-vit-ee rail" --allow-write

Download a call recording

# Get a single short-lived presigned URL for the whole call (assembled once, cached).
gr recordings download-url -w $WORKSPACE --chat-id 42

# Or download the assembled WAV straight to a file.
gr recordings download -w $WORKSPACE --chat-id 42 -o call.wav

Register and verify an org domain

# Register the domain and get the ownership TXT record
gr org domains register --org-uuid $ORG_UUID --domain example.com --allow-write

# Verify ownership TXT
gr org domains verify-ownership --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write

# Email DNS: enable records, then verify SPF/DKIM/DMARC/MX/return-path
gr org domains email enable --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write
gr org domains email verify-mx --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write

# Site DNS: enable custom site routing, then verify CNAME
gr org domains site enable --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write
gr org domains site verify-cname --org-uuid $ORG_UUID --domain-uuid $DOMAIN_UUID --allow-write

Find members by label

gr members list -w $WORKSPACE -o json | jq '[.[] | select(.labels[]?.name == "VIP")]'

Bulk create from a file

# members.jsonl — one JSON object per line
cat members.jsonl | while read line; do
  echo "$line" | gr members create -w $WORKSPACE --allow-write
done

Pipe workspace config between environments

gr workspaces get -w $SOURCE_WORKSPACE -o json | \
  gr workspaces create --data "$(cat -)" --allow-write

List all workflows with their task counts

gr workflows list -w $WORKSPACE -o json | jq '.[] | {name, task_count: (.tasks | length)}'

Check who's live as an operator

gr operator-groups list -w $WORKSPACE -o json | jq '.[].name'

Concierge setup over your phone (PSTN / SMS)

Outbound concierge modes ring or text your verified account phone only — no destination argument. Verify once, then initiate:

# One-time: OTP SMS + TCPA notice (writes Account.phone + phone_verified_at)
gr account verify-phone --allow-write
# Optional: pass E.164 inline instead of the prompt
gr account verify-phone --phone +15551234567 --allow-write

# Server originates call; CLI exits when Twilio returns callSid
gr concierge chat --call --allow-write

# Server sends opening SMS; CLI exits when messageSid is returned
gr concierge chat --sms --allow-write

--call and --sms are mutually exclusive. They cannot be combined with --voice or --realtime on the same gr concierge chat invocation. (gr concierge --call / --sms are equivalent shorthand.)

If the API returns 412 account_phone_unverified, run gr account verify-phone first.

Related

License

MIT