Omniscio documentation
Browse all documentation
  1. Getting Started13
  2. Sessions & Agents115
  3. Inbox & Notifications59
  4. Projects & Tasks95
  5. Automation & Scheduling75
  6. Knowledge & Memory26
  7. AI Features60
  8. Integrations100
  9. Plugins & Marketplace33
  10. Cloud & Teams56
  11. Settings & Customization58
  12. Account & Billing28
  13. Troubleshooting84
  14. CLI & API Reference22
  15. Legal & Policies4
  16. Uncategorised22

Start a new session

Pick a project and hit **+ New Session** (or `Ctrl+T` / `N`) — Omniscio spawns a fresh `claude` CLI inside that project's folder using your active account. Sessions are per-project, persist across restarts, and you can run many at once. Nothing is billed until you send your first message.

What it is

A session is one chat with Claude Code running inside a specific project's folder — the agent can read, edit, and run code against that folder, and your back-and-forth lives in the session's transcript. You can have many sessions open across many projects at the same time. Starting a new session means: pick a project, hit the launch button (or Ctrl+T / N), and Omniscio spawns a fresh claude CLI process inside that project's folder using your active Claude account.

Omniscio also auto-launches a session for you the first time you switch to a project you've added that has none, so you can start typing without ever clicking the + button. Most built-in tool panes (like the Automation Helper) are the exception — they wait for you to tap +. Two are not: clicking Ask Omniscio or Session Search in the sidebar drops you straight into a session, and if that pane has nothing waiting for you it launches a blank one on the spot, exactly like any other project with no open session. That launch carries no prompt (in-code: a blank launch "fire[s] no paid turn"), so nothing is billed until you send something — but a session row does appear. This holds on mobile too.

A session is per-project: the folder shown next to the project's name in the sidebar becomes the session's working directory. Anything Claude does (reading files, running tests, writing patches) happens inside that folder. Sessions persist across app restarts — the conversation history, attachments, and any pending state survive a quit.

Where to find it

The small + icon at the top of the Sessions panel — the middle column in the sidebar that lists a project's sessions — is the most-used entry point. The same action is on a keyboard shortcut and in the project's own menu.

How it behaves

How to use it

  1. Pick a project. Click any project in the left Projects sidebar (the strip with the colored vertical bars). The middle column will switch to that project's session list.
  2. Click the "+" icon at the top right of the Sessions section header (above the session list, next to the count). The icon shows a Plus glyph; the tooltip reads "Launch new session" plus your keyboard shortcut. The session appears at the top of the list, becomes active, and the composer focuses so you can type your first message right away. If the session list was scrolled down — a long Needs You list can push the Live Sessions section below the fold — it scrolls to bring the new session into view, so you always see the one you just started. The session row then follows the session's real state: it reads Starting while the CLI process is still coming up, and only turns green once that process is genuinely up — never ready before it has started.
  3. Or use the keyboard shortcut. Default is Ctrl+T (or just N) — both bound to the newSession action. Works from anywhere in the app. Pressing it twice in a row does NOT create a duplicate empty session — Omniscio reuses the existing blank session if one already exists in this project, so the keyboard shortcut is safe to mash.
  4. Launch it. The + button launches a new session immediately — there is no target dropdown any more. Where the session runs is chosen on the new-session empty state (a Run location picker), and whether it is isolated in a git worktree follows the project's Isolate by default setting — Shift+click the + button to quick-launch with the opposite isolation. See Session isolation for where that copy is created, what is inside it, and how the work comes back to your project.
  5. Send your first message. The composer placeholder shows "Send your first message to begin..." while the session is in ready state (on a phone, a shorter "Your first message..." so the narrow empty box stays one line instead of wrapping the long hint to two). Type a prompt and hit Enter (or Ctrl+Enter, depending on your Submit key setting). On the very first send, Omniscio auto-attaches any files in the project's .claude/docs/ folder so the agent has your project conventions on turn one.
  6. Or pre-fill the prompt. A few entry points launch a session with an initialPrompt already queued: the Super Prompts picker (Ctrl+Shift+K, only on the auto-created ~/Claude project), recipe and automation runs, and omniscio:// deep links. The prompt sends as soon as the spawn completes — you don't need to press Enter.

Picking a tool. The in-session chooser is organized as a Harness → Provider → Model → Thinking picker: you pick the tool (the AI harness) first; under Claude Code a Provider dropdown picks the brain, then a Model within it, then a Thinking / reasoning level if that model has one — each dropdown only offers what the previous pick makes available. On the collapsed pill that first picker is labeled Harness (so it reads e.g. "Harness Claude Code"), matching the muted label style of the Model and Thinking pills beside it. (Settings still calls these your tools — "Tools in the picker", "Default tool" — so tool and harness are the same thing here.) A tool usually maps one-to-one to a provider (Codex, Gemini, Cursor, OpenCode, Pi, …), but "Claude Code" groups several: the native Claude engine plus the Anthropic-compatible vendors that ARE the Claude binary pointed at a different endpoint (DeepSeek, Kimi). So Claude Code → DeepSeek is the same harness, a different brain.

By default every session uses Claude, and the New Session button launches a Claude session in one tap. The other tools are already available: Show alternative AI providers (Settings → Accounts) is on by default, so pick the tool from inside the freshly-created session before you send the first message (see the next paragraph) — and turn that setting off if you would rather see Claude only. On desktop the launch button itself also carries a tool menu.

Customize the list, set a default, or hide the picker entirely. Settings → Accounts lets you tailor the picker to how you work:

  • Tools in the picker — a checklist of which tools appear in the chooser (Claude Code is always shown — it's the guaranteed-available engine). Hide the ones you never use to keep the list short.
  • Default tool / model / thinking — the global default a new session starts on (also settable per-project via edit-a-project.md, or straight from a fresh session. For model, thinking, and provider / harness alike: a Project or Session badge on the pill tells you at a glance when the current value isn't your plain global default, and picking something other than your current default surfaces a one-line "Save as default" banner just below the pickers — click it for a scope menu tailored to what changed (Model: Only this project · All (engine) sessions; Thinking: This model · All (engine) sessions · All (harness) sessions · Only this project · Everywhere; Provider/harness: Only this project · Everywhere — the "All …" labels name the actual engine/harness, e.g. "All Codex sessions"). Promoting to a broader scope clears any narrower per-project pin for that dimension so the new default actually takes effect.)
  • "Always use my default" — when on, the picker is hidden and every new session just uses your default. The empty session shows a one-line "This session uses your default tool & model" with a "Choose for this session" button that reveals the full picker for that one session if you ever need to override.

Once you're inside a brand-new session — on desktop or mobile — you can pick its tool/model/thinking before sending: while the session shows "Start a new session", the main panel holds the launch-config pickers (Tool picker plus Model + reasoning-effort pickers for the engines that offer them — see below). Click or tap to pick Codex, Gemini, or another enabled tool — the choice is remembered instantly and nothing actually starts up yet; it's applied in one step when you send your first message, so you can flip between tools freely. The pickers disappear once you send the first message, because the choices lock in then, and the header shows a small static provider badge instead. (If you pick something but never send, the choice is simply forgotten.) You can set a per-project default in edit-a-project.md. ("Always use my default", above, hides this whole block behind the one-tap "Choose for this session" reveal.)

On a phone, tapping the message box opens the soft keyboard, which shrinks the screen. The launch-config pickers scroll into view just above the keyboard so they stay reachable, not hidden behind it, while you type your first message.

Pick the model — and, on some engines, the reasoning effort. In those same launch-config pickers, a fresh session shows a Model picker for every engine that offers a choice, plus a second picker (Thinking on Claude, Reasoning effort on Codex) where the engine has one:

  • Claude — Model: the current lineup (Fable 5.1, Fable 5, Opus 5.5, Opus 5, Sonnet 5.5, Sonnet 5, Haiku 4.5) shows at the top; the older versions (Opus 4.8, Opus 4.7, Opus 4.6, Sonnet 4.6, Sonnet 4.5) tuck behind an "Older versions" row you expand in place — nothing is removed, every model stays pickable (and if a session is already running on an older one, the row opens expanded so you still see your pick). Plus Thinking (Auto / Low / Medium / High / Max). One exception to “nothing is removed”: a model that needs a newer Claude Code than you have installed is hidden from the list, and a single grey line takes its place naming the version it needs — e.g. “Claude Fable 5.1 needs Claude Code 2.1.251+ (you have 2.1.236)”. Nothing is lost: it reappears on its own the moment you update Claude Code (Settings → Connected Tools). It is hidden because the installed Claude Code doesn’t know that model id, so a session started on it would fail on every single turn with nothing on screen explaining why. If Omniscio can’t read your Claude Code version at all, it hides nothing.
  • Codex — Model (GPT-6.1 Sol — the default, runs on a ChatGPT-plan login / GPT-6 Astra / GPT-6 Sol / GPT-6 Luna / GPT-5.6 Sol / GPT-5.6 Terra / GPT-5.6 Luna / GPT-5.5) + Reasoning effort (Low / Medium / High / Extra High / Max / Ultra).
  • DeepSeek — Model (DeepSeek V4 Flash / V4 Pro / V4 Flash Vision — experimental, image input). Gemini — Model (3.6 Flash — the default / 3.5 Flash / 3.5 Flash-Lite / 3.1 Pro / 2.5 Flash).
  • Kimi — Model (Kimi K3 + Kimi K2.7 Code). Cursor — Model (a curated 10-model list across the Anthropic / OpenAI / Gemini / Grok families plus Cursor's own Composer and Auto; the model picker doubles as the reasoning-effort picker, since Cursor bakes effort into the model id — see cursor-provider.md).
  • OpenCode — Model (Claude Sonnet 4.5, plus GPT-4o / Kimi K2 / DeepSeek via OpenRouter). Pi — Model (Claude Sonnet 4.5 / GPT-4o / Gemini 2.5 Pro / Kimi K2 — Pi is model-agnostic and runs whichever you've configured a key for). Both now take a per-session model pick (your choice wins over the global OpenCode/Pi model setting); previously they only followed that one global setting.
  • Anti-Gravity and Hermes — no model picker (each manages its own model / runs a model-agnostic local CLI), so the block shows just the tool chooser. Hermes is a first-class pickable tool, so it appears in the Tool chooser alongside the others.

Under Claude Code, the brains it spans — Claude / DeepSeek / Kimi / GLM / MiniMax — are listed in a separate Provider dropdown, each shown with its brand icon. The Model dropdown then shows only the chosen provider's models (a flat list — no company headings, since it's single-provider). Resellers (DeepInfra, RunInfra, InferX) are never listed as a provider and their copies of these models never appear; which company serves a GLM, DeepSeek, Kimi or MiniMax model, and who pays, is that family's supply list. See model-vendors.md.

They behave exactly like the provider chooser: editable only before your first message (each pick is staged locally and applied when you send), then locked in. The pill names the model the session will actually use — e.g. "Gemini 3.6 Flash", "Opus 4.8" — whether that's the inherited default or a pick of your own. To see whether it's the default, open the dropdown: the "Use default (…)" row is highlighted and marked Current — so "default" lives in the menu, not as clutter on the collapsed pill. Click to pick a model for this session, or Use default to clear the override and inherit again. The dropdown rows are clean single-tap picks (just like the Thinking menu beside it). To make a model your standing default, pick it for this session — a one-line "Save as default" banner appears below the pickers (only while your pick differs from what the session would otherwise inherit), offering Only this project (new sessions in this project) and All (engine) sessions (new sessions of that engine everywhere); a model belongs to one engine, so those are its two scopes, above the engine's built-in floor. There's no separate "clear without replacing" action in the session picker — to revert a project back to inheriting the engine-wide default, clear its default model field in edit-a-project.md instead. (On the built-in virtual projects, which can't carry their own default, only the engine-wide row shows.) After the first message a session you customized keeps a small read-only badge in the header — the engine's logo plus the model name (e.g. the Claude mark + "Claude Fable 5"; for non-Claude engines the provider badge already carries the logo, so the pill shows just the model name — the word "Model" is no longer shown) — so you can see what it's running, while a session on the plain default shows nothing extra. For Claude the precedence is this session's pick → the project's default → your global default (Settings → Accounts sets the global default, and edit-a-project.md sets a per-project default); other engines resolve this session's pick → that engine's own default ("Make it my default" writes that per-engine default; Gemini/Codex/Cursor ship with a sensible one seeded so the picker always names a model). Each engine reads only its own default — non-Claude sessions never inherit Claude's model list.

Thinking / reasoning effort inherits the same way — and can default per model. The Thinking picker (Claude) / Reasoning-effort picker (Codex) resolves a default just like the model does: this session's pick → the project's default → the per-model default → your single global Thinking Level (Codex has no single global, so its per-model default is the lowest layer). Thinking's same "Save as default" banner covers the fullest set of scopes when it appears: This model sets the level for that model everywhere (so bumping Opus to Max never touches Haiku); All (engine) sessions / All (harness) sessions set it whenever you use that engine / harness (named for the actual one, e.g. "All Codex sessions" / "All Claude Code sessions"); Only this project for this project only; Everywhere is Claude's single flat level. Promoting to Only this project or broader clears any narrower shadow so the new default takes effect right away. (On a single-engine tool like Codex, "This harness" is dropped — it would duplicate "This provider" — and Codex has no flat "Everywhere" thinking.) You can still set per-model defaults in bulk in Settings → Session → Per-model thinking level so, e.g., Opus starts on Max and Haiku on Low without you setting it each time — a level a model's engine doesn't support is validated out, so it never reaches a session. Full behavior: per-model-thinking-level.md.

Pick the MCP servers — at launch. That same block also carries an "MCP servers" button next to the model/thinking pickers. Click it to choose which MCP servers this session gets (Default / On / Off per server) before you send the first message — the choice applies on the session's first launch. It opens the same editor as the session's ⋯ menu → MCP servers, just up front. The button appears on real projects only (it's hidden on virtual/inbox projects, where MCP doesn't apply). Full behavior: mcp-servers.md.

What happens if no account exists yet: the spawn returns an error and a system message in the chat says you need to add a Claude account before sessions can run. Open Settings → Accounts and use Log In with Anthropic to add one. See add-a-claude-account.md.

What happens when every account is at its rate limit: the session row shows the amber "Needs You" / "Rate Limited" sub-state, the chat surfaces a banner with the absolute reset time, and a sidebar-wide "All accounts are at their usage limit" banner appears at the top of the Sessions panel. Omniscio auto-resumes when the first account regains capacity, so you can usually leave the session alone. See account-pool.md and session-stuck-in-needs-you.md.

What happens if the project's folder no longer exists on disk: the session lands in error and a red "Project folder is missing" banner offers a "Recreate Folder" button. See project-folder-missing.md.

What happens if a launch fails: an error toast appears carrying a Try again button that re-runs the same launch for you. The toast names the reason, so if the cause is something you can fix directly (no account yet, a folder that moved) do that first and then hit Try again; many other launch failures are simply transient and clear on a second try. The button is offered on both launch paths — the + button and Ctrl+T — because they run the same launch and the same error handling.

What happens if the app closes while a new session is starting: the request survives. Once Omniscio has accepted your New Session click, closing or losing the app before the process came up does not lose it — on the next start Omniscio brings that session up again, with the opening message you had already given it if there was one, or as an empty session if there wasn't. It is never turned into a broken/error session while it waits, and it is never resumed with a generic "please continue" in place of what you asked for. A request that has not started is kept until it starts or you cancel it — it is not dropped for being old. See durable-new-session-request-contract.md.

Which hub a session starts in when you don’t pick one

Most entry points use the hub you are already in, and the Start session button on an alert resolves a smarter one — the repo the alert names, then your Start alert sessions in setting, then an automatic Omniscio checkout, and ~/Claude last. That resolution, and the dialogs that deliberately keep the plain Claude default, have their own page: alert-session-hub.md.

How it works

The "+" button lives in SessionsSidebar.tsx (look for launchTriggerRef and the data-tour="launch-session-button" attribute). It calls handleLaunchSession(), which first tries tryFastNewSession() (the same instant pre-warmed path Ctrl+T uses) and, on a miss or a specialised launch (SSH remote, chosen provider, forced isolation, OpenClaw), falls back to launchSession() on the renderer's session-store.ts, which invokes the SESSION_LAUNCH IPC channel. The keyboard shortcut path runs through useKeyboardShortcuts.ts, which dispatches the newSession action to handleNewSession in session-actions.ts — same tryFastNewSession first, same launchSession fallback, same error handling and retry, so toasts are identical between Ctrl+T and the + button. Default bindings live in keybindings.ts.

The IPC handler is in session-handlers.ts (IPC.SESSION_LAUNCH). For the regular Claude provider, it first calls findBlankSession() from queries-sessions.ts — if there's already a blank session in this project (zero non-system messages, no draft text, no draft images, no scheduled response, not in a recipe lane), Omniscio navigates to that session instead of creating a duplicate. Otherwise it falls into session-create.ts createSessionWithPrompt(), which: increments the project's session counter, writes the session row, optionally creates a git worktree (isolation), and calls processManager.launch() from process-manager.ts.

Three guarantees ride along with every launch. A failed launch is retryable in place: both launch paths attach a Try again toast action that re-runs the same launch — handleLaunchSession in SessionsSidebar.tsx for the + button, handleNewSession in session-actions.ts for Ctrl+T — with the humanized reason kept in the copy. An accepted request cannot be lost: the instant the row exists, session-launch-pending-intent.ts records a launch-pending intent on the existing recovery rail and clears it in the spawn tail's finally; if the process dies inside that window the row is left behind, and on the next start session-recovery-rearm.ts drives it again — with the user's own last message when there is one, and as an empty start when there is not (every other intent kind is still dropped when it has nothing to replay). The sidebar tells the truth the whole time: the optimistic blank row mints status: 'starting' with no CLI session id (session-store.ts, buildOptimisticBlankSession), and the SESSION_LAUNCHED push now carries the row's real status instead of a hard-coded ready, so a session with no process is never shown as ready. Invariants: durable-new-session-request-contract.md and session-start-visibility-contract.md.

Why it feels instant (the pre-warm). When you open a project, Omniscio quietly pre-warms one blank ready session for it in the background (a debounced SESSION_ENSURE_BLANK, auto-numbered "Session N" like any new session). So when you then hit + / Ctrl+T — or tap New Session on a phone — tryInstantNewSession() flips straight to that already-ready session with zero IPC, instead of waiting on the full spawn above (worktree + CLI process, which over a phone's tunnel is several seconds). This runs on desktop and mobile: a phone is a thin client of the same desktop main process, so the pre-warm does identical work, and skipping it on mobile (a bug fixed 2026-06-17) was what made mobile "New Session" feel slow. On the rare cold tap before a warm blank exists, the mobile button navigates to the session view immediately and then reveals the real, typable composer the moment the new session activates — the SESSION_LAUNCHED push activates the row before the ~7-8s worktree build finishes, so you start typing right away while the spawn completes in the background, instead of staring at a non-typable "Starting session…" spinner for the whole spawn. If the launch request later times out over the tunnel but the session was already created, you stay in that live session rather than getting bounced back — which is what finally makes the inbox-group + (always a cold tap, since those projects are never pre-warmed) as reliable as New Session. Gated by the Pre-load new sessions setting (Settings → Performance, on by default). Mechanism + invariants: keep-alive-pool-contract.md.

The launch-config pickers (shown under the "Start a new session" title) reuse the same ChangeProviderButton + SessionModelThinkingChips, on desktop AND mobile. SessionPanel.tsx computes one bodyHostsStartConfig predicate — true on a fresh generic empty state with at least one control to show, keyed on zero NON-system messages (every new session is created with a "Session ready" system row, so the gate counts non-system messages — mirroring the backend sessionHasNonSystemMessages rule — never total messages.length; counting total was the 2026-06-07 regression that stranded the pickers in the header on every real new session) and not the bootstrap-seed / history-loading / Ask Omniscio / Search / first-mission sub-branches — from the pure helpers getEmptyStateProvider() (empty-state-provider.ts, which gates the chooser on the Show alternative AI providers toggle + isSwitchableProvider() — generalized from the old hardcoded claude/codex/gemini check, so deepseek/kimi/cursor/opencode/pi sessions also get a chooser) and resolveEmptyStateVariant() (empty-state-variant.ts). That single predicate drives BOTH the body render and the header yield: when the body hosts the pickers, the header's chooser (getHeaderChooserProvider, now gated on emptyStateActive) and its Model/Thinking chips are suppressed, so the pickers appear in exactly one place — never doubled, never vanished. The header keeps its pickers only as the fallback for the sub-branches where the body block does NOT render — a non-generic variant, history-loading, or a bootstrap-seed bubble; a plain blank session (only a "Session ready" system row) hosts them in the body. After the first message the header shows a static ProviderBadge + any read-only override badge; that static badge renders right after the session name on both desktop and mobile (before the snooze/recipe chips), default-inclusive so every session shows its engine mark (Claude in brand orange included), so a crowded screen can't shove it under the right-side toolbar (see mobile-in-session-provider-chooser-contract.md § "Static header badge"). Switching a session that turns out to already have history is rejected by the handler-side sessionHasNonSystemMessages guard, so the gate is a UI convenience, not the source of truth.

Because that block lives in the scrollable body, the mobile soft keyboard (which shrinks the layout viewport via interactive-widget=resizes-content) would otherwise clip it below the collapsed message area. SessionEmptyState.tsx listens for the keyboard to settle (a debounced visualViewport resize) and scrolls the body to its bottom — where the pickers sit — keeping them visible above the keyboard without relocating them out of the body (so the one-place invariant holds). Mobile-only; desktop is untouched.

Picking a provider / model / thinking does NOT hit the backend on tap — each pick is staged locally in pending-start-config-store.ts (key presence marks a field as staged; null = explicit "use default"). The staged config is applied in ONE step at first-message submit by applyPendingStartConfig (apply-pending-start-config.ts), called at the top of BOTH sendResponse and sendResponseAndNavigate so a first message sent any way (composer, voice) picks it up. SESSION_CHANGE_PROVIDER is therefore DB-only now (no eager terminate/relaunch — that would churn an engine the user may never use and double-spawn at submit); the first message's spawn reads the persisted provider/model/thinking fresh and starts the chosen engine exactly once. Invariants: start-config-staging-contract.md.

The Tool grouping is renderer-only presentation: picker-tools.ts derives the tool list from the registry's runtimeKind (Claude Code spans the claude + anthropic-compat providers, so a future compat engine folds in automatically), and the customize-list (pickerToolIds) / master toggle filter it. The backend stays per-provider — switching brains is an explicit Provider pick (which stages the provider via setProvider), and the Model dropdown then lists only that provider's models, so a Model pick is always same-provider. (The store keeps a cross-provider setProviderModel for other surfaces, but the in-session Model dropdown no longer reaches it.) The one exception is a session whose engine is a reseller host (an older DeepInfra session): its Model dropdown draws the cross-provider, deduped list and a pick under a DIFFERENT maker stages provider + model together via setProviderModel — see model-vendors.md. "Always use my default" (alwaysUseDefaultStartConfig) hides the block via a single hideStartConfig predicate in SessionPanel.tsx that suppresses it in BOTH the body AND the header (a body-only suppression would just bounce the picker up to the header), with a per-session revealStartConfigOnce flag behind the "Choose for this session" button that resets on session change.

The named default + "Save as default" banner route through one helper, provider-default-model.ts: getProviderGlobalDefaultModel resolves each engine's editable global default (claude → defaultModel; OpenCode/Pi → opencodeModel / piModel; every other engine → the providerDefaultModels map, falling back to the registry pin in provider-models.ts, validated against the engine's selectable list), and the build*Patch writers persist a promotion to the SAME key the read + the spawn (resolveSpawnModel) use — so the picker label can never disagree with what launches. Model, thinking, and provider/harness defaults are ALL promoted through one banner, SetDefaultHint, rendered below the pickers by SessionEmptyState.tsx and by the mobile create-on-send composer too (StartConfigPicker value mode with showDefaultHints, desktop parity). Each dimension is its own hook (useModelDefaultScopes / useThinkingDefaultScopes / useProviderDefaultScopes) that returns nothing while the current pick already matches the resolved default, so the banner appears only once you've actually changed something; when it does, it lists every changed dimension on one line with ONE SetDefaultScopeMenu offering that dimension's scopes: Model → Only this project · All (engine) sessions (a model is engine-bound), over the engine's built-in floor; Thinking → This model · All (engine) sessions · All (harness) sessions (multi-provider tools only) · Only this project · Everywhere (Claude's flat defaultThinkingLevel only); Provider/harness → Only this project · Everywhere. The per-scope writers live beside their reads: model → buildProviderDefaultModelPatch / buildProjectDefaultModelPatch; provider → settings.defaultProvider / buildProjectDefaultProviderPatch; thinking → buildModelDefaultThinkingPatch (per-model) / buildProviderDefaultThinkingPatch / buildHarnessDefaultThinkingPatch / buildProjectDefaultThinkingPatch / the flat defaultThinkingLevel. The three thinking conditional layers fold in ONE place — resolveModelGlobalThinking (per-model → per-provider → per-harness → flat) — read by the Claude spawn, the Codex spawn, and the chip, so the pill can't drift from what launches. Promoting a MODEL or THINKING pick to a global-tier scope also clears the per-project shadow (buildClearProjectModelOverridesPatch / buildClearProjectThinkingOverridesPatch, merged into the same atomic write) so the broader default actually takes effect instead of staying silently shadowed — provider is the deliberate exception (a per-project engine choice is intentional, so promoting it never wipes a project pin). The menu tags the winning scope "In effect" (never a checkmark — a row whose action is "save here" must never look like it's already saved there) and shows each scope's currentValueLabel so you can see what it's set to before you overwrite it. There is no separate "clear without replacing" action in this banner — reverting a project's model/thinking pin back to inheriting the engine default means clearing that field in edit-a-project.md instead. Each chip also shows a source badge (sourceBadgeFor — amber "Project" / indigo "Session") whenever its value isn't the plain global default, so the "why did it revert to Luna" shadow is visible at a glance. Every write awaits the save and only toasts success once a store re-read confirms it took, so a failed save never shows a false confirmation (see ipc-error-surfacing-contract.md). Gemini/Codex/Cursor are seeded in the registry pin so the picker names a model on day one. Invariant: start-config-staging-contract.md model-pill-names-the-default/provider-chip-is-a-provider-picker/new-session-provider-precedence (provider) + set-default-hint-is-the-one-surface (SetDefaultHint is the one surface for a Model/Thinking default — the per-level editor superseded-per-level-editor introduced is retired).

The actual spawn is spawnLocalStreamJson() — same module. It calls pickActiveAccount() (synchronous, cache-only) which delegates to the account pool's tiered selection (pinned → primary capacity → extra-capacity → API key, gated by allowApiKeySessionSpawn). The chosen account's credentials get injected into the spawned CLI's environment as CLAUDE_CODE_OAUTH_TOKEN (login) or ANTHROPIC_API_KEY (api key). The CLI is spawned with --output-format stream-json --input-format stream-json --verbose --permission-prompt-tool stdio, with cwd set to the project's folder (or the worktree path if isolated). On every subsequent message in the same session, Omniscio re-spawns with --resume <cliSessionId> so multi-turn context is preserved. See process-management.md for the full lifecycle.

Related

  • add-a-project.md — sessions live inside a project; add one if you don't have any yet
  • alert-session-hub.md — which hub the Start session button on an alert picks, and why it is the one dialog that does not use your current hub
  • add-a-claude-account.md — every spawn needs an account; this is where you add yours
  • mobile-in-session-provider-chooser-contract.md — the invariant behind "one provider chooser on mobile, not two" (header chooser yields to the centred switcher)
  • start-config-staging-contract.md — why picking a provider/model/thinking is instant: picks are staged locally and applied at first-message submit (no engine spin-up on tap)
  • keep-alive-pool-contract.md — why launching a session is instant (the pre-warmed blank), on desktop AND mobile
  • account-pool.md — when you have multiple accounts, the pool decides which one this session uses
  • send-a-message.md — the next thing you do after the session is up
  • attach-a-file.md — drop a file into the composer alongside your first message
  • use-super-prompts.md — Ctrl+Shift+K launches a session pre-filled with a curated starter prompt
  • project-folder-missing.md — what to do if the spawn fails because the folder moved
  • durable-new-session-request-contract.md — why a session you asked for survives closing the app, and comes back with your own opening message
  • session-start-visibility-contract.md — why the sidebar never shows a session as ready before its process is actually up

Last verified 2026-10-06