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

turnout-cli

v0.19.0

Published

A developer's switchyard: point local apps at any backend stand, keep servers and secrets at hand, build and deploy from any directory

Readme

A developer's switchyard: point local apps at any backend stand, keep servers and secrets at hand, build and deploy - from any directory.

Why

Working against several backend stands scatters the day: you cd into a folder to start a project, edit .env files across repositories to switch a stand, dig through notes for a password, and keep deploy paths in your head.

turnout keeps all of it in one place and works from any directory.

A day in the life

Point an app at a stand:

$ turnout use web staging
'web' now uses 'staging'.
The running gateway picks this up automatically.
Stand check: https://staging.example.com responded with 200 OK.

Nothing in the project changed - the app still talks to localhost, and the gateway routes it to the stand you picked. Your session survives the switch, because cookies are kept per app and stand.

Start working, from wherever you happen to be:

$ cd ~/dev/web/src/components
$ turnout dev --open
[web] pnpm dev --port 5100
[web] http://web.localhost -> dev server port 5100
◇  web ready in 1.4s - http://web.localhost

The server is up, the page is open, and the console stays quiet from here - until something breaks, which is when you want it loud.

Move the whole contour at once when the frontend and the API must agree:

$ turnout use contour prod-eu
Group 'contour' now uses 'prod-eu':
  web -> prod-eu
  api -> prod-eu

Forgot a name? Leave it out and pick from a list that shows where things point:

$ turnout use
? Switch ›
❯ contour   group: web, api
  api       -> staging
  web       -> staging

Ship it:

$ turnout deploy web-prod-eu -b
[web] pnpm build
✓ Connected to [email protected]:22
✓ Backup 20260809-011500.tar.gz created in /var/www/web.backups
================>          2.02 MiB/3.11 MiB · 1.81 MiB/s · eta 1s  assets/index-b3f0a1.js
Uploaded 142 files (3.11 MiB) to prod-eu:/var/www/web
✓ Ran: systemctl restart web
Deploy of 'web' to 'prod-eu' finished.

Every long flag has a short form, and nothing runs silently: the upload reports throughput and an ETA, and the steps that talk to the server say so while they wait.

And see what has been going on:

$ turnout status
turnout 0.19.0
Data directory: ~/.local/share/lacodda/turnout
Apps:    2 (api, web)
Servers: 2 (prod-eu, staging)
Group:   contour (web, api)
Creds:   1 (prod-deploy)
Paths:   1 (wwwroot)
Targets: 1 (web-prod-eu)
Bindings:
  api -> staging
  web -> prod-eu
Gateway: running (pid 24180)
Front:   http://localhost - http://NAME.localhost
Spare:   web:7100 -> VITE_API_URL, api:7101 -> TURNOUT_GATEWAY_URL
Recent:
  2026-08-09T01:15:02Z  deploy         web -> prod-eu (142 files)
  2026-08-09T01:12:44Z  use            web -> prod-eu

What you get

  • A dev gateway. Apps always talk to localhost; turnout forwards to the selected stand over HTTP or HTTPS (self-signed certificates allowed per server), rewrites redirects, proxies WebSockets, and keeps a cookie jar per app+stand pair so switching does not log you out.
  • One address per app. http://myapp.localhost reaches the dev server turnout started for myapp, whichever port it took - the gateway's front door routes by name, and *.localhost needs no hosts file. The port is assigned once and handed to the server as PORT and {port}; turnout open myapp opens the address.
  • You never type a port. turnout assigns an app's gateway port when you register it and its dev port on the first dev; both live in turnout only, and the app is handed the address - turnout dev sets it as an environment variable the framework can see (VITE_API_URL, REACT_APP_API_URL, your pick), and a .env.development.local that turnout keeps in step covers a dev server started from an IDE. build never gets it, so a production bundle cannot bake in localhost.
  • Servers, logins and paths kept apart. A machine, the credential that logs into it and the directory files land in are three named entities. Define a deploy account once and point every stand at it; declare a web root once and reuse it across servers.
  • Named deploy targets. The four of them under one name: turnout deploy web-prod-eu from any directory, no flags to re-type. A first deploy that has no target yet offers to save the one it just used.
  • Key access set up, not just used. turnout key setup prod generates an ed25519 key, authorizes it on the server, proves it signs in and only then switches the credential over - so a server-side misconfiguration never costs you the password that still works. Windows servers included: an administrator account keeps its keys in a different file that sshd reads instead, and turnout writes to the right one.
  • The SSH agent signs for you. A credential can authenticate with a key the agent already holds unlocked, so a passphrase is typed once per login session instead of once per command - turnout never reads the key file at all. SSH_AUTH_SOCK on Linux and macOS; on Windows, Pageant or the OpenSSH agent service, whichever is running. An agent holding several keys is the normal case: they are offered in turn and the first the server accepts wins.
  • Secrets in the OS keyring - Windows Credential Manager, macOS Keychain, Linux Secret Service. A secret belongs to a credential, so one pass set covers every stand that credential reaches. Copy it to the clipboard with one command; nothing lands in a config file, and status only ever reports that a credential exists.
  • Commands from any directory. dev, build, test, lint and any custom command run in the right project folder. Commands are taken from your actual package.json scripts, so a project whose dev script is serve still answers to turnout dev.
  • A quiet console. A build shows a loader and its elapsed time, not two minutes of scrollback; a dev server goes quiet once it reports itself and speaks again only when something breaks. A failure prints its output on the spot - no re-run to see what went wrong - and every job's output is kept in a log file whatever the terminal showed. -v gives you all of it, and so does any pipe, so scripts and CI logs are unchanged.
  • A hand on the server. turnout ssh web-prod opens a session with host, port, user and key from the catalogs, in the deploy directory, the password already on the clipboard; turnout exec web-prod -- docker compose ps runs one command there and hands back its exit code.
  • Deploy over SSH/SFTP - build, upload, restart, with remote backup and restore when a release goes wrong. Artifacts travel as a single archive instead of thousands of round trips, falling back to file-by-file when the server cannot unpack one. Linux and Windows servers alike: turnout detects which shell answers SSH and phrases every remote command in it.
  • Portable settings. export writes your apps, servers, credentials, paths, targets and groups to one file and import merges it on another machine; secrets come along only when you ask, sealed with a passphrase.
  • Stays current. A once-a-day check mentions a new release without ever delaying a command, and self-update installs it - leaving package-manager installs to their package manager.
  • Groups. Bind a whole contour to one stand with a single use.
  • Nothing to memorize. Leave a name out and pick it from a list; in bash, Tab completes app, server, credential, path and group names from your own catalogs. The short alias tn is installed alongside.
  • An action journal. Every state change appends one JSON line - what happened and to which entities, never secrets or output. tail, grep and jq work on it directly.

Examples

Three small apps under examples/ exist to see turnout at work rather than read about it:

  • vue-demo and react-demo - the gateway end to end: the app's own address through the front door, the gateway URL handed over by turnout dev, requests reaching the stand, and the cookie jar keeping what the browser never sees. Each README is the setup, three commands long.
  • deploy-demo - a page that shows when its bundle was built, so a deploy is verifiable at a glance.

Install

One-line installers. Windows (PowerShell):

irm https://raw.githubusercontent.com/lacodda/turnout/main/tools/install.ps1 | iex

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/lacodda/turnout/main/tools/install.sh | sh

On Windows use the PowerShell line above: install.sh carries the macOS and Linux builds only, and run from Git Bash it stops with a pointer back here.

With npm:

npm i -g turnout-cli

With cargo:

cargo install turnout

Binary releases - grab the archive for your platform from Releases (Windows x86_64, Linux x86_64, macOS arm64), unpack and put turnout on your PATH.

The installers and the npm package also register the short alias tn (skipped if the name is already taken; TURNOUT_NO_ALIAS=1 opts out). cargo install gives you turnout only. The alias is a link to the binary rather than a copy of it, so an install costs one binary and both names always answer with the same version.

Both installers take the newest release by default; set TURNOUT_VERSION to a tag to pin one, and TURNOUT_INSTALL_DIR to choose where the binary lands.

Quick start

turnout setup                  # first-run wizard: creates the data directory
turnout app add                # register a project (a wizard over every field)
turnout server add             # register a stand
turnout use                    # bind one to the other
turnout gateway start          # route traffic through the gateway
turnout deploy-setup           # to deploy: walks the credential, path and target

Data lives in the platform user data directory (e.g. %LOCALAPPDATA%\lacodda\turnout on Windows); set TURNOUT_DATA_DIR to override.

Full command reference and concepts: lacodda.github.io/turnout.

Status

v0.19.0, in daily use. Everything above works today: stands and switching between them, the gateway, secrets in the OS keyring, the quiet console, and build and deploy from any directory. What landed in each version: the Releases page.

Documentation

The documentation site (Astro Starlight) lives in docs/; architecture decision records are in docs/adr/.

License

MIT (c) Kirill Lakhtachev