diff --git a/docs/deployment.md b/docs/deployment.md index ad6283c0..33773972 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -92,3 +92,89 @@ If you edit the `.service` file itself, run `systemctl --user daemon-reload` bef > ```bash > loginctl enable-linger $USER > ``` + +## macOS LaunchAgent + +On macOS, run the gateway as a `launchd` user agent so it starts automatically after login and restarts if it exits unexpectedly. + +**1. Find the nanobot binary path:** + +```bash +which nanobot # e.g. /Users/youruser/.local/bin/nanobot +``` + +If you installed nanobot with `uv tool`, you may also want the Python path for `ProgramArguments`: + +```bash +which python +``` + +**2. Create the LaunchAgent plist** at `~/Library/LaunchAgents/ai.nanobot.gateway.plist` (replace paths if needed): + +```xml + + + + + Label + ai.nanobot.gateway + + ProgramArguments + + /Users/youruser/.local/share/uv/tools/nanobot-ai/bin/python + /Users/youruser/.local/bin/nanobot + gateway + --workspace + /Users/youruser/.nanobot/workspace + + + WorkingDirectory + /Users/youruser/.nanobot/workspace + + RunAtLoad + + + KeepAlive + + SuccessfulExit + + + + StandardOutPath + /Users/youruser/.nanobot/logs/gateway.log + + StandardErrorPath + /Users/youruser/.nanobot/logs/gateway.error.log + + EnvironmentVariables + + PATH + /Users/youruser/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + PYTHONUNBUFFERED + 1 + + + +``` + +**3. Load and start it:** + +```bash +mkdir -p ~/.nanobot/logs +launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.nanobot.gateway.plist +launchctl enable gui/$(id -u)/ai.nanobot.gateway +launchctl kickstart -k gui/$(id -u)/ai.nanobot.gateway +``` + +**Common operations:** + +```bash +launchctl list | grep ai.nanobot.gateway +launchctl kickstart -k gui/$(id -u)/ai.nanobot.gateway +launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.nanobot.gateway.plist +log stream --process nanobot +``` + +If you edit the plist itself, run `launchctl bootout ...` and `launchctl bootstrap ...` again so `launchd` reloads the updated definition. + +> **Note:** if `launchctl kickstart` fails with an "address already in use" error, you probably still have a manually started `nanobot gateway` process running on the same port. Stop the manual process first, then kickstart the LaunchAgent again.