Getting Started
Three commands: install stack, run stack setup once, then stack up inside any project. That's the whole workflow.
1. Install
$ irm https://github.com/sanayasfp/stack/releases/latest/download/stackenv-installer.ps1 | iex
Already have Rust? cargo install stackenv works too — the crate is published as stackenv since stack was already taken on crates.io, but it installs a plain stack command either way.
2. Run stack setup
One command, once per machine. It hooks into your PowerShell profile so your project's toolchain activates automatically every time you cd in, and installs the three tools stack runs on top of — vfox, uv, and Caddy.
$ stack setup added the stack hook for pwsh checking vfox/uv/caddy... vfox: OK (1.0.11) uv: OK (0.11.7) caddy: OK (2.11.4) caddy: local CA trusted (https://*.localhost works with no browser warning)
Restart your terminal once (or reload $PROFILE) so the hook takes effect. You won't need to run stack setup again unless you switch machines.
3. Create a project
Scaffold a manifest
Starting fresh, stack new asks a few questions with checkboxes for language/service selection — nothing commits until you confirm, so a misclick is a toggle, not a restart. Already have a composer.json or package.json? Run stack init instead — it reads the version you've already declared there instead of asking you to retype it.
$ stack new acme-api
domain: acme-api.localhost
languages (space to toggle, enter to confirm): [x] php
services (space to toggle, enter to confirm): [x] mysql
php version: 8.3.1
mysql version: 8.0.35
created acme-api\stack.toml
next: cd into it, add a [run] command when you know it, then `stack up`
You can also hand-write stack.toml directly — see the Manifest Reference for every field.
Add how it runs
Open stack.toml and set [run] to whatever starts your app's dev server. This is the one process that gets a real, stable URL:
[run]
command = "php -S 127.0.0.1:{port} -t public"
Plain PHP with no [run] at all also works — stack defaults to its own FastCGI engine automatically when [language.php] is declared.
Bring it up
$ cd acme-api $ stack up Loaded C:\Users\you\acme-api\stack.toml project: acme-api domain: acme-api.localhost languages: php services: mysql php: C:\Users\you\.vfox\cache\php\v-8.3.1\...\php.exe -> PHP 8.3.1 (cli) service.mysql: started (pid 41232, port 3306) run: php -S 127.0.0.1:52140 -t public (pid 41244, port 52140) log: C:\Users\you\.stack\logs\acme-api.log routed: http://acme-api.localhost -> 127.0.0.1:52140
That URL works over https:// too, with no browser warning — stack wires up a local CA through Caddy the first time it runs.
4. Everyday use
Once stack setup has run, activation is ambient — there's no daemon to remember to start. cd into any folder with a stack.toml and its pinned php/node/python are already first on PATH, for anything you run by hand: composer install, npm install, a test runner. Leave the folder and PATH resets behind you. stack up is only for the one process that needs a real routed domain and needs to keep running without a terminal watching it.
Done for the day:
$ stack down --all
Stops every project and every shared service at once — the actual 0% CPU point, not just the one project you happened to be looking at.
Need a version pinned outside any project (a global tool, a scratch script), or to briefly turn activation off without leaving the folder? See Profiles & ad hoc execution and stack deactivate in the CLI Reference.
Next
Why stack? — the case for it over Docker-based tools and XAMPP/manual setups. Manifest Reference — every stack.toml field, with defaults. CLI Reference — every subcommand. Examples — four real projects (FastAPI, Node, React, Laravel), each showing a different part of the manifest instead of the same happy path four times.