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

@jinyongp/gate

v2.10.1

Published

Agent-friendly Node API and CLI launcher for gate

Downloads

2,165

Readme

@jinyongp/gate

Agent-friendly Node API and CLI launcher for gate, a local HTTPS reverse proxy and port registry for development machines.

Use this package when JavaScript automation needs typed gate data, stable port lookup, or the package-provided gate binary. The proxy, registry, DNS, and trust behavior still live in the gate binary; the Node API is a wrapper around the same JSON command contracts used by scripts.

Install

npm install --save-dev @jinyongp/gate
npx gate --version

Or with pnpm:

pnpm add -D @jinyongp/gate
pnpm exec gate --version

Install only @jinyongp/gate. Platform binary packages are optional dependencies and are selected automatically on supported hosts:

  • macOS arm64/x64
  • Linux arm64/x64

CLI

The package exposes a gate bin. Run these inside a project with a gate.toml:

pnpm exec gate up -d
pnpm exec gate run --up web -- pnpm dev

Prefer gate run when launching dev servers. It injects PORT, peer GATE_<SERVICE>_* values, and service-specific env values declared in gate.toml. When --up is used in an interactive terminal, gate prints the selected route before starting the child process. Use --quiet to suppress that parent hint.

Node API

import { createGateClient } from '@jinyongp/gate'

const gate = createGateClient({ cwd: process.cwd() })
const web = await gate.service('web', { up: true })

console.log(web.port)
console.log(web.url)
console.log(web.loopbackUrl)

service(name) defaults to:

{ up: true, dns: 'localhost', daemon: false }

That means it can reserve and activate routes before reading service metadata. It does not start the daemon unless daemon: true is passed. Use service(name, { up: false }), ls(), or port() for read-only inspection.

Use inline project config when automation needs project-scoped behavior without writing gate.toml into the repository:

import { createGateClient, type GateInlineProjectConfig } from '@jinyongp/gate'

const config = {
  name: 'myapp',
  base: 'myapp.localhost',
  services: {
    web: {},
    api: {
      port: 3001,
      env: 'API_URL',
    },
  },
} satisfies GateInlineProjectConfig

const gate = createGateClient({ cwd: process.cwd() })
const web = await gate.service('web', {
  scope: { config },
})

Inline config is materialized as a generated TOML file in the user cache and passed to the gate binary through --config. scope.project may be used with inline config, but it must match config.name. envFiles are intentionally not part of the Node API; load environment variables before calling gate if inline values use ${NAME} or ${NAME:-fallback} references. Custom domains still require dns: 'hosts' or dns: 'preconfigured'.

Human-facing Node integrations should normally use the default gate state so they share the same registry, route, trust, and cache behavior as the gate CLI. Agent and sandboxed tooling can isolate gate state below a workspace-local, git-ignored runtime directory:

const gate = createGateClient({
  cwd: process.cwd(),
  isolatedRoot: '.gate-agent',
})

isolatedRoot sets GATE_ISOLATED_ROOT, GATE_NODE_CACHE_DIR, and the XDG state variables for gate subprocesses. This keeps generated inline config, registry locks, daemon state, and trust material out of the user's home config, state, data, and cache directories. Use isolated state for temporary agent inspection, tests, and sandboxed setup checks. Use normal gate state for real dev app launches that should share the user's registry, trusted certificate material, and listener daemon. isolatedRoot does not isolate kernel listener ports such as HTTPS :443 and HTTP :80. The Node API rejects isolatedRoot combined with daemon: true; pass daemon: false or omit it. Use the CLI with explicit non-default listener addresses for isolated daemon tests.

Use env() when another runner owns process spawning:

const env = await gate.env('web', {
  scope: { config },
})

await someRunner.start({
  env: {
    ...process.env,
    ...env,
  },
})

env() returns PORT, peer GATE_<SERVICE>_PORT, GATE_<SERVICE>_URL, GATE_<SERVICE>_ROUTE_URL, and service-declared env / routeEnv values from the selected config. Browser-visible variables still need framework-public names such as VITE_API_BASE_URL or NEXT_PUBLIC_API_BASE_URL in routeEnv. The values come from the same descriptor as gate env --json, so route URLs match CLI behavior, including non-default gate listener ports when gate can read the active listener daemon status.

Use ready() when automation needs the selected service descriptor before it starts a child:

const ready = await gate.ready('web', {
  scope: { config },
  up: true,
})

console.log(ready.service.url)
console.log(ready.envKeys)
console.log(ready.daemon?.running)

Use run() when the Node API should spawn the child and inject env itself:

await gate.run('web', ['pnpm', 'dev'], {
  scope: { config },
  onReady({ service }) {
    console.log(service.url)
  },
})

If you already resolved readiness, pass that snapshot to run() to avoid a second descriptor resolution:

const ready = await gate.ready('web', { scope: { config }, up: true })
await gate.run(ready, ['pnpm', 'dev'])

run() defaults to stdio: 'inherit' for human-readable dev-server logs. Agent callers that need structured diagnostics should use stdio: 'pipe'; non-zero exits throw GateError with exitCode, command, and captured stdout/stderr. onReady runs after route/env resolution and before the child is spawned; if it throws, the child is not started. Successful run() results also include service, env, and envKeys for short-lived commands and tests. Readiness diagnostics may include actions[]; suggestedCommand remains available for compatibility.

The Node API does not call gate doctor during normal service(), ready(), env(), or run() flows. Use gate doctor --json separately for install, setup, CI, preflight, or explicit local state diagnosis. Normal API failures surface through GateError fields such as gateCode, severity, retryable, hint, and nextActions.

Binary Resolution

Use resolveGateBinary() when another process needs the concrete binary path:

import { createGateClient, resolveGateBinary } from '@jinyongp/gate'

const bin = resolveGateBinary()
const gate = createGateClient({ bin })

You can also pass bin directly or set GATE_BIN.

Errors

import { createGateClient, isGateError } from '@jinyongp/gate'

const gate = createGateClient()

try {
  await gate.service('web')
} catch (error) {
  if (isGateError(error, 'GATE_DNS_REQUIRED')) {
    // Use a .localhost base, or intentionally pass dns: 'hosts'/'preconfigured'.
  }
  throw error
}

Common error codes:

| code | action | | --------------------------- | -------------------------------------------------------------------- | | GATE_DNS_REQUIRED | Use .localhost, or pass dns: 'hosts' / dns: 'preconfigured'. | | GATE_INVALID_OPTIONS | Fix incompatible scope/config options before retrying. | | GATE_BINARY_NOT_FOUND | Reinstall @jinyongp/gate, or pass an explicit bin / GATE_BIN. | | GATE_UNSUPPORTED_PLATFORM | Use a supported Darwin/Linux arm64/x64 host or provide bin. | | GATE_PERMISSION_REQUIRED | Retry only after explicit approval for privileged DNS/trust changes. | | GATE_SERVICE_NOT_FOUND | Check scope, config path, service name, and reservations. | | GATE_COMMAND_FAILED | Inspect exitCode, gateCode, stdout, and stderr. | | GATE_JSON_PARSE_FAILED | Treat as a gate/version mismatch or broken binary output. |

When available, GateError also preserves the gate JSON error metadata: severity, retryable, hint, and nextActions.

Project Config

Example gate.toml:

[project]
name = "myapp"
base = "myapp.localhost"

[services.web]

[services.api]
port = 3001
env = "API_URL"
route_env = "PUBLIC_API_URL"

See the full usage guide:

  • https://github.com/jinyongp/gate#readme
  • https://github.com/jinyongp/gate/blob/main/docs/usage.md