Skip to content

desktop: launch_at_login is persisted before it is attempted, the honest result is discarded, and off macOS it can never work #4498

Description

@MervinPraison

Found by a six-lens audit of the desktop app on 27 Aug 2026. Every finding was reproduced against the code, not inferred.
Severity: medium · audit rank 11 of 16.

Breaks: the toggle renders on, persists, and survives restarts while nothing was registered. set_launch_at_login returns {"ok": false, "message": "Only available in the installed app."} (:1113); that result is attached as launch_at_login_result, which grep shows nothing reads, and saveCfg never inspects the response. LAUNCH_AGENT (:1095) is hardcoded to ~/Library/LaunchAgents/, and PRAISONAI_APP_BUNDLE is only ever set from app_bundle(current_exe) (main.rs:300), which searches for a .app ancestor — impossible on Windows and Linux. So there is no Run-key write and no ~/.config/autostart/*.desktop, ever.
Who / likelihood: every Windows and Linux user who touches the toggle; every macOS user running from a checkout.
Where: engine/server.py:1660-1664.

--- a/engine/server.py
+++ b/engine/server.py
@@ -1658,10 +1658,15 @@
-            saved = save_settings(patch)
-            if "launch_at_login" in patch:
-                saved = dict(saved)
-                saved["launch_at_login_result"] = set_launch_at_login(
-                    bool(patch["launch_at_login"]))
+            if "launch_at_login" in patch:
+                # Store what happened, not what was asked. Writing the request
+                # first made the toggle report a login item that was never
+                # registered -- and survive restarts saying so.
+                result = set_launch_at_login(bool(patch["launch_at_login"]))
+                patch = {**patch, "launch_at_login": bool(result.get("enabled"))}
+                saved = dict(save_settings(patch))
+                saved["launch_at_login_result"] = result
+            else:
+                saved = save_settings(patch)
             self._json(saved)

with the registry row surfacing launch_at_login_result.message when enabled came back false. (Actually registering on Windows/Linux is a feature, not a fix; the fix is to stop claiming it.)

Test — engine/test_portability.py (its whole purpose is asserting another platform's behaviour on this one): call the settings handler with {"launch_at_login": true} against a set_launch_at_login stubbed to the non-bundle result, and assert the persisted settings read back false and the response carries the explanation. Fails today (persists true).



Not yet fixed. Filed so it is not lost with the session that found it. The fix and the test above are proposals from the audit — worth re-checking against current main before implementing, since the file has moved since.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclaudeAuto-trigger Claude analysis

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions