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
[web] pnpm dev
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 -s prod-eu -b
[web] pnpm build
✓ Connected to deploy@prod-eu.example.com: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.10.2
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)
Bindings:
api -> staging
web -> prod-eu
Gateway: running (pid 24180; web:7100, api:7101)
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. - 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.
- Secrets in the OS keyring - Windows Credential Manager, macOS Keychain, Linux Secret Service. A secret belongs to a credential, so one
pass setcovers every stand that credential reaches. Copy it to the clipboard with one command; nothing lands in a config file, andstatusonly ever reports that a credential exists. - Commands from any directory.
dev,build,test,lintand any custom command run in the right project folder. Commands are taken from your actualpackage.jsonscripts, so a project whose dev script isservestill answers toturnout dev. - 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.
exportwrites your apps, servers, credentials, paths and groups to one file andimportmerges 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-updateinstalls 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
tnis installed alongside. - An action journal. Every state change appends one JSON line - what happened and to which entities, never secrets or output.
tail,grepandjqwork on it directly.
Install
One-line installers. Windows (PowerShell):
irm https://raw.githubusercontent.com/lacodda/turnout/main/tools/install.ps1 | iex
macOS / Linux:
|
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:
With cargo:
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.
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
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
Everything above works today. What is next:
- Named builds - app + server + credential + path under one name, so
turnout deploy webui-prodworks from any directory - Key-based access, set up rather than only used - generate a key, install it on the server and verify it in one command, including the Windows administrator case
- Background runs -
dev --detach,ps,logs,stop, OS notifications - Observability - gateway request log,
doctor,reportfor handing context to an assistant - Deploy consists - atomic deploy and rollback across a group of apps
Released versions and what landed in each: CHANGELOG on the Releases page.
Documentation
The documentation site (Astro Starlight) lives in docs/; architecture decision records are in docs/adr/.
License
MIT (c) Kirill Lakhtachev