Project file
On this page
A site's settings normally live only in Short Leash on your computer. Put a leash.toml in the project's folder and commit it, and everyone who clones the project gets the same setup: the PHP and Node versions it needs, its document root, extra names, HTTPS, the services it uses, its background processes and the environment variables that aren't secrets.
Short Leash reads the file from the site's folder only, never from a folder above it, and reads it again whenever it changes.
What goes in it
php = "8.4"
node = "22"
docroot = "public"
aliases = ["shop-admin"]
secure = true
[services]
mysql = "8.4"
postgres = { version = "17", extensions = ["postgis"] }
[processes.queue]
name = "Queue worker"
command = "php artisan queue:work"
keep_running = true
[processes.vite]
command = "npm run dev"
start_on_visit = true
[processes.migrate]
command = "php artisan migrate"
once = true
[env]
APP_ENV = "local"
| Key | What it sets |
|---|---|
php |
A PHP version Short Leash offers, such as "8.4". |
node |
A Node major version, such as "22". "v22.3.0" is read as 22. |
docroot |
The folder to serve, inside the project. "." is the project's folder. A folder that leads out of the project through a link isn't used. Only for sites served from a folder (PHP or static files). |
aliases |
More names the site answers at: "shop-admin" for shop-admin.test. An alias that's another site's name, or the name of a Short Leash service such as reverb, is ignored with a problem. A site has up to 20 aliases. |
secure |
true to serve the site over HTTPS. |
[services] |
Services by their id in Short Leash, with a version: "8.4" matches MySQL 8.4.x, "17" matches PostgreSQL 17.x. A service can list extensions, such as postgis. |
[processes.<id>] |
A background process: its command, an optional name, and how it starts, as on the site's Processes page: keep_running = true starts it with Short Leash and restarts it when it stops, start_on_visit = true starts it on the site's first request (On first visit), and once = true runs it to the end when you choose Run. A process takes one of the three. Without any, it runs when you choose Start. |
[env] |
Environment variables for the site. |
A key Short Leash doesn't know, or a value it can't use, is listed on the site's settings and ignored; the rest of the file still applies. A file that isn't valid TOML, is larger than 64 KB, isn't UTF-8 or is a link to another file isn't read at all, and the site is served with Short Leash's own settings until it's fixed. Neither is a file with an invisible or direction-changing character in a key or value, such as a zero-width space, a right-to-left override or a variation selector: those can make a command look different from what would run. The problem names the key and the character, such as U+202E. An env variable whose value has a control character other than a tab, such as an escape sequence or a line break, is ignored with a problem.
Your own changes: leash.local.toml
Keep changes that are only yours in leash.local.toml beside it, and don't commit it. It goes over leash.toml:
- A single value, such as
phpordocroot, replaces the committed one. - Aliases add up.
- Services, processes and env variables merge by name: an entry in the local file replaces the committed entry with the same name.
leash init adds leash.local.toml to .gitignore for you.
Which setting wins
When the same setting comes from more than one place, the first of these wins:
- The site's settings in Short Leash.
leash.local.toml.leash.toml.- The project's own version files:
.nvmrcor.node-version,composer.json'srequire.php,.python-version,go.modand.ruby-version. - Short Leash's defaults.
So a setting you change in Short Leash always does what it says. When it differs from the file, the site's settings show what leash.toml asks for, with Use leash.toml's, which clears Short Leash's setting so the file's applies. Aliases, env variables and processes add up from all three, and Short Leash's own wins when both have one with the same name.
What applies straight away
The PHP and Node versions, document root, aliases and HTTPS apply as soon as Short Leash reads the file. A version that isn't installed yet is downloaded the first time the site needs it.
Processes and services run things, so they wait until you trust the folder, and so does the file's env anywhere but PHP's requests. Until then the site's settings list them as waiting.
Trust and apply
When a site's file asks for something that isn't in effect, Short Leash says the site has a leash.toml, with Review and Not now. Not now hides it until the file changes.
Review lists what the file would run: its processes with their commands, and its services. Trust and apply trusts the folder for exactly what you were shown, then:
- clears Short Leash's own PHP, Node, document root or HTTPS setting where it hides the file's;
- installs the PHP and Node versions the site then runs on;
- starts a service that's off, or adds one at the version the file asks for, and says so when Short Leash doesn't offer that version;
valkeyandgarnetboth mean this computer's Redis-compatible cache; - starts the file's processes that keep running.
When the file only sets things that apply straight away, the button is Apply and nothing needs trust. Env variables need trust, so a file that sets them gets Trust and apply. If the file changes while you're looking at it, Short Leash doesn't trust the folder and shows you the new version to review.
One grant covers everything the file runs. When the folder is a Git repository's root, it also covers running the repository's Git hooks when you commit from Short Leash, as they are when you trust it: when the repository gets another hook of its own, or a Git setting that needs trust, Short Leash's Git actions ask again before they run it. A site in a repository's subfolder is trusted on its own: the hooks belong to the repository's root, which is a separate grant.
Short Leash asks again when what the file runs changes: a process's command or how it starts, a service, its version or extensions, or the env. It says which: "leash.toml changed what it runs", "leash.toml changed its environment variables", or that the folder changed. A pull that changes them stops the processes the old file started, and nothing from the new file runs until you trust it again. It also asks again when the folder becomes a repository's root, when a file can't be read, and when the folder is moved, renamed or replaced. Changing the PHP version, a process's name or anything else that applies straight away doesn't ask again.
Trust is kept in trust.json in Short Leash's folder, readable only by you, never in config.toml. A trust.json that can't be read is set aside, so every folder is asked about again. One written by a newer Short Leash isn't replaced: update Short Leash, then trust the folder. Folders that are gone are forgotten when Short Leash starts.
To stop trusting a folder, choose Stop trusting on the site's settings. Its file's processes stop, and its services keep running until you stop them.
In the app
A site's Site settings has a Project file section. It lists what the files set (the PHP and Node versions, document root, HTTPS, aliases, env variables, processes and services), each with the file it comes from: "From leash.toml" or "From leash.local.toml". Processes, services and env variables say when they wait for trust. Under the list:
- Whether the folder is trusted, in words: Trusted, Not trusted or Changed since you trusted it, with Review to see what the file runs and Stop trusting to forget a grant. A file that sets nothing that needs trust says so and has no Review.
- What Short Leash ignored in the files, and why, as the files say it.
- Apply when the file asks for something that isn't in effect, named Trust and apply when that needs trust. It opens the trust dialog then, so the trust state has no Review of its own beside it. When Apply would replace your own PHP, Node, document root or HTTPS setting, the section says which first, such as "Apply uses leash.toml's PHP 8.4 instead of PHP 8.3."
- Write leash.toml, which does what
leash initdoes. When the folder has one already, it asks "Replace leash.toml in shop?" first.
Review opens the trust dialog. It lists everything the grant covers: each command and how it starts, each service with what trusting does about it ("Use MariaDB 11.8" when it's on, "Start MariaDB 11.8" when it's off, "Install and start MariaDB 11.8" when Short Leash doesn't have it), every env variable with its value, and the repository's Git hooks when the folder is a repository's root. A command or env variable your own setting in Short Leash hides is listed too, marked "(Short Leash's own wins for now)". The settings Trust and apply would replace are listed under it. The dialog trusts the folder for exactly what it showed. It keeps what it showed while it's open: if the file changes, it says "leash.toml changed while this was open. Look at it again." and Look again shows the new version before you can trust it. If the file changes as you choose Trust and apply, nothing is trusted and the dialog says why. A refused Apply says why too.
The site's other settings show where they come from too. The PHP and Node pickers, the HTTPS switch and each alias say "From leash.toml" when the file sets them. Where your setting hides the file's, they say what the file asks for, such as "leash.toml asks for 8.4", with Use leash.toml's, which clears your setting. If the file asks for something else by the time you choose it, nothing changes and Short Leash asks you to look again. A new PHP or Node version reaches the site's running processes when you restart the site.
A process from the file shows "From leash.toml" on the site's Processes page. It starts, stops and runs like any other, but you change or remove it in the file: its Starts menu shows what the file sets, such as On first visit for start_on_visit = true, and it and Remove are off. A process you add in Short Leash gets an id of its own, never one the file uses. Until the folder is trusted, the file's processes are listed there and in the Overview's Processes as "Waits for trust", with Review, which opens the trust dialog. An env variable from the file shows "From leash.toml" in the site's Environment, without Remove; adding your own value for it there wins over the file's.
When the folder was trusted at a terminal and nothing was applied yet, the section says the file's processes and services start when you choose Apply.
On the Overview
When a site's files ask for something that isn't in effect, its Overview says so under the site's name: "shop.test has leash.toml.", with what the file asks for, such as "PHP 8.4, PostgreSQL 17, 1 process". Review opens the trust dialog, or the site's settings when nothing in the file needs trust. Not now hides it until the file changes.
The site's Needs a look says when its files need you:
- Review when the file runs commands, starts services or sets env variables and the folder isn't trusted, or when they changed since you trusted it. It opens the same trust dialog as the site's settings; nothing trusts a folder until you choose Trust and apply there.
- Use leash.toml's for each Short Leash setting that hides one of the file's, such as "leash.toml asks for PHP 8.4; this site uses 8.3, set in Short Leash." It clears that one Short Leash setting, so the file's applies. If the file asks for something else by then, it changes nothing and asks you to look again.
- Apply when a trusted file names a service that's missing or off. It starts or adds the file's services and does nothing else.
- What Short Leash ignored in the files, with how many more problems the site's settings list.
- When Git tracks
leash.local.toml, with the command to stop:git rm --cached leash.local.toml, then add it to.gitignore.
From the terminal
leash project shows what a site's files set and where each setting comes from, whether the folder is trusted, where Short Leash's own setting hides the file's, and anything Short Leash ignored:
cd ~/Sites/shop && leash project
leash project --site shop --json
Read from leash.toml.
PHP 8.4 (leash.toml)
Node 22 (Short Leash)
Process Queue worker: php artisan queue:work (leash.toml)
Service PostgreSQL 17 with postgis
Not trusted: it runs 1 command and starts 1 service. Run `leash project trust` to review it.
leash project trustlists what the grant allows (each command and how it starts, each service, the env, and the repository's Git hooks) and asksTrust ~/Sites/shop? [y/N]. A command or env variable that Short Leash's own setting hides is listed too, marked "Short Leash's own wins for now": the grant covers it, and it applies if you remove Short Leash's own. It needs you at a terminal and has no option to skip the question. A first grant starts nothing: runleash project applyto start the file's processes and services.leash changes commit --trust,leash changes push --trustandleash workspace merge --hooks trusttrust a repository the same way: they list what the grant allows, with the folder and its fingerprint, and ask. They need you at a terminal and refuse without one.leash project applydoes what Trust and apply does. On a folder that isn't trusted it asks first, at a terminal, whatever its options. It lists each Short Leash setting it would replace with the file's value and asks before replacing them; without a terminal it stops and names them, unless you add--yes, which confirms those replacements and never trusts the folder. If the file changes after it listed them so that Apply would replace something else, it stops and asks you to look again.leash project untrustis Stop trusting.
leash link and leash park say when a folder has a leash.toml, with the command to review it.
Coding agents can read a site's files with the project_file MCP tool: what they set, where each setting comes from, the trust state and any problems. Trust is never a tool: neither an agent nor Short Leash's chat can trust a folder or apply its file.
No secrets
leash.toml is meant to be committed, so it never holds secrets. Short Leash ignores a value that looks like one and names it on the site's settings: names such as APP_KEY, DB_PASSWORD or STRIPE_SECRET, URLs with a password in them, private keys, tokens such as sk_live_… or ghp_…, and Laravel's base64: keys. An empty value, such as DB_PASSWORD = "", is fine. Keep secrets in the project's .env.
Write one from a site
leash init writes leash.toml from a site's settings in Short Leash:
cd ~/Sites/shop && leash init
leash init --site shop --force # replace the leash.toml that's there
- It writes the PHP version the site runs on, the Node version when the project has a
package.json, the document root, aliases, HTTPS when it's on, the site's processes with how each starts and env variables, and the services its.envpoints at, by the version they're known by (mysql = "8.4",postgres = "17"). - It leaves out anything that looks like a secret and says what it left out:
Left out APP_KEY: it looks like a secret. Keep it in .env.That includes a process whose command or name holds a password or token, such as--password hunter2,mysql -phunter2,curl -u admin:hunter2or anAuthorizationheader. It also leaves out a setting with a hidden or control character in it, which Short Leash wouldn't read back from the file, and says so. - Nothing from
leash.local.tomlgoes in: that file is yours. - It doesn't replace a
leash.tomlthat's already there unless you add--force. Run again, it keeps whatleash.tomlalready set, its services and their extensions included, even whereleash.local.tomlchanges it. Only the site's settings in Short Leash replace it. - When the project is in a Git repository that doesn't ignore
leash.local.tomlyet, it addsleash.local.tomlto the.gitignorein the site's folder and says so.
See the CLI reference for every option of leash init and leash project, and ADR 0078 for why the file works this way.