Desktop

The product Electron app composes createNyte. The demo desktop was the last pre-SDK host

There are two Electron apps in this repo. They are not the same product.

PathPackageWhat it is
packages/desktop@nyte-ai/desktopThe product app. Main process hosts createNyte. Renderer talks SDK operations over window.nyte.
packages/demo/desktop@nyte-ai/demo-desktopThe leftover demo. Per-agent conversations and snapshots over the old harness, which is deleted.

Root pnpm dev still starts the demo. Until that script moves, start the product app from its package:

pnpm --dir packages/desktop dev
pnpm --dir packages/demo/desktop dev   # also: pnpm dev

Desktop and the TUI share one store per workspace at ~/.nyte/workspaces/<path-hash>/sessions.db. On first open, a client imports an existing <workspace>/.nyte/sessions.db with a SQLite backup and leaves the original intact. NYTE_HOME overrides ~/.nyte. Missing folders stay in the sidebar with dimmed names, and their saved chats remain available. Trust grants live in ~/.nyte/trust.json, so a folder you trusted in the terminal stays trusted here.

Product desktop

Opening a workspace loads local history without checking trust. Sending resolves the folder through core and requests trust before loading project code. A missing path fails the send, which stays in the outbox for retry. The main process loads the same plugin set as the TUI (system-prompt, rename, context-files, tools-fs, fast-mode, web-search and its provider plugins, skills, plus user and project dirs), then createNyte. Runners attach per session. Switching workspaces keeps earlier sessions and their jobs open.

The renderer never imports @nyte-ai/core. IPC is one nyte:call channel: operation path plus one input object, the same namespaces as the in-process SDK (sessions, messages, jobs, runs, heads, workspace, provider, plugins). watch cannot be an AsyncIterable across IPC, so it is a start/stop pump with the same afterSeq / live cursors.

What you get in the UI today: session list, composer send, plugin slash commands, abort, a pending strip with cancel and redeliver, and a context gauge from runs.context. What the bridge already exposes but the renderer does not draw: the session tree, /usage card, and run-end notifications. Those are TUI surfaces, not missing SDK operations.

The renderer imports controls from @nyte-ai/ui and each product-specific headless namespace from its direct component subpath, such as @nyte-ai/ui/popover. Desktop keeps Cursor-specific layout and StyleX overrides locally; the shared package owns the Base UI dependency, accessible interaction contracts, and reusable control defaults.

Subagent models

The parent chooses an exact available provider/model for each delegated task. Tell it which model to use, or let it choose. There is no General/Explore task type or global subagent model setting. Unavailable models fail without substitution.

Child sessions stay out of the sidebar and chat search. Inspect their progress and results from the parent task or jobs panel.

TUI and desktop share the web-search plugin and saved search credentials. In auto, search prefers providers with keys and keeps the selected route for the session, including after a restart. HTTP 429 can switch to another eligible provider, once per provider per call. Keyed searches never fall back to anonymous access. Explicit provider selections never fail over.

Before the first anonymous request, the run waits for a choice: allow automatic search, choose an installed provider, or turn search off. TUI uses its OpenTUI selection dialog; desktop shows consent controls above the composer. Escape, ordinary messages, and closing the client do not approve search. The choice is remembered for that session. Headless clients must reply through runs.reply.

Search results identify the provider, credential source, and any rate-limit failover, without exposing keys. Routing details belong in the settings dialog, not the TUI footer. /websearch-key <provider> [key] saves a key; omitting the key removes the saved credential. Environment keys still apply, and a terminal-only environment variable may not reach the desktop app.

Jobs

Each chat has a Jobs panel above the composer. It lists commands and subagents, their foreground or background mode, state, and expandable output. Running foreground jobs have Run in background and Cancel job buttons. Background jobs keep Cancel job; finished jobs keep their output. These buttons remain available while the parent run is parked. They target a job, not the entire run.

Jobs panel -> window.nyte.jobs -> validated IPC -> owning workspace SDK
job event  -> refresh jobs list

The panel refreshes on job events and polls every two seconds while mounted. Closing it or switching chats does not cancel work. Closing the owning host interrupts live jobs; recovery retains their records without rerunning them. Terminal background results arrive as user messages when the parent head is idle. Background agents inherit workspace trust and are not offered tools marked availability: "foreground", regardless of tool name or whether a particular wait carries a selection.

GitHub account

Accounts uses the installed GitHub CLI, including at Home without an open workspace. Browser sign-in copies the CLI's one-time code to the clipboard. Sign-out removes the shared CLI login, so it also affects terminal commands and other apps using that login. Local Git does not require it.

Both dev and compiled desktop startup recover POSIX PATH from a bounded login-shell probe before starting the host. Windows keeps its inherited environment. Recovery reads only PATH; shell-only GitHub tokens and configuration overrides are not imported. Use gh auth login for stored CLI credentials.

Set NYTE_OTEL_ENDPOINT in the app's launch environment to enable the existing OTLP exporter. GitHub commands emit desktop.github.command spans with an allowlisted operation, outcome, exit code, and duration. They never include command output, arguments, credentials, device codes, repository paths, or environment values. Export is off when the endpoint is unset.

Demo desktop

Keep this around as a product sketch (agent profiles, per-agent history). Do not copy it if you want the SDK. Its preload was window.ujiDesktop with initialize, login, send, abort, newChat, selectAgent. It forwarded a handful of events from the old harness and discarded suspended on open, so crash resume was not faithful. Plugins were a system prompt from the agent instructions; no filesystem tools, no skills.

Host and client used to treat that IPC as the desktop contract. It is now labeled as the legacy demo. The future @nyte-ai/protocol should mirror window.nyte, not initialize / selectAgent.

On this page