# How Solenta works > Source: https://solenta.app/docs.html — generated from that page by scripts/build-llms.js. Solenta is a local-first desktop app: agents share a persistent local memory, so a later thread can pick up what an earlier one stored, and the Planboard is the project's GitHub issues. Each thread can run Claude Code, Codex, Cursor, Kimi, Grok, OpenCode or Muse Code in its own git worktree. Everything below matches the current app. ## Getting started Download the archive for your platform from [the latest release](https://github.com/currentbits/solenta/releases/latest), unpack it, and launch. The macOS build is signed and notarized, so it opens on a double-click. The Windows build is still unsigned, so SmartScreen will ask once. Solenta does not bundle any agent. Install the CLIs you want to use and it finds them on your `PATH`: - **Claude Code** (`claude`) - **Codex** (`codex`) - **Cursor** (`cursor-agent`) - **Kimi** (`kimi`) - **Grok** (`grok`) - **OpenCode** (`opencode`) - **Muse Code** (`muse`) Add a project from the project menu in the sidebar (**New project**). The destination path is typeable and browsable; a folder that is not a git repository yet is initialized on add. Remove a project from that same menu when you no longer want it in the list. A project is local, or a remote one (see [Other computers and SSH](https://solenta.app/docs.html#ssh)). **New thread** is the button on the search row. Type a prompt and the run streams in live. First launch opens a short wizard: pick an installed agent, add a project, then start a **first thread**. The composer stays empty so you write the prompt yourself. An example is on the last step if you want one. Replay the tour any time from Settings, Show welcome tour. ## Shared memory Solenta supervises a small local **memory server** (HTTP + MCP, SQLite with full-text and vector search). When it is healthy, it is injected into agent sessions automatically, so decisions and gotchas one thread stores are visible to the next. The Memory tab in the right panel lets you search, read and store entries yourself. The server is localhost-only and bearer-token gated. Entries carry **provenance** (which agent wrote them), and each agent builds a trust score from how its entries hold up, which ranks what comes back on a search. Facts can carry **file:line, thread or commit citations**; before a fact is injected, those file citations are checked against the current worktree and contradicted entries are invalidated. Assistant replies in the transcript carry the same idea as **tier labels**: a chip for repo paths the turn read or cited, one for shared-memory tools, one for GitHub issue or PR refs. A message long enough to make a claim (240 characters) with none of those sources is tagged *model prior knowledge*. Short chatter is left unlabeled. The stored embeddings are reused to fold near-duplicates together and to surface entries that contradict each other, and the memory graph records co-occurrence edges so related entries can be walked, not just matched on text. Above facts sit **strategy** entries: distilled *how we work here* notes that survive a single thread. `memory_distill` is how a finished run gets folded into that layer instead of leaving a pile of one-off observations. **Config doctor** lives in Settings, Memory, under Project tools, next to the code map. It lints the repo's `AGENTS.md`, `CLAUDE.md`, and sibling instruction files against a six-axis rubric (commands, architecture, patterns, conciseness, currency, actionability) and against shared-memory conventions, strategies, and verified decisions. Preview generates those files from memory without writing; Write from memory confirms, then writes `AGENTS.md` / `CLAUDE.md` / `GEMINI.md`. Scoring and generation are deterministic, no model in the loop. A **hypothesis ledger** records what an agent tried and ruled out. The next thread on the same problem is handed that list, so it does not spend its first ten minutes re-walking dead ends. A per-repo **code index** of symbols is built once and injected into every dispatched prompt, so a fresh worker starts knowing where things live. Each entry has an **inclusion mode** that decides when it is injected: *always* (the default), *glob* (when a file in play matches its globs), *auto* (when the prompt shares most of its title's words) or *manual* (when the prompt mentions `#` plus the first eight characters of its id). Conditional entries still show up in search. **Save as memory…** in a finished thread's menu drafts a shared memory entry from the run. You review and edit the draft before anything is stored. Two repos with the same folder name get separate memory scopes. The first keeps the plain name; later ones get a short suffix. Settings, Memory lists repos that share a folder name, with a Rename box per scope that moves its memories along. ### Browse the full memory library The Memory tab starts with your project's entries. Search by text or filter by knowledge, convention, strategy or task. Use **+** to add one, and load older memories to browse past the first page. Expand an entry to read its body and citations. When memories need a decision, a review banner opens the queue. The footer shows when consolidation last ran and links to Settings for the code map and config doctor. Switching projects discards the previous project's config-doctor preview and write confirmation, so a stale preview cannot write another repository's instructions. ## Inbox, Planboard, Review The sidebar is the inbox. Threads that need you stay up top. Quiet runs fold into a **Working** shelf at the bottom, next to **Snoozed** and **Settled**. Footer icons are Threads, Planboard, Review, and More. The right-hand inspector is Environment, Agents, Memory, and Skills. It is not a second home for settings. - **Planboard** shows one project's plan as its GitHub issues in Todo / In progress / Done. Cards open the issue on GitHub, and **Start task** on a Todo card opens a thread on it, in worktree, orchestrator or plain mode. - **Review** lists the open PRs per project with their checks, and jumps to the thread that opened one. The **Needs me** toggle swaps the per-project groups for one list of agent PRs across projects, sorted by what each needs: ready to merge, needs your review, stale or closeable, or waiting on the agent or CI. - **More** holds Activity, Kanban, Automations, Usage, Fleet, Insights, and the morning digest. - **Kanban** groups every thread by status (working, waiting on you, done, failed) so a pile of parallel runs stays readable. - **Activity** is a chronological feed, grouped by day, of everything your agents did. Planboard reads the board from labels. Agents on a GitHub-origin project write with the coder-threads tools `issue_create`, `issue_list`, `issue_set_plan`, `issue_complete`, `issue_comment` and `issue_label` (omitted when the origin is not GitHub). Sandboxed `gh` cannot see macOS keychain credentials, so those tools run on the host instead. An issue labelled `plan:doing` lands in In progress, `plan:done` or a closed issue in Done, and any other open issue in Todo. Other labels show as badges on the card. Agent sessions are told this convention, so “keep the plan on the board” is enough to have multi-step work tracked as issues. The view needs a project whose `origin` is on GitHub or GitLab. GitHub calls go through its API with a token saved per host in Settings, Git, under **Source Control**, or the GitHub CLI's token when none is saved; GitHub Enterprise hosts work the same way. GitLab goes through `glab`, including self-hosted hosts with "gitlab" in the name. The header also shows **review load**: how many open, non-draft PRs are waiting and their combined line count. Thresholds follow the 400-line cap, four PRs or 1,200 lines is busy; seven or 2,400 is overloaded, because an orchestrator that parallelizes agents manufactures review bottleneck, not agent bottleneck. The board can also dispatch for you: turn on auto-dispatch and an issue entering `plan:todo` starts its own thread, so labelling a ticket is the same act as queueing the work. Cards can depend on each other. An issue that GitHub marks as blocked by another, or that carries a `blocked-by: #12` label, shows a **Blocked by** badge, and auto-dispatch skips it until the blocker lands. Live plan steps now come from OpenCode and Kimi runs as well as Claude, and the planboard works on SSH remote projects. The sidebar's project scope filter limits Kanban, Planboard and Activity to the same repo, not only the thread list. Spaces are gone; cards carry their project slug instead. ### Saved views and returning to work Save a named sidebar view to reuse a combination of project, search, status, provider and tag filters. Views store matching rules, so new matching threads appear automatically. Changing a filter marks the active view modified; update or rename it from the same menu. Deleting a view leaves its threads alone. If its project or another filter is missing, the view says it is unavailable instead of showing all work. Activity and Kanban have a project selector in their own header. Planboard search accepts a title, an issue number or `#123`. The PR view searches number, title and branch, and offers more results beyond its initial list. Open a thread from a board or report and use **Back to** to restore the view, filters, scroll and row focus. Usage's thread breakdown also links directly to its threads. ### Recently deleted and moving threads Delete offers Undo and keeps the thread in **Recently deleted** for seven days. Restore returns the same conversation, notes and work log without starting a run. The shelf shows the expiry and also offers permanent deletion. Restoring a thread is not a guarantee that its former worktree is still on disk. **Move to project** in a thread's menu moves an idle conversation to another project. A running thread, worktree thread or pending worker cannot move. The move clears the old repository's session, branch and PR bindings so the next run uses the new project. ## Threads and providers A **thread** is one provider session against one project. It keeps its own permission mode, an optional model override, and its conversation. After the first turn, the provider session id is locked in and follow-up turns resume where the previous one stopped. - **Permission mode** is sticky per thread: Ask first, Accept edits, Plan mode, Auto review, or Full access. **Auto review** lets the CLI's own reviewer approve routine actions (Claude and Codex) and still sends you anything it will not approve. - **Model picker** lists the provider's known models; providers without a list accept free-form model ids. - **Reasoning effort** can be set per thread where the provider supports it. On models with a fast tier, **Speed** sets Fast and the model button reads "· Fast". - **Auto** in the model picker routes the first turn by task tier: fast, balanced or strong, picked from the prompt. Map each tier to an agent profile in Edit Project, **Model routing**. Routing never changes the permission mode. - **Agent** picks a custom CLI agent for the thread on Claude and OpenCode (passed as `--agent`), from the project's and your own agent files. - **Fork and hand off** copies a thread, optionally onto another provider, and starts it on a new prompt. **Fork from here** on an assistant message copies the conversation only up to that message; on Claude the native session is forked at that point. - **Best of N** sends one prompt to several providers at once so you can compare the results. Tick **Plan only** to have each one draft a plan without building. On the plan card you like, pick a provider next to **Implement in a new thread** to build it there. - **Agent profiles** save a provider + model + effort + permission combination under a name, so a thread can be set up in one click instead of four. A profile can also carry a [governance policy](https://solenta.app/docs.html#governance). - **Open in new window** in a sidebar thread's menu, `⌘⇧O`, or dragging the card out of the window detaches the thread into a window of its own, while the main window stays the fleet overview. A thread that already has a window gets that window focused, and notifications for it open there. - **Edit and resubmit** rewinds to any past message of yours, lets you change it, and runs again from that point. - **Scratch notes** are a free-text field per thread, edited from the header and previewed in the sidebar, for the context that is not worth a memory entry. - **Rename** a thread from its header or the sidebar menu when the auto-generated title stops describing the work. - **Snooze** hides a thread until a preset (an hour, this evening, tomorrow, next week) without stopping the agent. A thread that blocks on you, or fails after you hid it, wakes early and shows a *Woke* pill. *Settle on merge* archives the thread when its PR lands. - **Drop** images and folders anywhere on the transcript, not only on the composer strip. - **Pin a message** in the transcript to jump back to it. Pins take an optional label. The agent never reads them. - **Files on a question.** When an agent asks you something, you can attach supporting files to the answer, not only type it. The sidebar is a flat list, not per-project groups. Each card carries its project slug and, when the repo has one, its favicon or app icon; a scope filter at the top of the list limits every section to one repo, and status, provider, and tag filters plus group-by sit next to it. Each card uses a small provider mark instead of the harness name. **Pinned** threads sit in their own block at the top (oldest pin first) and never auto-settle. Below that, threads that need attention, then a **Working** shelf for quiet runs (a crew stays there while a background worker is still going), a **Snoozed** shelf (wake-soonest first) and a **Settled** shelf (newest wrap-up first, archived threads at the tail). Forks and subagents nest under the thread that started them; idle stopped fork workers drop off the list. Delegating, Orchestrating and Working show on the card. Right-click a card, or its overflow button, for the thread-actions menu: snooze (a nested submenu of presets), pin, fork or hand off, rename, mute, and settle. The menu is the native Electron menu when the app can show one, otherwise a keyboard-driven overlay (arrows, Home, End, Escape). `⌘N` starts a new thread, `⌘⇧N` starts one in a chosen project. `⌘K` opens the [command palette](https://solenta.app/docs.html#palette). Esc or Ctrl+C stops the live turn, including while the run is still preparing to launch. Quitting the app asks if agents are still working, then SIGKILLs detached CLIs so they do not linger. Click the project slug in the header to start another thread there. The composer's `/` palette lists orchestration commands, the CLI verbs, and the underlying CLI's own skills and custom commands. `/btw` (or `⌥Enter` on a plain draft) asks a side question on the same thread without interrupting the live run. A card, not a new thread, not the follow-up queue. `/usage` opens live account quotas (five-hour and weekly windows where the provider reports them). A mic on the composer transcribes locally, and optional vim mode adds Insert and Normal motions. `/goal ` sets a standing goal for the thread, shown as a chip in the header; a bare `/goal` clears it. Codex uses its native goal and keeps taking turns until the goal is done. Other providers get the goal as a note on each prompt. `⌘F` finds text in the open thread, including messages outside the rendered tail and collapsed tool groups, and in loaded diffs in the Git pane. Enter and `⇧Enter` step through matches. Threads with eight or more prompts get a tick rail on the right edge, one mark per prompt; hover it for the labeled outline and click to put that prompt at the top. `/jump auth` opens the same outline filtered to prompts containing "auth". `⌘⇧T` reopens the last closed pane. **Copy link** in the thread header menu or the sidebar menu copies a `solenta://thread/` link that opens the thread; the project filter menu copies `solenta://project/` links. A thread id in an assistant reply is a link when it belongs to this project. Coming back to a thread that sat idle for half an hour or more shows a dismissible **Recap** card: what was asked, what changed, where it stands, and what is open. It is built locally after each turn, so no provider is billed. While the agent thinks, the working row shows the last line of its latest thought instead of just Thinking. Agents can render an `html` block, or an MCP tool's UI, as a page inside the transcript. It runs in a sandboxed frame with no network access. When an agent calls `secret_request`, a masked **Secret requested** card asks for the value. Provide puts it only in the environment of that thread's next runs, never in the transcript or on disk, and the value is redacted from any output that echoes it. When an MCP server asks a Claude run for input mid-turn, the question shows as an input card instead of failing. A thread that fails keeps its **failure reason** and shows it on the sidebar card and in the Agents panel, so a red thread says what went wrong without being opened. When a provider returns a usage-limit error with a reset clock, the thread parks as **quota-wait** instead of failing. A banner names the resume time; the same prompt is sent again when the quota resets, or immediately with Resume now. Exhausted balance with no clock is still a hard fail. Solenta's own daily and orchestration spend caps are a separate gate and do not park this way. **New thread** on the search row follows your defaults: *Isolate new threads in a git worktree* and *Delegate new threads to a worker* in Settings, the second winning over the first. The caret beside it lists the other ways in: - **New worktree thread**: its own git worktree and branch, so the agent never touches your checkout. - **New orchestrator thread**: the thread hands its first prompt to a worker in a worktree and supervises instead of editing (see [Orchestration](https://solenta.app/docs.html#orchestration)). - **New plain thread**: straight in the project checkout, no worktree. - **New teach thread**: hints and review, not a finished solution (see [Teach mode](https://solenta.app/docs.html#teach)). - **New ask thread**: read-only repo Q&A; no worktree (see [Ask mode](https://solenta.app/docs.html#ask)). - **From an issue**: start from a GitHub or Linear issue. On a draft, the strip under the composer chooses **Local checkout**, **New worktree**, or **Previous worktree** (stacked on the project's latest other worktree branch). That choice locks after the first message. ### Queue or steer While Claude or Codex is running, choose **Queue** to send your draft after this turn, or **Steer** to inject guidance into the live turn. `⌘Enter` follows that choice; `⌘⇧Enter` steers directly. A delivered steer appears on the current turn with a Steered label. If the live turn ends before delivery, Solenta can fall back to queueing; a failed delivery keeps your draft. Other providers use the follow-up queue. A failed or stopped turn leaves queued instructions waiting for you. Failed queue edits keep their text, and Retry uses the actual failed message, including a machine-delivered worker notice. A side question through `/btw` remains a separate card. ### Pins, quotes and attachments Pin a message and optionally label it, then use the pin to jump back even when it is outside the currently rendered transcript. Pins are your bookmarks and are not added to the agent's prompt. Select text inside an assistant reply and choose the quote action or press `⌘⇧C` (Cite) to attach that selection as a quote chip for your next send. A draft can hold several quote chips, each with an optional note. Type `@` in the composer to attach more than files. The list shows your prompt snippets first, then threads, PRs and skills, then files. A thread, PR or skill becomes a chip that survives a restart and is expanded into the prompt when you send. Files still insert `@path`. Save reusable text in Settings, Agents, **Prompt snippets**, then insert one with `@name`. Attach a screen recording (`.mp4`, `.m4v`, `.mov`, `.webm`) and the agent gets up to eight sampled frames, each labelled with the clip name and time. Queued follow-ups show their files as chips, and cancelling a queued follow-up gives back both the text and the files. A Claude thread that sat idle past the prompt cache window with a large context shows a strip above the composer: **Compact first** compacts the conversation before your next send re-reads all of it. Question cards accept supporting files on each answer. Those files belong to that question, separate from the composer draft. In web mode the paperclip accepts ordinary files and offers a folder picker; dropping a directory preserves its tree. Images are available only for models that accept them. Screenshots captured from Browser stay with the thread that requested them if you switch before capture ends. ## Import, eject and reclaim Open the caret beside **New thread**, choose the project, then choose **Import Codex session** or another provider. Codex, Claude Code, Grok, Cursor, OpenCode, Kimi and Muse are supported. Select a session to import, or import all remaining ones. Already imported sessions are marked; re-importing adds new turns to their existing Solenta thread instead of creating duplicates. To continue outside Solenta, choose **Eject to terminal** in the thread menu. This releases Solenta's process for that session, copies a provider-specific resume command and, if a terminal is configured through `TERMINAL`, attempts to open it there. Otherwise paste the command into your terminal. Ejecting a lead does not stop its workers. Solenta holds automatic Codex wake-ups while the session is ejected. Finish the outside CLI turn before choosing **Reclaim**. Solenta reads that known session and appends the outside conversation without duplicating messages already present. Sending a new prompt while still ejected starts a fresh provider session rather than taking the ejected session back. For Codex, read the copied command's model warning: terminal `exec resume` can retain the original rollout model even after you selected another model in-app. ## Codex sessions Interactive Codex conversations support live steering, command approvals and model changes on subsequent turns. Selecting Astra after a Sol turn applies Astra to the next interactive turn while preserving the conversation. Build workflow phases and background completions use the noninteractive CLI path and do not offer live steering. A Codex command approval shows **Accept** and **Deny**. **Accept all** appears only when Codex offers approval for the session. The displayed command is read-only because this provider cannot change it through the approval response. Stop cancels pending requests. Unsupported approval request types are rejected rather than silently approved. When Codex asks to write files, the approval card shows the proposed change as a diff, with its reason and a warning when it asks for session-wide write access under a folder. A sandbox permission ask shows the folder and what it wants, and Accept grants exactly that. An ask whose diff never arrived is refused, never approved blind. First-party memory and Planboard tools are bound to the selected project. Planboard writes run on the host. Workspace-write also grants the Git metadata paths needed to stage and commit in a checkout or managed worktree. Plan mode remains read-only. If Codex reports **already has an active writer**, the error identifies the holder where available. Solenta uses private lock directories and can release a holder it identifies as its own; an outside owner must finish or close before retrying. The session is retained, worker notices wait, and a blind Retry loop is suppressed. Eject and Reclaim are the explicit controls for moving session ownership. Astra and other image-capable Codex models receive images as native inputs. Spark is text-only: its attachment controls still accept files and folders, but reject images. Tool-result images are kept in the transcript. The context ring uses current usage separately from the session's cumulative token totals. ## Command palette Three entry points, one overlay: - `⌘K` is the command list plus recent threads and projects. - `⌘P` searches files in the current project. - `⌘⇧F` searches file contents and jumps to the matching line. Type to filter. The command list includes New thread, Settings, Kanban, Planboard, pull requests, Usage, Fleet, Insights, the morning digest, Add project, and Toggle agents panel (`⌘.`). Selecting a file opens it; selecting a thread or project switches to it. Escape closes the overlay. The same shortcuts are on the keyboard sheet. ## Worktrees and pull requests Each thread can get its own **git worktree**, so agents work on an isolated branch and never touch your checkout. Setup is fail-closed: if the worktree cannot be created, the thread errors instead of silently running in your working copy. The worktree diff is a full-height **Git** pane in the thread center, Environment's Open Git, the next-action Commit, and `/review` all open it there, not as a card in the right-hand panel. The Environment tab still runs `git pull --ff-only`, starts the project dev server, and holds Fork and Handoff. In that pane the Changes list has a **checkbox per file** and a tri-state header checkbox: a commit or a merge stages only the files you ticked, and the button names the count. Everything is checked by default, so leaving it alone commits the lot as before. Clicking a **line number** in the diff opens an inline comment box; sending it posts that comment to the agent as a follow-up prompt with the file, the line number and the quoted diff line attached, so a review note goes straight back into the run. Each hunk has its own stage checkbox and a discard button, so you can commit part of a file or throw away one hunk and keep the rest. A changed image (PNG, JPEG, GIF, WebP, BMP) shows its before and after side by side instead of a text diff, at Fit, 100% or 200%. A worktree thread can start on a chosen local **base branch**, shown in the header and the Git pane. Change the base before the first PR and Solenta rebases this thread's commits onto the new branch; a dirty tree or a rebase conflict is refused and the recorded base stays put. After the first PR the control hides, because the pull request already names the target. The header carries one **next-action** button that names the next git step (commit, push, open a PR, watch checks, or merge) instead of a row of always-visible controls. Create PR works on an unpublished worktree without a prior Push. Create PR opens a **PR workspace** dialog: title, an editable body, a draft toggle and a markdown preview. The body starts from the repo's `PULL_REQUEST_TEMPLATE` in the root, `docs/` or `.github/`, including files in a `PULL_REQUEST_TEMPLATE/` folder. After the PR is open you can view it, edit the body, comment, mark it ready, close it or merge it from the same pane, without a trip to the browser. Its **Code** tab reviews the PR's files in the app, across all commits or one at a time. Mark files viewed; a file that changes in a later push flips to Changed. A thread can link several PRs, including ones in other repos, and a stacked chain offers **Rebase stack** and **Merge stack**. File paths in the transcript open the file in that worktree. Create PR refuses a diff larger than the configured **PR size cap** (default 400 changed lines) before anything is pushed. The header then offers to split the branch into a stack of smaller PRs, or to create this one anyway. Empty the cap in Settings to disable it. Claude shell-command permission cards allow editing before approval. Codex command cards are read-only; see [Codex sessions](https://solenta.app/docs.html#codex) for their approval controls. Answer permission and plan cards from the keyboard, like the CLIs: `y` accepts (or approves the plan), `n` denies (or keeps planning), and `a` always allows for the rest of the session. A pending permission outranks typing: the keys work even while the composer has focus, and are not typed into it. The card's own fields (the command, the rule, plan notes) keep their keys, and a card the guardrail flagged as risky never takes keys from the composer. Always-allow on a shell command is a prefix rule such as `npm test:*`, not all of Bash; edit it, or allow the whole tool, under **Always-allow options**. PR state is live: checks show as badges on the thread card, and merging is a button, not a terminal command. Worktree merge and delete are guarded, so you cannot drop unmerged work by accident. Automatic checkpoints are committed as the agent works, and you can restore to any checkpoint from the Environment tab. Restore rolls the transcript back with the files, not only the tree. The Git pane can also open a **per-turn diff**: what changed between two checkpoints, unified or split, with a chip per file, instead of the whole branch since the base. In the checkpoint list, tick any two checkpoints to compare them, or use **Fork** on one to start a new thread with that checkpoint's files and conversation. Settings, Git has two opt-in merge settings. **Review new PRs with a different provider** has a worker on another installed provider review each PR a thread opens and send real bugs back to the author thread. **Strip agent Co-authored-by lines from squash merges** drops AI agent trailers and keeps human co-authors. A thread whose PR merged offers **Open revert PR**. GitLab projects get the same flow for merge requests through the `glab` CLI: list, check out, create, squash merge, and CI badges from the head pipeline. Work can also start from an issue: paste a GitHub, GitLab or Linear issue reference and Solenta pulls the title and body in as the thread's first prompt. Linear needs an API key in Settings (Git) or LINEAR_API_KEY in the environment. When several worktrees run in parallel, **conflict forecast** compares what they are touching and warns that two branches are heading for the same lines while both are still cheap to redirect, rather than at the merge, when one of them has to be redone. Hover the pill to see the other thread and the colliding files. Finished worktrees are cleaned up rather than accumulating: **worktree GC** gives each project a retention setting (a default applies when the project has not set its own), batch cleanup, and a visible disk-usage figure so you can see what the branches are costing you. **Worktree location** in Settings, Threads moves new worktrees to another absolute folder; existing threads stay where they are. Solenta keeps two idle worktrees per project ready, so a new worktree thread starts without waiting on a full checkout. A new worktree gets copies of gitignored files listed in a checked-in `.worktreeinclude` (gitignore-style patterns), or the root `.env*` files when there is none. Existing files are never overwritten. If a thread's worktree folder was deleted, the next run restores it from the thread's preserved branch, so earlier commits are not lost. **Environment variables** in Edit Project takes one `KEY=value` per line (`#` comments allowed). They apply to agent runs on every provider, workflow phase agents, the thread terminal, verify, setup and quick-action commands, and dev servers, locally and over SSH. **Other folders** in Edit Project adds up to eight more folders next to the project's repo, one path per line (local projects only). The repo still owns git, worktrees, memory and skills. Agents can read and search the other folders, and a **+N folders** badge marks the project. On Claude, an edit in one of them asks first, and **Allow writes to ** on the card grants that folder for the thread. Other providers can read them but not write there, and shell commands are not gated. Coming from Vibe Kanban: Settings → *Your data* reads the local VK database (`db.v2.sqlite` in `~/Library/Application Support/ai.bloop.vibe-kanban` on macOS) and turns cards into threads, mapping leftover worktrees when they still exist. The same section exports a JSON dump of your Solenta projects, threads, and messages. Nothing is locked in. ### Development lanes and previews For a local project, Environment's **Lanes** section lets a thread **Claim lane**. Each lane has a number, branch, working path and assigned `PORT`. **Preview** temporarily mirrors the selected lane into the project checkout; **Restore** returns the checkout afterward. This changes the checkout, so it is guarded against overwriting dirty work. **Spotlight** is a per-project opt-in in Settings, Git. It does not merge or publish a lane. **Recycle wedged** reclaims eligible stale lanes; live runs and previews stay protected. Claimed lanes keep their heartbeat even when you switch away from Git or to another local project. ## Build workflows Type `/workflow` in the composer to run a multi-phase workflow template instead of a single prompt. Phases run in order (seed, analyze, verify, judge, synthesize), phases can fan out to several agents, and each phase can use a different provider. A failed phase agent retries once on the same slot; you can also retry it from the transcript. The Agents panel shows every phase and worker settling in real time. You can write your own templates in the composer. Workflow editor drafts survive moving between templates. Closing a dirty editor asks whether to keep editing or discard. A successful save is retained even if refreshing the template list fails, so retry does not create a duplicate workflow. A true save failure keeps the unsaved draft available. A workflow can live in the repo. When you run the default template, Solenta reads `WORKFLOW.md` (or `.solenta/workflow.md`) from the thread's checkout, so the workflow versions with the branch. An invalid file fails the start with its name in the error. A template you pick explicitly still wins. **Export to repo** in the workflow editor writes a template out as that file and asks before overwriting. A multi-phase run that was cut off by a crash or quit is kept. Retry on an interrupted agent reruns the interrupted agents of that phase and continues from there; finished phases are not redone. ## Orchestration An **orchestrator thread** never edits your code itself. Its first prompt goes straight to a worker thread in its own worktree, and the orchestrator supervises: it can fork more workers, poll them, review what they produce, and merge. Create one from the sidebar caret, from a Planboard card, or make it the default for every new thread with *Delegate new threads to a worker* in Settings. Workers nest under the thread that spawned them in the sidebar. While any of them is still running, the parent reads **Delegating** and stays on the Working shelf rather than reporting itself done. Stopping an orchestrator stops its crew. Like worktrees, orchestrator threads are local-only: an [SSH remote project](https://solenta.app/docs.html#ssh) always gets a plain thread. An agent that forks a worker on a remote project is refused rather than silently sharing the remote checkout, unless it asks for a shared checkout explicitly. A worker row in the Agents panel has a **Stop** button while it runs. A worker an agent forks can never run in a higher permission mode than its lead. When a worker finishes, the lead's wake notice carries a **worker result** card: the diff summary, the verify verdict when a verify command is set, ruled-out hypotheses and review risks. Pending crew notices are saved to disk. After a restart they wait for you, and the lead shows **Resume crew** with the number of held updates. One task can span several repos. **Continue task in another repo** in the thread menu (**Add repo to task** once a group exists) starts a thread in another project, and a **Multi-repo task** banner lists each repo's thread, status and PRs. Each thread still writes only to its own repo. A crew is not just a fan-out. Workers under one orchestrator share a **crew task list**, so each can see what the others have claimed and finished, and they can **message each other directly** instead of routing every fact back through the orchestrator. Loop guardrails cut the case where two workers keep handing the same question back and forth. A **subagent model pool** in Settings lists described candidates; the lead picks per spawn instead of every worker inheriting the same default. When two runs of the same task exist, a Best of N sibling, a fork, or an earlier completed run on this thread, Environment can show a **divergence** compare. It pairs tool steps (name, input, output, decision) and names the first mismatch. Assistant prose is ignored, so two models answering in different words do not count as a split. A length gap is not a verdict while the shorter run is still going. The toggle is *Show divergence compare on threads*; it defaults on and persists in local storage. Three composer commands cover the common shapes without a workflow template: `/handoff` plans here and implements on a fresh model, `/advisor` asks one contrasting model for a second opinion, and `/committee` has two contrasting models converge on a root cause. For ad-hoc fan-out you do not configure anything: you ask. Every agent session gets MCP tools from the built-in `coder-threads` server, so any thread can drive the others: | Tool | What it does | | --- | --- | | threads_list | Lists every thread with id, title, provider and status. | | thread_fork | Copies a thread into a new one, optionally on another provider, and starts it on a prompt. | | thread_send | Starts a run with a prompt on an existing thread. | | refresh_worker_snapshot | Refreshes an idle worker onto its lead's current committed revision without changing the final destination. | | thread_status | Reports a thread's status and the first line of its last reply. | | thread_archive | Archives a thread the same way the sidebar does. | | thread_settle | Marks a thread settled, or clears the override. | | thread_stop | Stops the live run on a thread. | | thread_rename | Renames a thread. | | thread_merge | Squash-merges a worker's branch into the working tree and deletes its worktree. | | thread_pr | Pushes a worker's branch and opens a pull request, leaving the worktree in place. | | work_suggest | Offers out-of-scope work as a one-click chip on the current thread. | | issue_list | Lists GitHub issues on this thread's project origin (Planboard). | | issue_create | Creates a GitHub issue on this origin and labels it plan:todo. | | issue_set_plan | Moves a Planboard issue's plan:todo / plan:doing / plan:done label. | | issue_comment | Appends an issue comment without changing plan labels or closing the issue. | | issue_label | Adds non-plan labels (type, priority, duplicate, needs-info), creating missing ones. | | issue_complete | Labels a plan:doing issue plan:done and closes it. | The five `issue_*` tools are omitted when the project's origin is not GitHub. Out-of-scope findings do not have to derail the current run. `work_suggest` lands a chip under the transcript: start a new thread, file it on the planboard, or dismiss it. A prompt like *“fan out three Grok workers to build this, have Opus review the diffs”* is enough. Runs are asynchronous: the orchestrating agent sends work, then polls `thread_status` until each thread settles. Use Build workflows when the pipeline shape is known and repeatable, and plain-language orchestration when it is not. ### Integrate workers, then land the crew The lead's Agents tab contains **Integration**. It names the path from worker branches to the lead branch and then to the final merge or PR destination. Check worker readiness, select workers and integrate them into the lead. Run **Verify now** on the combined result, then use the destination-named merge or PR action. Worker menus send you back to this lead view instead of silently landing on another checkout branch. Each worker records the lead's committed branch and revision at fork. Uncommitted lead edits are not copied; when the lead has any, the fork event in the lead's transcript says so and names the commit the worker started from. **Refresh snapshot** explicitly updates an idle worker to the lead's current committed revision; it does not change the final merge target. Busy workers and unsafe refreshes are refused. Integrating a worker into the lead keeps its issue open until the combined change actually lands. ## Guardrails and verification An orchestrator owns the rules its workers run under. It can mark **protected config**: files a worker is not allowed to edit, so an agent cannot quietly loosen the settings it is working inside. **Hook packs** are installed into a worker at spawn time, so the checks apply from its first tool call rather than being remembered later. What comes back is scanned for **prompt injection** and for **secrets**, because content a worker read from an issue, a page or a dependency is untrusted input. Deny-tier tools are blocked even when the CLI is in always-approve, on Grok, Cursor, Codex, OpenCode, and Muse. Separately, a thread can carry a **verify command**. The thread only settles green once that command exits 0; if it fails, the thread stays open with the output attached. It is the difference between an agent saying it is done and the build agreeing. After a PR merges, the same command can run again on a delay (**post-merge verification**) and reopen the thread if the build regressed. ### Governance policies An agent profile can carry a **policy**: a default of ask or allow, plus up to 40 rules. Each rule matches a tool, a bash command, a write path or a network target by glob, and blocks, denies, asks or allows. The most severe matching rule wins. A bash rule matches each subcommand, so `npm publish` also catches `cd x && npm publish`. A denied call is logged in the transcript with no card; an ask card says which rule raised it. If you edit a command on the card, the edited version is checked again before Allow goes through. Every decision is written to a signed, chained audit log. Settings, Advanced shows the last 50 entries and a **Verify chain** button that detects tampering. Secrets are redacted before anything is written. In v1 policies apply to Claude threads, and only to calls the CLI asks about: Accept edits, Full access, and allow lists in your Claude settings skip the check. ## Spec mode For work where the plan matters more than the first patch, a thread can run in **spec mode**: it produces **requirements**, then **design**, then **tasks** as separate artifacts, and each one is gated: the next stage does not unlock until you approve the previous one. The artifacts live with the thread, so the tasks that come out the end are traceable back to the requirement that asked for them. You can leave spec mode without approving the remaining stages if the work has moved on. Once `tasks.md` is approved, the checkboxes are a dispatch DAG: each line is an id, a title, and optional `needs:` dependencies. **Dispatch** forks a worker per currently unblocked task; a second click only starts work that is still open. **Converge** has the spec thread re-read the artifacts and the repo and append missing checkboxes. A cycle or a dangling `needs:` id is a parse error, not a silent skip. ## Teach mode A thread can run as a tutor instead of an implementer. **Teach mode** puts a hints-not-solutions persona on every provider, and gates how much of the machine the student can give away. Autonomy starts at *Hints* (ask / plan only), steps up to *Review* after enough passed reviews, then *Pair*, which unlocks full access. The point is a session you can learn from, not a silent patch. ## Ask mode A thread can run in **Ask mode**: read-only questions about the repo, answered from the code index and shared memory. It never spawns a worktree, never calls tools, and never counts against the daily budget. Create one from the sidebar caret, or turn it on from the overflow menu (which clears Teach, which conflicts). The composer then hides permission, Build, Best of N, and attach. Answers prefer the on-device `fm` CLI, then the provider in print mode, then a retrieval-only pack if neither is available. *Start work* turns Ask off and, when Isolate new threads is on, arms a worktree for the next turn. ## Review itinerary Opening an agent's diff should not mean reading files top to bottom. The **review itinerary** builds an ordered, risk-ranked plan from the working-tree diff: CI and config first (a hard stop if those moved), then a scan for duplicated utilities, the critical path, tests, and the rest, chunked by functional area, never alphabetically. Tests can be pulled to the front when that is the review you are actually doing. ## Skills The Skills tab is the installed list. Search by name or description, and open the filter menu for source (user, project, catalog) and provider. **Manage** opens Settings, Skills & MCP, which holds the catalog, add-skill, MCP servers, and import. Project skills remain read-only, while user-installed skills can be managed and synchronized to the provider directories on this machine. When installed copies have drifted, a banner offers Sync. In Settings, open **Import from other tools** to scan Claude Code, Codex or Cursor. Preview skills, slash commands, MCP servers, memories and instruction files, select the items you want, and import them. This is a one-way copy; the source provider home stays in place. Already imported items are identified. Local MCP commands and plugin code require their separate trust choices; scanning the preview does not execute them. Enabled Codex and Cursor plugin commands also appear directly in the composer's slash palette without importing first. Namespaced commands keep plugin names from colliding with existing commands. Disabled or unlisted plugin-cache entries are not offered. In Settings, **MCP servers**, local command arguments accept quoted paths and values containing spaces, or a JSON array of strings. Invalid quoting shows an error and preserves the draft. Trust the local command only after reviewing what it launches. On a project with an Xcode workspace or project, or a `Package.swift` for an Apple platform, Settings, Skills & MCP shows an **Xcode** card. One click adds MobileBuildMCP when it is on your `PATH`, otherwise Apple's `xcrun mcpbridge`. The card shows the exact command first, and offers install hints for whatever is missing. ## Automations Automations run a prompt on a schedule: hourly, daily at an hour, or weekly. Each automation targets a project with its own provider and optional model, and can be paused with a toggle. **Run now** fires one immediately. Runs appear as threads, so scheduled work is as inspectable as interactive work. A finished thread can be **repeated** rather than retyped: put its prompt on a schedule as a new automation, or distill the run into a [Build workflow](https://solenta.app/docs.html#workflows) when the shape of it is worth keeping. Use **Edit** to change an automation in place. Its recent runs link to the corresponding transcripts, including live and quota-wait runs. Changing a name, prompt or model keeps the schedule's identity; changing the schedule recalculates its next run. History retention removes completed old runs, preserving unfinished work. You can also describe an automation in a thread. The agent creates it and a card links to it with **Open in Automations**. Instead of a schedule, **When** can be an event. The app polls for these about once a minute: - **GitHub**: PR opened, PR merged, Label added (optional label filter), Review submitted, Push (optional branch), CI completed (optional branch and result), and Issue opened. **Use triage template** fills in an issue triage prompt that labels, dedupes and questions new issues, so only well-formed ones reach `plan:todo`. - **Linear**: issue created or status changed, optionally per team or status. - **Sentry**: a new grouped issue. Save an auth token in Settings, Git, or set `SENTRY_AUTH_TOKEN`. Each automation has a **Memory** field: notes it keeps between runs, which a run replaces by ending with an `` block. After three failed runs in a row the automation pauses itself and notifies you. Turning it back on resets the count. **Scope** chooses **Private (this machine)** or **Project (solenta.json)**. A project automation is written to `solenta.json` so teammates get the definition, but it only fires on a machine where someone chose **Run on this machine** and approved the file. ## Dev servers A project's dev server starts from the app: Solenta reads `package.json` and offers the `dev`, `start` or `serve` script, keeps the log, and picks the URL out of the output (the usual `Local: http://localhost:5173/` banner) so it is one click away. Stopping the server is a button too: no orphaned process on a port you have to hunt down later. Dev servers launched for a thread receive separate data, configuration, cache and temporary directories. A claimed lane sets its port. Supported local Electron launches also get a distinct thread app name and icon. Apps must respect the supplied environment to use the isolation; it does not rewrite hard-coded paths or ports. Stop and settle clean up the thread's managed dev server. By default the server's URL is taken from its log. To wait for the server to actually be up, declare a readiness probe in `solenta.json`: `{"devServer": {"ready": {"tcp": "$PORT"}}}`. A probe is exactly one of `tcp` (a port), `http` (a localhost URL that must answer 2xx or 3xx) or `exec` (a command that must exit 0, such as `test -f /tmp/ready`). `$PORT` and other variables come from the dev server's environment, so each lane probes its own port. The Dev server card shows the probe's state. The URL appears, and the Browser pane loads it, only once the probe passes. If it hasn't passed by `timeoutMs` (default 120000), the card shows the last error and the server keeps running. Setup commands and quick actions keep their output in the transcript, so you can read, copy or attach it without running the command again. An `onSettle` entry in `solenta.json` (a command, or the name of a quick action) runs once in a worktree thread's checkout when the thread settles. It goes through the same repo-command trust prompt as the rest of the file. ## Project config files A project's setup command, quick actions, `onSettle`, dev server probe, icon and shared automations can live in files at the repo root, so they are reviewed, diffed and shared like code. Three layers apply, highest first: - **Edit project** in the app. A setup command set here replaces the files' setup, and a quick action list set here replaces theirs. Nothing here is shared. - **`solenta.local.json`**, gitignored and for this checkout only. It may hold `setup`, `quickActions` and `onSettle`. - **`solenta.json`**, committed and shared with everyone who opens the repo. Quick actions merge across the two files by `id` (or by name when there is no id). A local entry with the same id replaces the shared one, a new id adds a button, and `{"id": "test", "hidden": true}` hides a shared entry on this checkout. Commands from either file ask for your approval before they first run, and again whenever the merged set changes. Start either file with `"$schema": "https://solenta.app/solenta.schema.json"` and editors that read JSON Schema autocomplete and check every key. Solenta rejects an unknown key, so a typo like `setpu` shows up as an error in Edit project instead of being ignored. If your commands only live in the app, **Move to solenta.json** in Edit project opens a pull request from a new worktree thread. The PR adds them to `solenta.json` and gitignores `solenta.local.json`. Your saved settings stay in place until you clear them after it merges, so nothing changes before review. ## Terminal and Browser panes The thread centre is a split of panes, not one transcript. Chat is the transcript. **Terminal** and **Browser** open from buttons in the thread header and sit beside the transcript rather than under it. The **Terminal** pane is one long-lived shell per thread, started in that thread's worktree (the project root when it has none), so `cd` and exported variables survive between commands and you are never a directory away from what the agent is editing. It is pipes rather than a full TTY: interactive prompts and curses apps are out of scope, and closing the pane kills the shell and its scrollback. The toolbar has **Find** (Enter searches up from the newest output, `⇧Enter` down), **Clear** (the display only, the shell keeps running), **Copy**, and **To composer**, which adds the selected output to your draft as a chip you can review before sending. When the terminal or a dev server prints a build error, a failing test or a merge conflict, a card appears at that line. **Fix it** asks this thread's agent to fix it, **Edit prompt** puts the fix prompt in the composer first, and **Fork** fixes it in a new thread. The **Browser** pane is an embedded browser bound to the thread, with back, forward, reload and an address bar that suggests the thread's dev-server URL. It is restricted to loopback addresses: this is for looking at what you are building, not for browsing the web. The capture button screenshots the visible page and attaches the PNG to the composer. The agent on that thread can drive the same view through its own tool: navigate, reload, click and type by CSS selector, and take a screenshot it can actually see, which closes the loop between changing a page and checking it. The agent can also read the page instead of only looking at it: a size-capped snapshot of the visible roles, names and states, whose refs it can click and type into, and diagnostics with the console messages and request results since the pane opened (no headers or bodies). The viewport picker switches between mobile, tablet, desktop and fill, and agents can switch it too. The **Diagnostics** toggle shows you the same console and network data, with a count of problems. **Inspect** (⌖) lets you pick an element on the page: click it, or Tab to it and press Enter, with ↑ for the parent and Esc to cancel. The picked element goes to the composer as a chip with an optional comment and a cropped screenshot. The picker never reads text field values, redacts secret-looking attributes, and clicking a submit button does not submit the form. ## Spend guardrails Set a daily budget in Settings and Solenta tracks today's spend across all providers. Once the cap is reached, new runs are blocked until tomorrow. Token usage and cost are visible per thread in the composer footer, so there are no surprise bills from a runaway loop. A second cap, **per-orchestration budget**, bounds what one fan-out can spend across all the workers it spawns: the case where a runaway loop gets expensive fastest. Leave it empty for no ceiling; when a wake-up is held back by it, the thread says so instead of stalling silently. **Max concurrent runs** in Settings, Spending caps how many runs go at once across all projects (default 4; empty for no cap). A start beyond the cap is queued on its thread with a Queued #N note and starts, oldest first, as a slot frees up. ## Usage and fleet analytics The **Usage** view breaks spend and token burn down per provider and per model over the last 7, 30 or 90 days, so the question of which model is actually costing you money has an answer. A provider filter narrows the totals, charts and rows. `/usage` is separate: it reads the provider's own quota windows and reset clocks, not the local history. For models that report tokens but no cost, set prices in Settings, Spending, **Model prices** (USD per million tokens for input, output and optional cache read and write). They fill only the missing costs, never override a cost the provider reports, and re-price past usage when you edit them. **Fleet analytics** asks the harder question: is the work any good. It is computed from git and GitHub ground truth rather than from what the agents report about themselves: merge rate, review tax (how much human review each PR pulls in), rework (work that had to be redone), and cost per merged PR. Failure modes are clustered across threads, so a mistake several agents keep making shows up as one pattern instead of ten separate red threads. When a thread finishes, a one-tap card asks how much time it felt like it saved (15 min through 4 h+, or Skip). Fleet analytics sums those estimates against wall-clock and agent-active time for the same threads and reports the **perception gap** as felt divided by wall-clock. Skip records a decline so the card does not ask twice. Threads with no estimate are left out of the ratio rather than treated as zero. The orchestrator also emits **OpenTelemetry GenAI spans**, so runs can be sent to whatever tracing backend you already have. ## External MCP pairing Settings, **Integrations** mints a pairing so a client outside Solenta (Claude Desktop, Claude Code, or any MCP client on this machine) can launch and track tasks through the loopback coder-threads server. Solenta has to stay running. The raw token is shown once at mint; disk stores only a sha256 hash, mode `0600`. Each pairing has a name, an optional expiry (7, 30, 90 days, or none), and an optional project scope. Default capabilities are **read** and **launch**. You can also grant **steer** or **read all tasks**. New work starts in a managed git worktree and, by default, waits for you to approve it in the app. Revoke a pairing any time. Do not put the token on a command line. Hosted agents (ChatGPT, claude.ai) cannot reach loopback. If Tailscale is installed and logged in, **Expose /mcp on the public internet** under **Public URL (Tailscale Funnel)** publishes the MCP endpoint over HTTPS on port 8443, and **Copy public URL** gives you the address. It is off by default. A caller on that URL must sign in with OAuth or present a pairing token; the in-app session token is not accepted there. ## Notifications and updates A desktop notification fires when a thread finishes or needs a decision from you, never while the window is focused, so parallel runs do not turn into a stream of pings while you watch them. For work that ran while you were not watching, the **morning digest** collects it into one summary: what ran, what it cost, and what changed. A waiting update shows next to the sidebar Settings button as a button that installs it and relaunches, so you do not have to open Settings, or GitHub, to act on one. Updates come from plain GitHub releases on two channels: **prod** follows the newest normal release, **nightly** the newest prerelease, and a nightly install never migrates itself onto prod. Nightly ships as **Solenta Nightly** with its own bundle identifier, so both channels can sit side by side; they share one user-data directory. Checking is automatic; installing is not. Solenta downloads only when you click, verifies the archive against the sha256 digest GitHub stamps on the asset, then swaps the bundle in place on macOS. Windows and Linux stage the new tree and swap it in when you Restart. Builds from a dev tree carry no channel stamp and never self-update. ## Phones and browsers Solenta Web serves the whole app to a browser, so you can check on runs from your phone or another device. It runs on the computer that has your projects and agents. Everything is set up in **Settings > Connections > Let other devices in**: 1. Turn on **Serve Solenta Web**. It listens on `127.0.0.1:4620`, which only this computer can reach. 2. To reach it from another device, either turn on **Allow devices on my network** (plain HTTP on your LAN) or, with Tailscale installed, press **Expose over Tailscale (HTTPS)** to reach it from anywhere on your tailnet. 3. Under **Devices**, name the device, pick its access and press **Add device**. Scan the QR code with the device's camera or open the link on it. The token is shown once and the browser remembers it. Access is per device: **Read only**, **Steer threads** (the default) or **Full access**, plus grants for files, git, the terminal (watch or type), preview control and settings. Solenta checks every request against them on the host. Steer threads can approve the agent's tool requests. To change a device's access, revoke it and pair again. Revoking signs the device out at once and its browser asks for a new token. If the connection drops, the page says so and reconnects on its own. A message you send in the meantime waits and goes out once the connection is back. You can also start Solenta Web from a terminal. It prints the address, the token, a sign-in link and a QR code: ``` # macOS /Applications/Solenta.app/Contents/MacOS/Solenta --serve-web # Linux (the unpacked tarball) ~/solenta/solenta --serve-web --serve-host 0.0.0.0 # LAN, plain HTTP ``` If Solenta is already open, this turns Solenta Web on in that app and prints its token. There is no TLS on the LAN bind; use Tailscale for HTTPS. ## Other computers and SSH There are two ways to use a second computer, such as a workstation or a Linux server: - **Connect to another computer** opens the whole Solenta on that computer in its own window. Its projects, threads, agents and worktrees stay there. - A **remote project** keeps one repo from that computer in this window. Git and the agent CLIs run there over SSH. It is described further down. ### Connect to another computer 1. On a Mac, install Solenta in `/Applications` there. On a Linux server you can skip this: Connect offers **Install Solenta on **, which downloads this version into `~/solenta` over SSH and checks it against the release checksum (x86_64 only). 2. Make sure `ssh user@host` works from a terminal on this computer without a password prompt, using an SSH key or agent, and that you have accepted the host key once. 3. In **Settings > Connections > Connect to another computer**, enter the SSH host and press **Connect**. Leave Token blank. Solenta checks the other computer over SSH. If Solenta is not running there it starts it: on a Mac through `open` (someone must be logged in to the desktop), and on Linux without a window. If it is open but Solenta Web is off, it turns Solenta Web on; a copy older than this release cannot be asked to, so Connect tells you to turn on **Serve Solenta Web** there yourself rather than start a second copy on the same data. It then reads the token over SSH, forwards the port through an SSH tunnel, and opens the window. The host key must match `known_hosts`, the tunnel reconnects if it drops, and a remembered token is encrypted with the system keychain. After connecting, Connections shows which Solenta version the other computer runs and which agent CLIs it has and is signed in to. If a Linux host is older than this app, **Update Solenta on ** installs this version the same way; a copy running without a window is restarted on the next connect. If the install finds missing system libraries, it shows the `sudo apt install` line to run there. Agents sign in on the computer they run on: open Settings > Agents in the remote window and press Sign in. ### Linux servers without a display `--headless` runs Solenta without a window and implies `--serve-web`. It needs no X server or Wayland session, only the libraries Electron loads (on Ubuntu: `libnss3 libgtk-3-0t64 libgbm1 libasound2t64`). Use `--no-sandbox` unless `chrome-sandbox` is owned by root with mode 4755. ``` ~/solenta/solenta --headless --no-sandbox ``` Connect starts it this way for you, and the log goes to `~/.solenta-headless.log`. To keep it running after logout and across reboots, use a systemd user service: ``` # ~/.config/systemd/user/solenta.service [Unit] Description=Solenta (headless) [Service] ExecStart=%h/solenta/solenta --headless --no-sandbox Restart=on-failure [Install] WantedBy=default.target ``` ``` systemctl --user daemon-reload systemctl --user enable --now solenta sudo loginctl enable-linger "$USER" # keep it running after you log out ``` The agent CLIs and their sign-ins live on the server. Install and log in to them there (`claude`, `codex login`, and so on) before you start threads. ### If Connect fails - **not in known_hosts yet**: run `ssh user@host` in a terminal once and accept the host key. - **SSH refused the login**: Connect cannot type a password. Add your key with `ssh-copy-id user@host` or load it into your SSH agent. - **Solenta is not installed**: on Linux, press **Install Solenta on **. On a Mac, install it in `/Applications` there. - **Solenta did not start**: on a Mac, log in to the desktop once. On Linux, read `~/.solenta-headless.log` on the server. A missing library shows up there. - **Nothing is listening on port**: the other computer uses a different port. Set the same port in the form, or start it with `--serve-web=PORT`. - On Windows hosts, Solenta cannot be started or its token read over SSH. Start Solenta Web there and paste a device token from its Settings. ### Remote projects A project can also live on another machine while you stay in this window. Set **remote host** (`user@host`) and **remote path** when adding or editing the project, and every command Solenta would run locally is wrapped as: ``` ssh -o BatchMode=yes -o ConnectTimeout=10 user@host 'cd /remote/path && claude ...' ``` The agent CLI executes on the remote and streams back over the pipe, so the UI looks exactly like a local run. Notes: - Auth is key-based only. `BatchMode=yes` never prompts for a password; a host you cannot key into fails fast. - The agent CLIs must be installed on the remote; local installs are not needed. - Worktree setup and pull are local-only in v1. ## Windows The Windows build is a first-class agent host, not a zip of the macOS tree. Adding a project on Windows runs a **doctor**: long paths, Git Bash, Node 22, and whether the repo sits across a WSL boundary. Failed checks are advisory (they do not block add), but they name the fix. Agent CLIs stay attached to the app so Stop stops them, and a sandbox badge shows how the run is isolated. ## Performance and memory use Content search scans saved transcripts in a background worker without loading every archived conversation into the main history cache. A new query cancels the old scan. Skill inventory scans yield between chunks, reuse parsed files across symlink aliases and avoid repeating the full scan just to open the catalog. Memory diagnostics load their full details only when requested. Recently opened transcripts use an eight-entry cache with an 8 MiB estimated payload budget. Recent threads still appear immediately; evicted ones load again when selected. A larger selected transcript remains visible but is not retained in that cache after leaving it. These are cache bounds, not a promise about total application RAM. Work logs are saved per thread, so activity in one thread no longer rewrites all historical logs. The optional export to shared memory has a separate cap of 256 pending entries and a 4 MiB estimated payload, including requests in flight. Under pressure that optional mirror may omit entries; the local conversation history remains intact. Removing a project also retires its idle agent sessions, and quitting cleans up detached agent processes. ## Architecture Electron main owns the agent processes, the store, the memory supervisor and scheduled automations. The renderer is a React app that talks to main over a typed IPC contract. Providers are data-driven adapters around each CLI's stream format. Housekeeping work (titles, summaries, small classifications) is handed to Apple's built-in `fm` CLI on macOS 27 when it is present, so the chores run locally and free instead of billing a frontier model. The full breakdown lives in [docs/ARCHITECTURE.md](https://github.com/currentbits/solenta/blob/main/docs/ARCHITECTURE.md), and contributions are welcome on [GitHub](https://github.com/currentbits/solenta).