LocalRun

Always-on

There are two separate questions here, and mixing them up is the usual source of confusion:

  1. Do your .test names resolve after a reboot, without you opening LocalRun?
  2. Does a particular project keep running?

The first is about the daemon. The second is about that project's keep-running tier.

Keeping the daemon up

Turn on Launch at login in Settings. macOS then starts LocalRun when you log in, the daemon comes up with it, and .test names resolve without you doing anything.

This uses RunAtLoad and nothing else.

KeepAlive would make Quit unwinnable

KeepAlive does not mean "start at login"; it means "restart forever". With it set, quitting LocalRun would immediately relaunch it and the app would look possessed. Launch at login uses RunAtLoad alone, so Quit actually quits.

Quitting LocalRun stops the daemon too. That is deliberate: the app spawns the daemon detached, so without an explicit stop it would outlive the app and keep serving ports you thought you had closed. If you want things running in the background, that is what launch at login and the always tier are for.

Keeping one project up

Set that project's tier to Always. LocalRun writes a LaunchAgent for it into ~/Library/LaunchAgents, and macOS keeps it alive across quit, crash and reboot, including when LocalRun itself is not running.

The generated agent handles the things that break only on other people's machines:

  • A usable PATH. launchd gives a process /usr/bin:/bin:/usr/sbin:/sbin. Homebrew, pnpm, bun, and any nvm-installed node are all missing from that. The agent puts your project's node_modules/.bin first, then the usual install locations.
  • Restart on failure only. A crash restarts, with a throttle. An explicit stop wins instead of fighting you.
  • Logs that keep working. Output is written back into ~/.localrun/logs/, so the Logs tab still shows the project once launchd owns it.

If the first word of your run command cannot be resolved from that rebuilt PATH, LocalRun tells you when you set the tier. Fix it by using an absolute path, or a command that lives in the project's own node_modules/.bin.

Checking it worked

bash
launchctl list | grep localrun

You should see an entry per always-on project. To inspect one:

bash
launchctl print gui/$(id -u)/<label>

Turning it off

Set the tier back to Manual, or press Stop. Stopping an always-on project also demotes it to Manual. Otherwise, the next reboot would bring back something you deliberately shut down.

LocalRun waits for the port to be genuinely free before reporting the stop as done, rather than assuming launchd has finished reaping the process.

What survives what

Quit LocalRunCrashReboot
Launch at login (daemon)Daemon stopsn/aComes back at login
Project on manualStopsStays downStays down
Project on localrunStopsRestartsComes back with the daemon
Project on alwaysKeeps runningRestartsComes back

Next: Troubleshooting if something does not come back the way this table says it should.