## Problem
Closing a project tab only hid it in that window. The backend workspace
record kept routing the folder's events, notifications, auto-accept and
pending-request recovery, invisibly, until the palette-only **Stop
Workspace** command was run on the active tab. That command still showed
the V1 message "Stop OpenCode instance? This will stop the server."
although V2 has one shared OpenCode service, and it called
`debug.location.evict`, which (per OpenCode source) rejects pending
permissions, cancels pending Forms, fails plugin RPC and kills terminals
of that directory, even for sessions started elsewhere. OpenCode loads
locations on demand and unloads idle ones itself.
## Change
- **Closing a project tab** (×, Ctrl/Cmd+W) removes that tab's backend
workspace record. CodeNomad stops following it; sessions keep running in
OpenCode and reappear when the project is reopened.
- **Another tab of the same folder** has its own record and is
unaffected.
- **The same record shown in another window**: that window's tab closes
through the existing `workspace.stopped` broadcast, with an info
notification ("closed from another window"); the initiating window shows
nothing.
- **CodeNomad never evicts OpenCode locations**: eviction, its
serialization helpers and `locationOwned` bookkeeping are removed. A
failed launch now always removes its logical record (the retention only
existed to retry a failed eviction).
- **Stop Workspace removed** (command, confirm dialog, i18n keys in all
locales).
- Unchanged: opening an open project still offers a new tab (recent row)
or switching (switch button); temporary projects keep Keep / Discard /
Cancel; window close, app quit, reload, restore and backend shutdown
delete nothing; disconnected-instance dismissal stays local.
- Delete failure: error toast, record kept and reachable from the home
page, no automatic retry.
## Docs
Help in all 10 locales (`projects`, `index`, `desktop`, `server`,
`opencode`, `missions`), `AGENTS.md`, `CONTRIBUTING.md`,
`dev-docs/architecture.md`, `packages/server/README.md` and the
architecture-guide skill now describe the new contract.
## Validation
- UI store tests (`--conditions=browser`): app-tabs,
temporary-instances, workspace-list-reconciliation-fence,
instances-restore-ownership — 30/30.
- Server: manager + shared service 54/54; event ownership and workspace
identity suites pass.
- New real-component browser regression (click ×, Ctrl+W, Cmd+W): 3/3;
project restoration (Electron/Tauri) and new-instance launcher browser
suites pass.
- `npm run test:help` 9/9 (250 pages); UI, server and Electron
typechecks.
6.7 KiB
Desktop windows and data
Windows, tabs and the shared service
- Use New instance to open another project/home tab in the current window.
- Use native Window → New Window (
Ctrl+Shift+NorCmd+Shift+N) for a separate application window. - In Settings → Advanced, enable Focus existing window on second launch if another launch should focus the most recently used window rather than open a new one.
Project tabs, selected conversations and layout belong to a window. OpenCode sessions/messages belong to the shared native OpenCode service: another window can see the same conversation. Closing a project tab closes that project in CodeNomad, not its OpenCode sessions; reopen it to find them again. Another window displaying the same project connection also closes its tab and shows a notification; separately opened tabs of the same folder are unaffected. Closing a whole window, quitting or reloading preserves project connections for restoration; see Projects. Do not use closing windows as proof that an agent or scheduled Mission has stopped.
Preferences and startup restore
- Open Settings from the window you want to configure. Local desktop entry points focus the single native Preferences window with that opener's project/Location.
- In General → Startup, enable or disable Restore previous state.
- To forget that window's saved layout, use Clear saved state after reading its consequences.
Restore can reopen workspace/SideCar tabs and active sessions, unsent text, scroll positions, panels, window placement and zoom. It is per-window client state, not a copy of the native conversation database. Clearing it removes saved tabs, drafts and layout; it does not delete CodeNomad configuration or OpenCode conversations. Save any important unsent draft elsewhere first.
The Preferences window does not own a separate restore state: Startup targets the exact window that opened it. If that window closes or changes, unavailable/stale controls do not silently write another window's state. Open Preferences again from the intended window. Project-scoped settings likewise use the opener's Location; they stay unavailable without one.
Browser and remote settings are embedded rather than a second native Preferences owner. A native Preferences opening error is reported; it is not a reason to assume a hidden embedded settings screen was opened instead.
Explicit desktop data profiles
Without an explicit profile, packaged launches reuse the remembered profile for that configuration. If no choice is remembered, the app checks the default, dev and dev-v2 profiles for restorable work: it selects the sole candidate, asks when several exist, or uses the default when none exists. Selection does not move, merge or delete profile data. Use CODENOMAD_PROFILE to open another profile explicitly.
- For deliberate desktop isolation, set
CODENOMAD_PROFILEbefore launching the executable. - Use a name of 1–64 ASCII letters/digits, dots, underscores or hyphens, starting with a letter or digit. Names are normalized to lowercase;
defaultorstableselects the default profile. - Check Settings → Info → Data profile for a named profile. An invalid name prevents launch instead of selecting another profile.
For example, in PowerShell, before launching the desired desktop executable:
$env:CODENOMAD_PROFILE = "review"
For an independent server configuration, set CLI_CONFIG to a separate configuration file before launch as well. The default is ~/.config/codenomad/config.yaml. A profile name by itself does not change that file or the shared OpenCode service.
| Isolated by a desktop data profile | Not automatically isolated |
|---|---|
| Window/tab restore state, unsent drafts and desktop singleton/backend scope | OpenCode sessions, messages, provider credentials and execution |
| Native Chromium/WebView storage associated with that profile, subject to platform limits | CodeNomad configuration/preferences, speech keys, SideCars and extension activation when configuration is shared |
| Native preview storage within its host/profile | Files in opened projects; remote servers' data |
On macOS Tauri, scoped profiles share system WebKit storage, sign-ins and cache; do not use profile names as account-security isolation. Electron stores web data in its profile. Installed version and Update feed never select another data profile. Unpackaged development launches use the dev profile unless explicitly selected.
Delete other saved profiles
- In native Settings → General → Startup, find Other saved profiles. It appears only when other profiles are present on the machine.
- Refresh the list if needed, choose Delete…, and read the listed targets and skipped profiles.
- Confirm only after preserving any drafts/sign-ins you need. Inspect any incomplete-removal report before retrying.
Deletion removes other profiles' saved tabs, drafts, layout and owned web storage/cache/sign-ins, including listed profiles from another configuration. It preserves the open profile, OpenCode conversations and project files. Open or unknown-state profiles are skipped; close the relevant CodeNomad windows before explicitly refreshing and retrying. Unrecognized content is retained and reported rather than broadly deleted.
macOS Tauri's shared WebKit store is kept because deleting it would affect other profiles. This is not an undoable cleanup: a surviving native conversation does not restore a deleted unsent draft. Clear saved state is the smaller action when you only want to reset the current window.
Zoom and panel geometry
- Use native View → Zoom In, Zoom Out or Actual Size; keyboard/wheel input also follows host support.
- Use Left panel and Right panel at the fixed outer header corners to toggle panels. Pin/unpin drawers when that layout permits it.
- If controls no longer fit, reduce zoom or widen the window; narrow layouts move controls into menus and panels into overlays.
Main local and remote desktop windows reserve at least 390 × 600 CSS pixels, scaled by application zoom and bounded by the monitor work area. Zooming in can enlarge a window that is too small; zooming out does not shrink an already larger one. Preferences and browser-preview children have separate size rules.
Panels leave a minimum conversation width before floating. Below 420 CSS pixels of conversation width, the timeline hides and header actions use their overflow menu; the saved timeline preference is preserved. These geometry changes do not alter your prompt draft or native session. See Settings and layout and Browser previews and SideCars.