Quick Start
1
Close, don't quit
Hit the red button — the window hides and the menubar item keeps the engine running.
2
Reopen from the tray
Click the menubar glyph to bring the window back; the engine never restarted.
3
Quit for real
Use Quit PraisonAI from the tray (or
⌘Q) to stop the engine cleanly.Menubar Tray
A menubar item hosts the app’s status and controls, so closing the window means “put it away” rather than “quit”.The tray glyph is a template image (
icons/tray.png) drawn from its alpha channel alone. macOS discards the colour and tints the shape for the current menubar, so the mark is cut into the alpha rather than filled with pixels.Single-Instance
Launching PraisonAI a second time focuses the existing window instead of opening a rival shell. Registered viatauri-plugin-single-instance, and first — the guard runs before anything else touches the lockfile or the engine, so two shells never race over one engine.
Draggable Titlebar
The header carriesdata-tauri-drag-region, and the core:window:allow-start-dragging permission is granted in src-tauri/capabilities/default.json.
Window Geometry Persistence
Position and size are saved as the window moves, resizes, and closes, viatauri-plugin-window-state.
Saves are coalesced during a drag (one file write after a short pause), and geometry is also written on close and exit — because a hidden window never fires a real close, and a signal kill runs neither handler.
Launch at Login
Turning on Open at login asks the OS to register the app to launch at sign-in. The toggle now reflects what the OS actually did, not what you asked for.This is installed-app only. Only the packaged macOS
.app bundle can register a LaunchAgent for the current PraisonAI shell, so the OS refuses on Windows, on Linux, and on macOS when the app runs from a checkout. When it refuses, settings.json stores false, the toggle rolls back to off, and an inline message on the row explains why — the app never claims to be registered when it isn’t. Contributors testing on macOS from cargo run can point PRAISONAI_APP_BUNDLE at the built .app to opt in.The
/settings response returns a launch_at_login_result object whenever the patch touched launch_at_login: {ok, enabled, message}. The UI reads enabled to reconcile the toggle and message to fill the inline warning; a launch_at_login_result where enabled is true means the login item is actually registered.Orphan Reclamation
If a previous run left an engine alive — a crash or a signal kill skips the orderly quit — the app adopts it instead of starting a second one beside it. The lockfile (engine.lock) is bumped to LOCK_FORMAT_VERSION = 2 and distinguishes every outcome:
Absent and corrupt are never collapsed into one answer: absent means spawn, corrupt means a process may still be holding the port and must be investigated. Collapsing them is how an orphan survives every interrupted write.
Best Practices
Close to keep the engine warm
Close to keep the engine warm
The engine takes seconds to start. Closing the window hides it and keeps the process alive, so the next open is instant.
Quit from the tray to stop the engine
Quit from the tray to stop the engine
The red button hides; Quit PraisonAI (or
⌘Q) exits and reaps the engine. Verify with pgrep -f server.py after quitting.Delete the lockfile only when the app is fully quit
Delete the lockfile only when the app is fully quit
If the app is stuck, quit it, remove
engine.lock from the data directory, and relaunch. Deleting it while the app runs invites a duplicate engine.Related
First-Run Provisioning
How the runtime is installed on first launch
Troubleshooting
Startup pill, engine log, and reset recipe

