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

@ratio-app-sandbox/cli

v0.1.11

Published

Official Ratio developer CLI

Readme

@ratio-app-sandbox/cli

The official Ratio developer CLI — scaffold, link, run, and develop apps on the Ratio platform.


Install

npm install -g @ratio-app-sandbox/cli

Homebrew:

brew tap imran-primathon/ratio
brew install ratio

Requirements: Node.js >= 18. Works on macOS, Linux, and Windows (WSL recommended for Windows users).


Quickstart

# 1. Sign in
ratio auth login

# 2. Scaffold a new app
ratio app create hello-app --template minimal

# 3. Link it to your Ratio developer account
cd hello-app && ratio app link

# 4. Start local development (runs your dev command + webhook listener)
ratio app dev

What you get with the Ratio CLI

| Command | Status | What it gives you | |---|---|---| | ratio auth login | GA | One-command sign-in to your Ratio developer account — browser PKCE flow, --manual copy-paste fallback for headless machines | | ratio auth logout | GA | Signs out and securely clears stored credentials | | ratio auth whoami | GA | Shows the signed-in identity, scopes, and profile; --json supported | | ratio app create <name> | GA | Scaffolds a fully-wired Ratio app in seconds — three templates: minimal, with-admin-ui, serverless | | ratio app link | GA | Connects your local code to a Ratio app registration — interactive or flag-driven; writes clientId to ratio.config.jsonc | | ratio app dev | GA | One command for local development: runs your dev server and a live webhook listener side by side | | ratio dev listen | GA | Streams real platform webhook events to your localhost server over a WebSocket relay — no tunnels to set up | | ratio dev trigger [topic] | GA | Fires synthetic webhook events (cod, prepaid, cancelled scenarios) so you can test handlers without real orders | | ratio version | GA | Prints the CLI version | | ratio help [command] | GA | Command help | | ratio app deploy | Coming soon | Deploy your app to the Ratio platform (prints guidance in this release) | | ratio app info | Coming soon | Show details of the linked app (prints guidance in this release) | | ratio app generate | Coming soon | Generate code inside your app (prints guidance in this release) |


Per-command examples

ratio auth login

Sign in to Ratio using a browser-based PKCE flow. The browser opens automatically and the CLI waits for the callback.

ratio auth login

Use --manual for headless environments where a browser cannot be opened. The CLI prints a URL; you visit it, copy the authorization code, and paste it back.

ratio auth login --manual

Flags:

| Flag | Description | |---|---| | --manual | Use manual copy-paste flow instead of a browser | | --verbose | Write structured diagnostic lines to stderr | | --profile <name> | Credential profile name to write into (default: default) |

--json is not supported for auth login — the command has no machine-readable output.

RATIO_API_TOKEN bypass: If the environment variable RATIO_API_TOKEN is set to a non-empty value, ratio auth login exits immediately ("Using RATIO_API_TOKEN — no login needed."). This lets CI pipelines skip interactive sign-in. Because the token bypasses the stored credential file, ratio auth whoami cannot report identity while it is set. Store RATIO_API_TOKEN as a CI repository secret and never echo it in logs.


ratio auth logout

Sign out and clear stored credentials.

ratio auth logout

Flags:

| Flag | Description | |---|---| | --verbose | Write structured diagnostic lines to stderr |

--json is intentionally not supported for auth logout — there is no machine-readable output to emit.


ratio auth whoami

Show the currently signed-in Ratio user.

ratio auth whoami

Machine-readable output:

ratio auth whoami --json
# stdout: {"ok":true,"data":{"source":"file","clientId":"...","merchantId":"...","scopes":[...],"expiresAt":"...","profile":"default"}}

Flags:

| Flag | Description | |---|---| | --verbose | Write structured diagnostic lines to stderr | | --json | Write a single JSON envelope to stdout | | --profile <name> | Credential profile name to read (default: default) |


ratio app create <name>

Scaffold a new Ratio app from a template into a new directory named <name>.

# Minimal Node.js app (default)
ratio app create my-app

# Node.js app with an admin UI panel
ratio app create my-app --template=with-admin-ui

# Cloudflare Workers serverless app
ratio app create my-app --template=serverless

Flags:

| Flag | Description | |---|---| | --template=<name> | Template to scaffold from: minimal (default), with-admin-ui, serverless | | --verbose | Write structured diagnostic lines to stderr | | --json | Write a single JSON envelope to stdout: {"ok":true,"data":{"template":"...","path":"...","filesWritten":N,"next":[...]}} |

Templates at a glance:

  • minimal — plain Node.js Express-style server with OAuth callback and webhook handler. Starts on port 3000 (npm run dev).
  • with-admin-ui — API server (port 3000) plus a React admin panel (port 3001, npm run admin:dev).
  • serverless — Cloudflare Workers entry point; deploy with wrangler.

After scaffolding, run ratio app link to write the clientId into ratio.config.jsonc.


ratio app link

Link the app in the current directory to a Ratio app registration. Signs you in (if needed), lets you pick or create an app, then writes its clientId into ratio.config.jsonc.

# Interactive: prompts for credentials, lists your apps, lets you pick or create
ratio app link

# Pre-fill the developer email to skip that prompt
ratio app link --email [email protected]

# Attach to an existing app by its id (non-interactive)
ratio app link --app-id 4f9d2c31-8a6b-4f2e-9c1d-3e5a7b9d0f12 --json

# Write a known clientId directly without contacting the server
ratio app link --client-id ratio_ci_1234

Flags:

| Flag | Description | |---|---| | --email <address> | Developer email for sign-in (prompted when omitted) | | --client-id <id> | Write this clientId directly into ratio.config.jsonc without contacting the server | | --app-id <uuid> | Attach to an existing app by id; its clientId is fetched and written | | --category <slug> | Category slug used when creating a new app (default: general) | | --verbose | Write structured diagnostic lines to stderr | | --json | Write a single JSON envelope to stdout |

Environment variables:

  • RATIO_DEVELOPER_TOKEN — skip interactive sign-in entirely by providing a developer bearer token. Intended for CI pipelines. This is separate from RATIO_API_TOKEN (used by other commands). Store it as a CI repository secret and never echo it in logs.
  • RATIO_SERVER — override the server base URL (default: https://api-gw-v4.dev.gokwik.in/sandbox).

Manifest file: ratio.config.jsonc must exist in the current directory before running ratio app link. The command reads appName and rewrites the clientId field in-place, preserving all comments and whitespace.


ratio app dev

Run the current app locally. Reads ratio.config.jsonc from the current directory and starts two side-by-side processes:

  1. Your own dev command (the devCommand field in ratio.config.jsonc).
  2. A webhook listener that forwards platform events to your local server.

Output from both processes is multiplexed to stdout with per-child line prefixes. If either process stops, the other is shut down and the failing exit code is propagated. Ctrl+C stops both cleanly.

ratio app dev
ratio app dev --verbose

Flags:

| Flag | Description | |---|---| | --verbose | Write structured diagnostic lines to stderr |

--json is not supported for ratio app dev — the command is a long-running process that streams interleaved child output.

Manifest fields read:

| Field | Required | Description | |---|---|---| | devCommand | Yes | Command string to start your app (e.g. npm run dev). Tokenized by the CLI and spawned without a shell. | | devServerPort | No | Port your dev server listens on. When set, passed to your dev command as PORT env var. |

Exit codes: the codes you are most likely to see from ratio app dev are 10 (a child process could not be started), 11 (a child had to be forcibly terminated during shutdown), 130 (Ctrl+C), and 143 (SIGTERM). These are part of the CLI-wide taxonomy — see Exit codes and troubleshooting for the full table.


ratio dev listen

Stream webhook events from your Ratio dev session and forward them to a local HTTP server. Requires an active sign-in.

# Forward all events
ratio dev listen --forward-to localhost:3000/webhooks

# Filter to specific topics
ratio dev listen --forward-to http://127.0.0.1:3000/webhooks --events=orders.created,orders.updated

# Machine-readable event log on stdout (NDJSON)
ratio dev listen --forward-to localhost:3000/webhooks --json

Flags:

| Flag | Description | |---|---| | --forward-to <url> | Local URL to forward events to (localhost only, explicit port required). Required. | | --events <topics> | Comma-separated event topics to forward (default: all topics forwarded) | | --verbose | Write structured diagnostic lines to stderr | | --json | Write one NDJSON object per event to stdout instead of key=value lines to stderr |

Event log line shapes:

  • Key-value mode (default): seq=N t=<timestamp> topic=<topic> forward-status=ok:200
  • JSON mode (--json): {"seq":N,"t":"<timestamp>","topic":"<topic>","forward-status":"ok:200"}

Forward status tokens: ok:<http-status>, err:timeout, err:network, err:http-<status>, filtered, dropped:control.


ratio dev trigger [topic]

Fire a synthetic Ratio webhook event for local testing. The platform delivers it to your registered webhook endpoint.

# List available topics and their scenarios
ratio dev trigger --list

# Fire an event
ratio dev trigger orders.created --scenario=cod --app-id=4f9d2c31-8a6b-4f2e-9c1d-3e5a7b9d0f12

# List in JSON
ratio dev trigger --list --json

Flags:

| Flag | Description | |---|---| | --scenario <name> | Payload scenario: cod, prepaid, cancelled | | --list | List available topics and scenarios | | --app-id <uuid> | App id whose synthetic delivery to trigger (UUID). Required when a topic is given. | | --verbose | Write structured diagnostic lines to stderr | | --json | Write a single JSON envelope to stdout |


ratio version

Print the CLI version.

ratio version

ratio help

Show help for any command.

ratio help
ratio help auth login
ratio help app create
ratio help dev listen

Coming-soon commands

The following commands are registered and will print a guidance message, then exit. No destructive action is taken.

  • ratio app deploy — deployment to the Ratio platform (coming in a future release).
  • ratio app info — show details about the current linked app (coming in a future release).
  • ratio app generate — generate code inside the current app (coming in a future release).

Configuration

Environment variables

| Variable | Used by | Description | |---|---|---| | RATIO_API_TOKEN | All commands | OAuth token override. When set, bypasses the stored credential file, so ratio auth whoami cannot report identity while it is set. Store it as a CI repository secret; never echo it in logs. | | RATIO_DEVELOPER_TOKEN | app link only | Developer bearer for unattended sign-in. Strictly separate from RATIO_API_TOKEN. Store it as a CI repository secret; never echo it in logs. | | RATIO_SERVER | app link | Server base URL override (default: https://api-gw-v4.dev.gokwik.in/sandbox). | | RATIO_NO_UPDATE_CHECK | All commands | Set to 1 to disable the "new version available" nudge and skip the background registry check. See "Auto-update check" below for the full suppression matrix. |

Auto-update check

On every invocation the CLI checks the npm registry, at most once per 24h, for a newer published version of its own package. When a newer version is known (from the persisted cache), a two-line nudge is written to stderr (never stdout):

▲ Update available @ratio-app-sandbox/cli 0.1.4 → 0.1.5
  Run: npm install -g @ratio-app-sandbox/cli@latest

The check is asynchronous and fire-and-forget: it never delays your command's exit or changes its exit code, and any network / registry failure is completely silent (no stack traces, no partial output).

Suppression matrix — the nudge is NOT shown when any of the following is true:

| Condition | Reason | |---|---| | --json is present on the command | Byte-clean JSON contract; the nudge would corrupt stdout consumers. | | stderr is not a TTY (piped, redirected) | The nudge is intended for interactive terminals only. | | CI env var is set to any truthy value | Prevents CI log floods. Falsy values (empty string, 0, false) do not suppress. | | RATIO_NO_UPDATE_CHECK=1 | Documented opt-out. Also skips the background registry check entirely. |

The 24h cache lives at <config-dir>/ratio/update-check.json — same <config-dir> resolution used by the credential file. It is safe to delete at any time; the next invocation will rebuild it.

Credential file

Stored credentials are written to:

  • POSIX: ~/.config/ratio/credentials (mode 0600)
  • Windows: %APPDATA%\ratio\credentials

Manifest file: ratio.config.jsonc

Created by ratio app create in the app directory. Fields:

| Field | Required | Description | |---|---|---| | appName | Yes | Human-readable name for the app | | clientId | Yes | Written by ratio app link; identifies the app to the platform | | devCommand | Yes (for app dev) | Command string to start your app (tokenized and spawned without a shell) | | devServerPort | No | Port your dev server listens on; passed as PORT env var to your dev command |


Exit codes and troubleshooting

Exit codes

Every command maps its typed errors to a deterministic exit code. This table applies CLI-wide — any command can return the codes whose condition it can hit.

| Code | Condition | What to try | |---|---|---| | 0 | Success (also used by the coming-soon stubs, which print guidance and exit) | — | | 3 | Not signed in, or the stored session expired and could not be refreshed | Run ratio auth login | | 4 | Scope denied — the signed-in identity lacks a required scope | Re-authorize with the needed scopes | | 5 | Network failure reaching the Ratio server | Check your network and retry | | 6 | Relay connect failure (dev listen could not reach the event relay) | Verify the server URL and that the relay is reachable | | 7 | Template destination already exists (app create into a non-empty directory) | Choose a different name or remove the existing directory | | 8 | Invalid configuration or arguments (validation error) | Fix the flag/manifest value named in the error message | | 9 | Relay resume gap (dev listen reconnected past the event buffer window) | Reconnect; events outside the buffer window are not replayed | | 10 | app dev: a child process could not be started | Check that devCommand in ratio.config.jsonc runs from the app directory | | 11 | app dev: a child had to be forcibly terminated during shutdown | Make your dev command exit promptly on SIGTERM | | 130 | Interrupted (Ctrl+C / SIGINT) | — | | 143 | Terminated (SIGTERM) | — |

Unexpected internal errors render as INTERNAL: <message> and exit with code 1.

ratio app dev shutdown behaviour

  • Drain window: when ratio app dev shuts down (Ctrl+C, SIGTERM, or one child exiting), the orchestrator sends SIGTERM to the children and allows them up to 5 seconds to exit on their own. A child that appears to "hang" briefly during shutdown is usually just inside this drain window. A child that does not exit within it is force-killed, and the run exits with code 11.
  • Second Ctrl+C forces exit: pressing Ctrl+C a second time within 2 seconds of the first skips the remaining drain and exits immediately with code 130. Use this when a child is stuck and you don't want to wait out the drain window.

Reporting bugs

When reporting a bug, re-run the failing command with --verbose and include the diagnostic lines in your report. Diagnostics go to stderr (capture with 2>diagnostics.txt if needed) and never contain tokens or other secret material — see --verbose output conventions.


Architecture

The CLI is organised as reusable library modules (src/lib/) that command entry points (src/commands/) compose. Some library modules are deliberately pure — the dev-store gate module, for example, carries a per-module no-I/O invariant. Others own their I/O directly: credential storage reads and writes the credentials file, the auth loopback server binds a local HTTP listener for the PKCE callback, the manifest readers parse ratio.config.jsonc, and the dev-command orchestrator spawns and supervises child processes. Commands stay thin — they parse flags, compose library modules, and map typed errors to exit codes.

Dev-store gating seam

src/lib/dev-store-gate.ts defines the DevStoreGate interface and a NoopDevStoreGate class (permissive by default). A process-lifetime singleton is exposed via getDevStoreGate(). When the entitlement service is ready, a real implementation will replace the noop without any callers changing — they already depend on the interface, not the concrete type.

Interface:

interface DevStoreGateContext {
  readonly command: string;   // e.g. "app link" — always required
  readonly appId?: string;    // present for authenticated flows
  readonly developerId?: string;
}

interface DevStoreGate {
  assertAllowed(context: DevStoreGateContext): void;
}

The method signature is void-returning — a caller cannot silently proceed after a denial. The only signalling channel is an exception, so a missed try/catch surfaces immediately in tests and logs.

v1 behaviour: NoopDevStoreGate.assertAllowed() is a no-op. Every operation is permitted regardless of store type. A future single-class swap in getDevStoreGate() activates enforcement without touching any consumer.

Preview seam

src/lib/preview/types.ts defines the PreviewController interface and the NullPreviewController class (no-op by default). The factory createPreviewController() (in src/lib/preview/index.ts) always returns a NullPreviewController in v1.

Interface:

interface PreviewController {
  onDevServerReady(port: number): Promise<void>;
  onShutdown(): Promise<void>;
}

v1 behaviour: Both methods of NullPreviewController are async no-ops. ratio app dev v1 does NOT do preview injection — there is no admin iframe, no storefront override, and no preview activation API. The seam exists so that a future release can bind an active implementation without editing the orchestrator.

--verbose output conventions

--verbose writes diagnostic lines to stderr only — one line per boundary crossing (an HTTP request, a spawn, a callback, a shutdown step) — so a failing run can be diagnosed from the terminal transcript alone. The exact lines differ per subsystem. Placeholders below are shown in angle brackets (e.g. <port>); the real output contains the concrete value.

Auth (auth login, token refresh) — lines are prefixed with [verbose]:

[verbose] refresh: fired (access token expired or expiring)
[verbose] POST /oauth/token → <status> (<elapsed>ms)
[verbose] POST /oauth/token → network error (<elapsed>ms)
[verbose] loopback: bound 127.0.0.1:<port>
[verbose] callback: received on port <port> (state ok)
[verbose] callback: timeout fired after <timeout>ms

app dev orchestrator — lines are prefixed with [verbose]:

[verbose] spawn app: <command> (<pid>)
[verbose] spawn listen: (<pid>)
[verbose] app exited: code=<code> signal=<signal>
[verbose] listen exited: code=<code> signal=<signal>
[verbose] signal received: <signal>
[verbose] drain elapsed: <elapsed>ms
[verbose] preview: onDevServerReady(<port>)

app create — plain diagnostic lines on stderr:

template: <name>
destination: <path>
wrote <relative-path>
rendered in <elapsed>ms

dev trigger — plain diagnostic lines on stderr:

server: <url>
trigger: topic=<topic> scenario=<scenario>
trigger accepted in <elapsed>ms

dev listen — plain diagnostic lines on stderr:

session created: <session-id> (expires <timestamp>)
target probe: responded with status <status>

Verbose lines never interpolate environment-variable values or secret material — no access or refresh tokens, no authorization codes, no state values. Only method, path, HTTP status, port numbers, pids, exit codes, signal names, durations, and the user's own declared dev command appear in diagnostic output.

--json output conventions

When --json is supported (see per-command tables above), the command writes a single JSON envelope to stdout:

{"ok":true,"data":{...}}

Errors are not written to stdout in --json mode; they surface as non-zero exit codes with a typed error message on stderr.


Contributing

See LICENSE for the project license. To report issues or propose improvements, open an issue or pull request in this repository.