Add a project
Click the LocalRun icon in the menu bar, then the + button in the header (or Add New Project if the list is empty). The form opens in two modes.
Folder mode: LocalRun runs the server
Choose a folder and LocalRun inspects it before you type anything:
- If the folder has a
.localrun.json, every field comes from there. - Otherwise it reads
package.jsonand proposes<pm> run dev(falling back tostart), where<pm>is inferred from the lockfile:pnpm-lock.yaml,bun.lock,yarn.lock, orpackage-lock.json. - The port is picked up from a
--port,-p, orPORT=in that script. If the script has none but something is already listening for that directory, the live port is used. - The name defaults to the folder name, lowercased and hyphenated.
| Field | What it does |
|---|---|
| Name | Becomes <name>.test. Lowercase letters, digits and dashes, must start with a letter or digit, 63 characters max. |
| Port | Where your server listens. Leave it blank and LocalRun detects it from the startup output. |
| Run command | What LocalRun executes to start the server. Leave blank if you start it yourself. |
| Build command | What the Rebuild button runs before restarting. |
| Open in Terminal runs | The command a new terminal window types when you hit Open in Terminal: claude, nvim ., whatever. |
| Keep running | Manual, with LocalRun, or Always. See Keep running. |
| Scheme | HTTPS with a locally trusted certificate, or plain HTTP. |
Submit, and the site is live at https://<name>.test. If you set a run command, Start is enabled on
the row.
With no port set, LocalRun watches the process output for lines like listening on 3000 or
http://localhost:5173, then reloads Caddy once it knows. That survives a framework picking a
different port because yours was taken; a hardcoded port does not.
Port mode: LocalRun only proxies
Give it a name and a port, no folder. Use this for a server you start yourself in a terminal, a
container publishing a port, or anything else already listening. LocalRun routes <name>.test to
127.0.0.1:<port> and nothing else; it will not try to start or stop it.
Adopting something already running
The panel has a Running on this Mac section listing local servers LocalRun did not start, with
the folder and git branch it traced them back to. Adopt w/LocalRun gives one a .test name
without restarting it.
What you can then do with that row depends on what the process is: LocalRun classifies it and only
offers what will actually work. Killing a docker-proxy does not stop the container, and signalling
a launchd-supervised process just makes launchd restart it. Service kinds
has the full table.
Pin it in .localrun.json
A .localrun.json in the project root makes the setup reproducible and checks into git, so a
teammate adding the folder gets the same name, port and command:
{
"name": "my-scraper",
"runCommand": "npm run dev",
"buildCommand": "npm run build",
"port": 3000,
"tls": "auto",
"health": "/health",
"keepRunning": "localrun",
"envFile": ".env.local",
"env": { "NODE_ENV": "development" },
"terminalCommand": "claude"
}| Field | What | Required |
|---|---|---|
name | The hostname. Becomes <name>.test. Must match ^[a-z0-9][a-z0-9-]{0,62}$ | no, defaults to the folder name |
runCommand | Shell command that starts the server | only if you want LocalRun to start it |
buildCommand | Shell command the Rebuild button runs before restarting | no |
port | Upstream port, 1-65535. Omit to auto-detect | no |
tls | auto for HTTPS or off for plain HTTP | no; omitted means your default scheme setting, which ships as HTTPS |
health | Path to poll for the health dot, e.g. /health. Checked every 10s | no |
keepRunning | manual, localrun, or always; see Keep running | no |
env | Environment variables as an object | no |
envFile | Path to a dotenv file, relative to the project | no |
terminalCommand | What Open in Terminal runs. {{dir}}, {{name}}, {{port}} and {{url}} are substituted | no |
The file is read when you add the folder and when you re-detect it; editing it does not retroactively rewrite a project you already added. Change those fields in the tray, or remove the project and add it again.
The Rebuild button runs buildCommand and then restarts. It only appears on rows that have
one set. If you cannot find it, that is why.
Working with a row
Click a row to expand it. Three tabs:
- Info: the URL, the port and where it came from, the process, and the actions the daemon says this kind of service supports.
- Logs: a live tail of stdout and stderr, with copy and clear. Log files are keyed by project id, so renaming a project keeps its history.
- Env: a plain-text editor for the project's environment. Saving restarts the process if it is running. Variables only apply to processes LocalRun starts.
Next
How it works explains what the daemon does with all this. If your project should still be up after a reboot, go to Keep running.