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

@infracraft/gate

v0.8.0

Published

Run any Vercel, Railway, or Fly.io CLI command as any account. Real native-CLI switching, per-invocation credential injection, and sandboxed deploys.

Readme


Native CLIs (vercel, railway, fly) hold one account at a time. gate stores as many accounts as you need per provider and lets every native command run as any of them: gate <provider> <anything> passes through to the native CLI with that account's credentials injected per-invocation. gate … auth switch really switches the native CLI session, and deploys run from an isolated sandbox copy of the repo's tracked files by default.

Install

bun add -g @infracraft/gate

Requires Bun. Also install whichever native CLIs you intend to use:

bun add -g vercel          # Vercel
bun add -g @railway/cli    # Railway
brew install flyctl         # Fly.io

Commands

One uniform tree for every provider (vercel, railway, fly):

gate <provider> auth <verb>        # gate account management (table below)
gate <provider> deploy [...]       # sandboxed deploy (railway: `gate railway up`)
gate <provider> <anything else>    # passthrough: the native CLI runs with the
                                   # selected account's credentials injected
gate <provider> -- <args...>       # escape hatch: verbatim native args

Account management (auth)

| Verb | Description | |---|---| | auth login | Add an account by opening the provider's own browser login flow | | auth logout [label] | Remove a stored account; prompts for selection if no label given | | auth switch [label] | Write that account's session into the native CLI auth file. THE real switch | | auth whoami [label] | Show and validate the account; defaults to the currently active account | | auth list | List all stored accounts with an active marker | | auth import | Adopt the current native CLI session as a named account |

Passthrough

Anything that isn't auth or the deploy verb runs natively, with credentials injected per-invocation (Vercel: the global --token flag; Railway/Fly: env vars). The native session is never touched — only auth switch rewrites it.

gate vercel env ls                    # native `vercel env ls` as the active account
gate vercel env ls --project hat-rec  # any project, no .vercel link needed
gate vercel switch my-team            # vercel's own team switch (native)
gate railway logs --account work      # one-shot account selection
gate fly -a work status -a my-app     # gate account "work"; fly app "my-app"
gate vercel env ls --json | jq        # stdout is byte-for-byte native

Interactive runs print one dim account badge to stderr (● work (worker@email)), so you always see who ran the command — pipes and --json output stay clean. If you pass your own --token (Vercel), gate steps aside and says so. The command exits with the native CLI's exit code.

Gate flags

| Flag | Where it's recognized | |---|---| | --account <label>, --account=<label> | Anywhere in the command | | -a <label> | Anywhere — except on Fly, where -a natively means the app name: there it's only read between the provider name and the first native token (gate fly -a work status -a my-app), and never inside deploy args | | --project <name>, --project=<name> | Vercel passthrough only — gate resolves the project via the API and injects VERCEL_PROJECT_ID/VERCEL_ORG_ID, so it works on every command (env, logs, …). Deploy is unaffected (--project stays native there). Native flag reachable via -- | | -- (first token) | Escape hatch — everything after is verbatim native; gate flags must come before it |

Anything after any -- is never interpreted by gate.

Deploys

Sandbox is on by default. Every gate … deploy / gate railway up runs from an isolated /tmp copy of the repo's tracked files (git ls-files) with a stub .git (a fresh git init + git add -A with an unborn HEAD), so the deploy sees a clean copy of exactly what git tracks — never untracked local files.

Deploy flags

| Flag | Description | |---|---| | --account <label>, -a <label>, --account=<label> | Use a specific stored account for this deploy (on Fly, use the long form — -a belongs to fly) | | --no-sandbox | Deploy from the live working tree (native CLI behavior, no isolation) | | --git-metadata | Isolated /tmp copy but with the real .git. The platform sees actual commit data | | --create-project | Create the project when it does not exist, without prompting (the interactive default asks first; this is the CI-friendly opt-in) |

Everything else passes through verbatim to the native CLI. For example:

gate railway up --detach --service api
gate vercel deploy --prod --scope my-team
gate fly deploy --remote-only --strategy rolling

The command exits with the native CLI's exit code. Outside a git repo the sandbox is skipped automatically (there are no tracked files to copy) and the deploy runs natively.

How switching works

gate … switch merges the stored session into the native CLI's auth file and writes it atomically with 0600 permissions. The native CLI then runs as that account with no further gate involvement. The active account is always read directly from the native file; gate never stores which account is "active" separately.

Switching vs passthrough: auth switch persistently rewrites the native auth file — the native CLI then runs as that account even without gate. Passthrough injects credentials per-invocation and leaves the native session untouched. Both coexist; the stderr badge always shows which account ran the command.

| Provider | Native auth file | |---|---| | Vercel | ~/Library/Application Support/com.vercel.cli/auth.json (macOS) · ~/.local/share/com.vercel.cli/auth.json (Linux) | | Railway | ~/.railway/config.json | | Fly.io | ~/.fly/config.yml |

Writes are merge-not-clobber: other keys in the native file are preserved. Vercel tokens are OAuth-based and auto-refresh; the refreshed token writes through to the native file whenever the active account is used.

Non-interactive use (CI)

Off-TTY, gate never prompts. An unresolvable account fails fast with No active <provider> account. Pass --account <label> or run "gate <provider> auth switch"., and an expired session fails with a hint instead of opening a browser. --create-project remains the promptless opt-in for deploy target creation.

Migrating to 0.7

| Before (0.6.x) | After (0.7.0) | |---|---| | gate vercel login (and the other 5 verbs; railway too) | gate <provider> auth <verb> — the old spelling now runs the NATIVE command, with a stderr tip | | gate vercel switch | gate vercel auth switch (top-level switch is vercel's native team switch) | | gate fly auth token (errored) | passes through to the native fly auth token | | gate fly deploy -a my-app (gate ate -a) | -a my-app goes to fly; use --account for the gate account | | Library: ProviderCommandLayout, deployCli, DeployCliContext | removed — deployVerb is a direct provider field; injection lives in nativeCli() |

Running native login/logout through the passthrough modifies the native session outside gate; gate's discovery offers to import the new session on the next run.

Migrating from vergate

The first interactive Vercel command (switch, list, whoami, or deploy without an explicit account) checks whether you have vergate accounts stored. If gate has no Vercel accounts yet and vergate does, gate offers to migrate them automatically. vergate is deprecated in favor of gate.

Library

import {
  AccountStore,
  vercelProvider,
  ensureValidSession,
  runDeploy,
  runPassthrough,
  SandboxMode,
} from "@infracraft/gate"

const store = new AccountStore()
const accounts = store.list(vercelProvider.id)

// Validate + optionally refresh the stored session
const valid = await ensureValidSession(vercelProvider, store, accounts[0])

// Run any native command with injected credentials
await runPassthrough({
  provider: vercelProvider,
  token: valid.session.token,
  nativeArgs: ["env", "ls"],
})

// Run a sandboxed deploy (compose the argv through the provider)
const command = vercelProvider.nativeCli({
  token: valid.session.token,
  args: [vercelProvider.deployVerb, ...vercelProvider.deployDefaultFlags, "--prod"],
})

const result = await runDeploy({
  command,
  urlPattern: vercelProvider.deployUrlPattern,
  mode: SandboxMode.STUB,   // STUB = fresh stub .git, ORIGINAL = real .git, NONE = no sandbox
})

console.log(result.url, result.exitCode)

Key exports: AccountStore, PROVIDERS, vercelProvider, railwayProvider, flyProvider, ensureValidSession, detectActiveAccount, runDeploy, runPassthrough, routeCommand, splitGateFlags, SandboxMode, InteractionMode, CommandRoute, GateAuthVerb, GateFlagRegion, CommandContext, RoutedCommand, GateTreeRoute, PassthroughRoute, InvalidRoute, GateProvider, GateAccount, NativeCliContext, NativeCliCommand, PassthroughTargetCapability, DeployRunOptions, DeployRunResult, DeploySpawner, SpawnedDeploy, PassthroughRunOptions, PassthroughRunResult, PassthroughSpawner, SpawnedPassthrough.

License

MIT