Endara Desktop
A tray app that bundles Endara Relay, manages its lifecycle, and gives you a UI for adding endpoints, running OAuth flows, and watching tool calls live — no terminal required.
Overview
Endara Desktop is a Tauri 2 tray application that wraps the relay. It bundles the endara-relaybinary as a sidecar, spawns it on launch, monitors its health, restarts it if it crashes, and kills it cleanly on quit. Everything you can do from the relay's management API — adding endpoints, completing OAuth flows, browsing tools, streaming logs — is available from the UI, which reaches the management API through a local socket rather than HTTP.
If the relay sidecar exits unexpectedly (an external kill, OS-initiated termination, or a crash), Endara Desktop restarts it automatically with bounded exponential backoff (1s, 2s, 4s, 8s, 16s, capped at 30s). The header status dot turns amber and pulses with a Relay restarting… label during the gap, then flips back to green when the new relay is healthy. After 5 consecutive failed restarts in a short window the supervisor backs off and shows Relay crashed repeatedly; auto-restart suspended. Click Restart to retry. The attempt counter resets after 60 seconds of healthy uptime, so a stable relay that crashes once an hour never hits the cap. Intentional shutdowns (Quit, manual Restart, port conflict) never trigger auto-restart.
In the standard install, the desktop owns the relay. There is no separate background service: the relay's lifetime is bounded by the desktop's lifetime. The relay's MCP endpoint binds to 127.0.0.1:9400 in production (and 127.0.0.1:9500 in dev), so any MCP client on the same machine can reach it over loopback. The management API used by Endara Desktop is exposed on a separate local Unix-domain socket / Windows Named Pipe — see Management API.
Under the hood the UI is a SvelteKit frontend (Svelte 5 + Tailwind CSS 4). It talks to the bundled relay's management API through a Tauri command (relay_api_request) that proxies HTTP semantics over a local Unix-domain socket (macOS / Linux) or Windows Named Pipe — never over a TCP port. This means a malicious page in your browser can't reach /api/* even if it guesses the right URL. Both the GUI and the bundled relay are open source — see endara-ai/endara-desktop.
Install
macOS — Homebrew (recommended)
brew install --cask endara-ai/tap/endaraInstalls the latest signed and notarized DMG from the endara-ai/homebrew-tap tap and registers the app for brew upgrade. The built-in Tauri updater also continues to work, so new versions arrive whichever way you prefer.
Direct downloads
Grab an installer for your platform from github.com/endara-ai/endara-desktop/releases:
| Platform | Format | File |
|---|---|---|
| macOS | DMG installer | Endara_x.x.x_aarch64.dmg |
| Windows | NSIS setup | Endara_x.x.x_x64-setup.exe |
| Windows | MSI installer | Endara_x.x.x_x64_en-US.msi |
| Linux | Debian package | endara_x.x.x_amd64.deb |
| Linux | AppImage | Endara_x.x.x_amd64.AppImage |
First run
Launch the app. The Endara icon appears in your menu bar (macOS) or system tray (Windows / Linux), and the bundled relay starts automatically on 127.0.0.1:9400. Click the tray icon and choose Open Endara to bring up the main window.
From the dashboard you'll see an empty endpoint list (left sidebar) and a detail panel on the right. Add your first MCP server from + Add server, then point any MCP client at http://localhost:9400/mcp. For Claude Desktop, drop this into claude_desktop_config.json:
{
"mcpServers": {
"endara": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:9400/mcp"]
}
}
}Claude Desktop's config file does not accept HTTP URLs directly — entries with a top-level url field are silently stripped on startup. The snippet above uses mcp-remote as a stdio shim that proxies to the relay over loopback. It requires npx on your PATH (ships with Node.js).
For Cursor, paste http://localhost:9400/mcp under Settings → MCP → Add new MCP server → HTTP. Restart the client and your endpoint's tools show up in its tool list, prefixed by the endpoint name.
Start on Login
Open Settings (⌘, on macOS) and toggle Start on Login. On macOS this registers a LaunchAgent at ~/Library/LaunchAgents/Endara Desktop.plist that re-launches the desktopat login — the desktop then spawns the relay as its child. The LaunchAgent does not run the relay directly. On Linux and Windows, autostart uses the platform's native mechanism (XDG autostart and the Windows registry, respectively).
Keyboard shortcuts
| Shortcut | Action |
|---|---|
⌘K | Open global tool search |
⌘, | Open settings |
Esc | Go back / close panel |
Managing endpoints
An endpoint is one MCP server the relay talks to. The sidebar lists every endpoint with a transport badge (STDIO / SSE / HTTP / OAuth) and a health dot — 🟢 healthy, 🟡 degraded, 🔴 failed. Endpoints that are still spinning up display an Initializing…label in place of the usual tool count; the relay's parallel async startup means slow remote/OAuth servers no longer hold up the rest of the UI. Selecting one opens a detail panel with tabs for tools, logs, config, and (for OAuth endpoints) auth.
Add a server
Click + Add server and choose a transport:
- STDIO — paste a command and arguments (for example
npx -y @modelcontextprotocol/server-filesystem /Users/me). By default the relay runs it inside a per-endpoint container (see Containerized stdio servers), falling back to a direct child process when no container runtime is detected. - HTTP — paste a URL like
https://mcp.context7.com/mcpand any required headers. - SSE — for legacy servers that speak Server-Sent Events instead of streamable HTTP.
- OAuth — for remote servers that require an OAuth token. See OAuth setup.
Saving the form writes the new [[endpoints]] entry into ~/.endara/config.toml. The relay's file watcher picks the change up and reloads adapters without a restart — see hot reloadin the relay docs. Once the adapter is healthy, the modal's Advanced section surfaces the upstream-reported serverInfo.name alongside the prefixed-tool preview, so you can see exactly what the relay learned from the server.
The Add Server modal also exposes a Server type override field under Advanced. Use it when an upstream MCP server reports a placeholder or unhelpful serverInfo.name(e.g. Google's hosted MCP servers all self-identify as statelessserver). The override replaces the label the relay advertises to connected clients in Connected server types: — tool-name routing (the tool_prefix) is unaffected. See tool prefixing for the full story.
If you start typing in the configure step and then dismiss the modal (Escape, backdrop click, or Cancel), Endara asks Discard changes?before closing. The catalog browse step (before you've picked a server) still closes instantly. The per-endpoint Config tab applies the same guard to any navigation away from unsaved edits — clicking a different server in the sidebar, switching to another inner tab, jumping to a top-level tab, pressing Cmd+,, or using the Unified Catalog's jump-to-endpoint icon all prompt before discarding. Saving clears the dirty state.
Edit, disable, or remove
Right-click an endpoint (or use the ⋯ menu) to edit its configuration, temporarily disable it, restart its adapter, or remove it altogether. Disabling keeps the entry in config.toml but unloads the adapter; removing deletes the entry. STDIO adapters that crash are restarted automatically with exponential backoff — their logs stream to the Logs tab, which renders each line as a structured row — timestamp, color-coded level pill (ERROR, WARN, INFO, DEBUG, TRACE), endpoint chip, and message — with a filter bar above for free-text search, per-level toggles, and an endpoint multiselect; tool-call events are highlighted inline. The per-endpoint Logs tab live-streams new lines scoped to that endpoint only. The per-endpoint Config tab also exposes server_type_override inline so you can change the advertised label without leaving the detail panel.
Browse tools
The Tools tab lists every tool the endpoint exposes, with the prefixed name the relay advertises (<name>__<tool>), the input schema, and the description. The global ⌘K palette searches across every connected endpoint at once.
Containerized stdio servers
Local (STDIO) servers run inside their own per-endpoint container by default, for stronger isolation and clearer observability. Endara auto-detects a container runtime — docker or podman — and runs each server in a small mcp-runner image that ships with uvx and npx on the path, so the usual launch commands work without installing anything on the host. If no runtime is detected, Endara falls back to spawning the server directly, exactly as before.
The endpoint detail panel shows a status badge — CONTAINERIZED (docker) or DIRECT — alongside live CPU, memory, and network stats for the container. The Config tab adds an isolation toggle and a volume-mount editor that takes Docker-style host:container pairs, so servers that need host paths (key files, Unix sockets) can be wired up from the UI. The Logstab surfaces each container's stderr line by line, tagged [stderr], so a failure shows the server's own error message instead of a cryptic exit code.
Endpoint profiles
Profiles let you serve a named subset of your endpoints under their own MCP URL — for example, a work profile reachable at http://localhost:9400/mcp/work that only exposes the servers you added to it. See Endpoint profiles in the relay docs for the URL shape and protocol details; this section covers the Desktop UI.
Create and delete profiles
Open the Profiles tab in the main window. Click + New profile, give it a short name (used in the URL), and submit — the profile shows up immediately with an empty allow-list. Right-click a profile (or use its ⋯ menu) to rename or delete it. Deleting a profile removes its entry from config.toml and tears down its URL; the underlying endpoints are untouched.
Add servers to a profile
From the profile detail page, click + Add serverand pick from a list of registered endpoints. Or open any server's detail panel and use its Profiles sub-tab to toggle membership in each profile. Both flows write straight to config.toml and the relay picks up the change without a restart.
Per-profile TOON + JS Execution toggles
Each profile carries its own JS Execution and TOON Output toggles on the profile detail page, independent of the global toggles on the Settings page. Flip JS Execution on for an agent that benefits from the meta-tool surface while keeping it off for another agent on the same machine, or run one profile in raw-JSON mode for a tool that needs JSON while keeping TOON on everywhere else.
Copy a claude_desktop_config.json snippet
The profile detail page includes a copy button that yields an mcp-remote-based snippet ready to paste into claude_desktop_config.json, pointed at the profile's URL. The same pattern works for any stdio-only client that can't speak streamable HTTP directly.
OAuth setup
Some MCP servers require an OAuth flow before they expose any tools. Endara Desktop runs the entire flow inside the app: you fill in the + Add serverdialog, complete the provider's consent screen in your default browser, and the relay receives the authorization code on a loopback redirect URI at http://127.0.0.1:9400/oauth/callback.
Add an OAuth endpoint
From + Add server, choose OAuth and fill in:
- Name— used to namespace this server's tools (
<name>__<tool>). - URL — the MCP server's endpoint, e.g.
https://mcp.linear.app/mcp. - OAuth server URL— the authorization server's base URL. Many MCP servers advertise this via OAuth metadata discovery; if not, paste it from the provider's docs.
- Scopes — the scopes you want to request, e.g.
read write.
If the authorization server supports Dynamic Client Registration (RFC 7591), the relay registers a client automatically and you don't have to provide a client_id. If not, follow Manual client setup below.
Manual client setup (Google, GitHub, etc.)
For providers without DCR, register an OAuth app yourself before adding the endpoint. Use these values when registering the app:
- Application type: Web application (or equivalent — anything that supports a redirect URI).
- Redirect URI:
http://127.0.0.1:9400/oauth/callback(or whichever port your relay is listening on).
Back in the + Add server dialog, expand the Advanced section and paste the client_id (and client_secretif the provider is a confidential client) before submitting. If the relay still attempts DCR and the authorization server rejects it, the dialog falls back to a manual credentials prompt — paste the same values there. Credentials are persisted via the relay's management API into ~/.endara/tokens/ with mode 0600; they are not written into config.toml. See OAuth credential storage in the relay docs for details.
Run the flow
Submitting the + Add serverdialog kicks off the OAuth flow automatically: your default browser opens the provider's consent screen, and after you approve, the provider redirects to 127.0.0.1:9400/oauth/callback. The relay exchanges the code for a token, stores it, and the new endpoint appears in the sidebar with its Auth tab badge set to Authenticated. Tools become available immediately.
Token lifecycle
- Refresh. The relay refreshes tokens automatically before expiry when a refresh token is present. The Auth tab shows a live countdown to expiry; click Refresh Now to force one.
- Re-authorize. If a refresh fails (revoked, expired refresh token, scope change), the badge moves to Auth Required. Click Re-authorize in the Auth tab to re-run the browser flow against the same endpoint.
Just-in-time sign-in
Endara also handles servers that require sign-in without you having to pick the OAuth transport up front. When you add an http/sse server that advertises OAuth, Endara detects it at add-time and offers to walk you through the OAuth setup wizard right away; declining still saves a plain HTTP endpoint. At runtime, if a tool call hits a server that needs sign-in (an HTTP 401 with a WWW-Authenticate challenge), the relay starts the OAuth flow and hands your client a sign-in URL instead of a raw error — after you sign in, retrying the call just works, and your AI client never sees the upstream 401 or any upstream credentials.
When an OAuth-protected server lands in a connection_failed state, the Auth tab surfaces recovery actions inline: Refresh Now attempts a silent token refresh when a refresh token is on hand, and Re-authenticatereopens the browser sign-in. The two share a busy state so they can't run at the same time.
Organizations (EMA)
PreviewEnterprise-Managed Authorization is a previewcapability. The relay's full sign-in → token-exchange → call chain is implemented and mock-validated, but a live run needs an identity provider and a resource authorization server that both support cross-app access / ID-JAG. No production catalog provider (GitHub, Linear, Slack, Atlassian, …) redeems ID-JAGs today, so you cannot EMA-connect them in production yet. See the relay EMA reference for the full background and the per-provider setup matrix.
An organization is one identity-provider sign-in shared across every MCP server that org governs. Connect it once and Endara detects the servers your organization grants — no per-server URLs or OAuth flows to run by hand.
Connect an organization
From + Add server, choose Connect an organization. The flow walks through:
- Pick a provider — Okta, Microsoft Entra ID, Google, PingOne, or Custom.
- Name the organization (e.g.
Acme Corp) and supply its slug (Okta subdomain, Entra tenant, Ping environment id) or, for Custom, paste the full issuer URL. Endara previews the resolved issuer inline. - Client ID (optional) — paste a pre-registered IdP client id. This is required for Okta and Entra, which do not support automatic client registration. The form reminds you that the IdP app must whitelist
http://127.0.0.1:9400/oauth/callback(or your relay's dev port,9500) — byte-exact, with127.0.0.1rather thanlocalhost. - Sign in — clicking Connect opens the IdP consent screen in your browser. Endara polls until the sign-in lands.
- Detecting— Endara probes which MCP servers the org's credentials can reach.
- Review & select — pick the detected servers you want. Confirming creates an
auth.type = "ema"endpoint per server, all sharing the org's pooled ID token.
See the per-provider matrix for the exact app type, issuer, grants (Authorization Code + Refresh Token), and scopes (openid offline_access) to register at each IdP.
Bind a custom server to an organization
You can also route a server you add manually through an existing organization. In + Add server, for a URL-based (HTTP/SSE) server, use the Organization selector. The default, None — use this server's own authentication, keeps the server's per-endpoint OAuth. Choosing an organization instead creates an EMA endpoint bound to that org (the server URL becomes the EMA resource), and the per-server OAuth fields are hidden. The selector is disabled with a Connect an organization hint when none exist yet, and never appears for stdio servers.
Manage organizations (Settings)
Settings → Organizations lists every connected org with a status pill (Connected vs Sign-in required). Each row offers:
- Detect servers — re-run detection for an already-connected org to pick up newly-granted MCP servers. Servers you already added are shown disabled with an Already addedpill so you don't duplicate them. Disabled with a Sign in first to detect servers hint until the org is authenticated.
- Re-authenticate— re-run the IdP sign-in when an org's session has lapsed (e.g. its refresh token expired). An org whose first sign-in failed shows up here as Sign-in required and can be retried without re-entering its details.
- Remove — delete the org and purge its stored credentials. Endpoints bound to it stop working, so a confirmation prompt spells that out first.
JS execution mode
Endara Desktop exposes a toggle for the relay's JS execution engine. When enabled, the relay stops advertising every tool from every endpoint to the model. Instead it advertises three meta-tools — list_tools, search_tools, and execute_tools — and lets the model run a sandboxed JavaScript program that calls the underlying tools in a single round-trip.
Toggle it from Settings → JS Execution Mode. The relay reloads in place; any open MCP clients pick up the new tool list on their next refresh. The sandbox is in-process boa_engine with no network or filesystem access — see sandbox limits and the meta-tool reference for the full surface area.
TOON output format
Endara Relay re-encodes JSON-shaped tool-call responses to TOON (Token-Oriented Object Notation) before forwarding them to MCP clients, which typically cuts tool-response token usage by 40-60% on the structured shapes most MCP tools return. The encoding is lossless and applies to both the native tools/call path and the relay's meta-tool responses.
Toggle it from Settings → TOON Output Format, directly below the JS Execution Modetoggle. The toggle defaults to on (matching the relay's default) and persists to config.toml as [relay] toon_output. Changes take effect immediately — the running relay sidecar reloads in place, so you do not have to restart the app or the relay process. Flip it off to forward JSON responses unchanged.
Tool-call overlay window
Endara Desktop ships an always-on-top, click-through overlay window that surfaces every MCP tool call routed through the relay as a live card. Cards flash in-flight (blue), turn green on success, or red on failure, then dismiss after a short countdown so the overlay stays out of your way when nothing is happening.
Each card shows the calling client, the upstream server, the tool name, and the call status (for example Claude Desktop → Linear). Repeat calls to the same tool stack into a single card with rising counts and a rolling-average duration, so a burst of activity appears as one entry instead of a wall of toasts. Clicking a card jumps straight to that request in the desktop Logs view.
Settings
The overlay is enabled by default. Toggle it on or off from the tray menu (Show overlay) or from the new Overlay section of Settings, which also lets you pick the screen corner (any of the four), the maximum number of visible cards, and whether the overlay is suspended while the main Endara window is focused. Every option persists across launches.
How it works
The overlay consumes the relay's tool-call event bus — GET /api/events/tool-calls(server-sent events) on the management API — bridged through the desktop's relay sidecar rather than spoken over loopback HTTP. If the relay sidecar restarts (manual restart, auto-restart after a crash), the overlay re-subscribes automatically once it's healthy again.
Because the overlay is click-through, it never steals focus from windows beneath it — clicks fall through to whatever is under the cursor. The only interactive surface is the optional click target on each card that jumps to the corresponding Logs entry.
Observability
The Observability tab records every proxied tools/call routed through the relay, so you can see exactly what flows through it — the server and tool involved, which client made the request, how long it took, whether it succeeded or failed, and the request and response sizes. Search across calls and filter by server, tool, status, and time window, with latency sparklines to spot slow tools at a glance.
Drill into any call for a detail view that shows the captured request and response payloads in a collapsible JSON viewer, complete with copy and a full-screen pop-out. A confirm-guarded Purge all data action clears the history when you need a clean slate.
Capture, retention, and payload storage are configurable under Settings → Observability: toggle capture on or off, set the retention window, cap the database size, and bound the payload budget.
Tray health indicator
The Endara tray icon displays a small colored dot reflecting overall relay health at a glance — green when everything is healthy, yellow when one or more endpoints need attention (most commonly an OAuth sign-in), and red when the relay itself is failed, stopped, or unreachable. You can see whether anything wants you without opening the app.
Status line in the menu
The first item in the tray menu (and the tooltip on hover) spells out a specific reason instead of a generic label. The exact strings:
Endara — Running— relay healthy and every endpoint is healthy.Endara — Sign in required for {name}— exactly one OAuth endpoint needs sign-in.Endara — N endpoints need sign-in— multiple OAuth endpoints need sign-in.Endara — N endpoints unhealthy— multiple endpoints are in a failed state.Endara — N endpoints need attention— multiple endpoints are degraded for mixed reasons.Endara — Relay failed: {error}— sidecar reported a startup error.Endara — Relay stopped— sidecar exited and is not being restarted (e.g. the supervisor backed off after repeated crashes; see Overview).Endara — Relay not reachable— the management socket can't be reached.
The tray menu also contains the existing Open Endara, Show overlay, Restart relay, and Quitentries. If the icon doesn't appear at all on your system, see Tray icon doesn't appear in Troubleshooting.
Troubleshooting
Relay not starting / port 9400 in use
If the desktop reports the relay failed to start with EADDRINUSE, another process is already bound to 127.0.0.1:9400. The most common cause is having both the bundled relay (inside Endara Desktop) and a separately-installed CLI relay (brew install endara-ai/tap/endara-relay) running. Pick one. Dev builds listen on 127.0.0.1:9500instead — substitute that port below if you're running a dev build.
Find the process holding the port:
# macOS / Linux
lsof -nP -iTCP:9400 -sTCP:LISTEN # use 9500 for dev builds
# Windows (PowerShell)
Get-NetTCPConnection -LocalPort 9400 -State ListenStop whichever instance you don't want. The desktop's relay watchdog restarts the bundled relay automatically on the next health check; if it stays in a failed state, open Settings and use the relay-restart action shown when the relay is down. See also Relay troubleshooting.
NoteThe relay's management API (/api/*) does not bind a TCP port — it lives on a Unix-domain socket / Windows Named Pipe (see Management API). Don't look for an api.sock conflict in the diagnostic above; a separate failure mode is covered in the next subsection.
Management socket conflict (UDS / Named Pipe)
The management API binds to a per-user local endpoint. If the bundled relay reports it can't bind the socket or pipe, a previous process likely left a stale entry behind after a hard kill. The relay attempts to clean these up automatically on the next start, but you can verify and remove the stale entry by hand if needed.
Socket and pipe names include a stable hash of the relay's data-dir (<suffix> below), so the dev build (~/.endara-dev) and the installed production build (~/.endara) get distinct endpoints and can run side-by-side. Locations:
- Linux —
$XDG_RUNTIME_DIR/endara-relay-<suffix>/api.sock - macOS —
$TMPDIR/endara-relay-$(id -u)-<suffix>/api.sock(falls back to the relay's data dir if$TMPDIRis unset) - Windows —
\\.\pipe\endara-relay-<sessionid>(per-user Named Pipe; ACL is restricted to the current user's SID; falls back to\\.\pipe\endara-relay-<data-dir-hash>when no session id is available)
Check whether a stale socket is present:
# Linux — replace <suffix> with the value from the relay's startup logs
ls -l "$XDG_RUNTIME_DIR"/endara-relay-*/api.sock
# macOS
ls -l "$TMPDIR"/endara-relay-$(id -u)-*/api.sock
# If you confirm the relay isn't running, a stale file is safe to remove:
rm -f "$XDG_RUNTIME_DIR"/endara-relay-*/api.sock # or the macOS path aboveNamed Pipes on Windows do not leave a file on disk — the OS releases the pipe when the owning process exits, so the same hard-kill scenario isn't a concern. If a pipe-binding failure persists, another endara-relay instance is still running under the same user account.
Tray icon doesn't appear
If the Endara tray icon is missing from the menu bar — or the Open Endaraentry isn't showing in the tray menu — first quit and relaunch the app. On macOS, check System Settings → Control Center → Menu Bar Only for hidden items, and make sure Endara Desktop is allowed in System Settings → General → Login Items & Extensions if you expect it to launch at login. On Windows and Linux, confirm the system tray / notification area is enabled and not collapsed behind an overflow chevron.
OAuth redirect failed
If the browser approves the consent screen but the Auth tab stays on Needs Login:
- Confirm the Redirect URI registered with the provider is exactly
http://127.0.0.1:9400/oauth/callback(matching the relay's actual port — if you customized it, use that port). - Some VPNs and endpoint security tools block loopback HTTP. Disable them temporarily, or whitelist
127.0.0.1. - Open the Logs tab for the endpoint and look for the OAuth exchange. The same data is available in
~/.endara/logs/relay.log.<YYYY-MM-DD>.
Endpoint stuck in failed or degraded state
Open the Logstab for that endpoint to stream the adapter's stderr live. STDIO adapters auto-restart with exponential backoff, so a transient crash will recover on its own; persistent failures are usually a missing command, an unset env var, or an OAuth flow that hasn't completed. The relay's own log at ~/.endara/logs/relay.log.<YYYY-MM-DD> has the full picture.
Auto-update isn't finding new versions
The Tauri updater checks GitHub Releases. Make sure the app can reach github.com. On macOS you can also force an upgrade through Homebrew:
brew upgrade --cask endara-ai/tap/endaraOn Windows and Linux, re-run the installer from the latest release.
Reset configuration
Quit Endara Desktop, then edit or delete ~/.endara/config.toml. The relay recreates a default config on next start if the file is missing. To force every endpoint back through OAuth, also remove ~/.endara/tokens/.
File locations (macOS)
- Bundled relay binary:
/Applications/Endara Desktop.app/Contents/MacOS/endara-relay - Auto-start LaunchAgent:
~/Library/LaunchAgents/Endara Desktop.plist(only present if Start on Login is enabled) - Desktop log:
~/Library/Logs/ai.endara.desktop/Endara Desktop.log - Relay log:
~/.endara/logs/relay.log.<YYYY-MM-DD>(rotated daily) - Relay config:
~/.endara/config.toml
On Linux and Windows the same parent/child model applies; only the paths differ — the desktop uses Tauri's standard log/config directories for the ai.endara.desktopidentifier, and autostart uses the platform's native mechanism (XDG autostart on Linux, the Run registry key on Windows) instead of a LaunchAgent.