---
title: Keep Omniscio resident in memory (Windows working-set floor)
---

# Keep Omniscio resident in memory (Windows working-set floor)

## What it is

A Windows-only **Settings → Performance** toggle that keeps Omniscio's own memory resident in physical RAM so its pages can't be trimmed out to the pagefile when the machine is starved. It is the **memory twin** of the CPU-side [Boost Omniscio interface priority](amc-priority-boost.md): where that keeps Omniscio _scheduled_ under CPU contention, this keeps Omniscio _resident_ under memory pressure.

> **The primary mechanism is the resident PIN, not the floor this page describes (updated 2026-06-28).** The `keepAmcResidentInMemory` toggle is now **default-ON**, and its PRIMARY action is a true `VirtualLock` page-**pin** of the main process's DB + hot heap — needing **no admin** (only the working-set min raised first), because a hard working-set minimum alone is a HINT Windows trims under real pressure (measured: a 600 MB floor trimmed to 1 MB). The pin is sized from a STABLE basis (DB mapped footprint + a fixed heap allowance, NOT the trimmable live working set — a 2026-07-05 fix, after it was found unwinding from ~3.7 GB→~1.2 GB under load) so it holds through the swarm storm. SSOT: [resident-lock.ts](../../src/main/process/resident-lock.ts) + the resident-pin contract. The working-set **floor** documented below is now the **FALLBACK** — applied only where the pin can't run (non-Windows / < 13 GB RAM / FFI unavailable). The floor details below are still accurate for that fallback; a fuller rewrite to lead with the pin is a tracked follow-up.

> **Escalation when the pin is DEFEATED — "Serve the database from private memory" (2026-07-14).** `VirtualLock` can hold private (heap) pages but CANNOT hold a **file-backed memory-map** against Windows' cache-manager trim under sustained disk load — so on a swarm-busy machine the pin is repeatedly DEFEATED: the database's ~2 GB file-mapped window keeps getting evicted despite the lock, hard-faulting the main thread back off the busy disk (the whole-app **STARVED** freeze). The opt-in **Settings → Performance → "Serve the database from private memory (Windows only)"** toggle (`keepDbInPrivateCache`, **default OFF**, takes effect on the next restart) fixes this at the source: it opens the database with the file-mapped window OFF (`mmap_size=0`) and a large **private** page cache instead, so the hot database lives in committed heap the pin CAN hold. Trade-off: a cache miss falls to a synchronous read from disk — bounded, since the cache is sized to hold the whole database with headroom. Fully reversible: turn it off and restart. SSOT: the resident-pin contract (R9).

### The problem it solves

When many Claude CLI sessions run at once, total committed memory climbs and Windows starts trimming working sets — evicting cold pages out to the pagefile to free physical RAM. Omniscio's own processes are fair game: if Omniscio has been in the background (you were in your IDE or browser), Windows will happily page out its renderer's heap. When you `Alt-Tab` back, Omniscio has to fault all those pages back in from disk — the window paints stale, scrolling stutters, the first click lags. That is not slow code; it is Omniscio's memory having been demoted to disk and now crawling back.

Omniscio already pushes _the other direction_ on the session children — [session working-set trimming](session-memory-paging.md) actively evicts idle Claude CLI children toward the pagefile to keep headroom. This toggle is the counterpart for Omniscio itself: hold a floor of Omniscio's own pages resident so the window stays instant even when the box is under memory pressure.

## Where to find it

**Settings → Performance** → **Keep Omniscio resident in memory (Windows only)**. Off by default, reapplies live without a restart, hidden entirely on macOS / Linux.

## How it behaves

### What the toggle does

When on, Omniscio sets a **hard working-set minimum** on every one of its own Electron processes — main, renderer, GPU, utility, plus any helper renderer Electron spawns later — via Win32 `SetProcessWorkingSetSizeEx` with the `QUOTA_LIMITS_HARDWS_MIN_ENABLE` flag. A _hard_ minimum is one Windows actually honors: it will not trim that process below the floor even under memory pressure. The companion `QUOTA_LIMITS_HARDWS_MAX_DISABLE` flag is set at the same time, so Omniscio only ever establishes a floor — it never caps its own working set.

The floor is **128 MB per process**. Across Omniscio's ~5 Electron processes that reserves roughly 0.5–0.75 GB of resident headroom — enough to keep each process's hot pages (the renderer heap, the main event loop, the V8 code) in RAM without hoarding memory the rest of the system needs.

Behaviour details:

- **Rides on a privilege Omniscio already holds — no admin needed.** Setting a working-set minimum requires `SeIncreaseWorkingSetPrivilege`, which Omniscio already enables for its existing working-set features ([win32-privileges.ts](../../src/main/process/win32-privileges.ts)). This floor is only that working-set minimum — a strong hint Windows honors, NOT an unbreakable pin. (True page-locking is the resident **pin** described in the note above: `VirtualLock`, which — contrary to a common misconception — needs **no** admin either, only the raised working-set min for quota; the admin-gated `SeLockMemoryPrivilege` is a _different_ API that Omniscio does not use.)
- **Self-verifying (the anti-silent-no-op guard).** Right after Omniscio sets its own floor, it reads the value back from Windows (`GetProcessWorkingSetSizeEx`) and logs a loud `[ResidentFloor]` warning if the floor did not actually take. This exists because a sibling memory feature once failed a privilege check and silently did nothing in production for months — the read-back makes that failure mode loud instead of invisible.
- **Idempotent + 30s refresh.** Flipping it on once is enough; a 30s interval re-applies the floor to Omniscio's main process (cheap) and catches any newly-spawned Electron child. The refresh only ever touches Omniscio's _freshly-enumerated current_ processes, so it can never accidentally pin an unrelated app that reused an old process id.
- **Clean turn-off.** Disabling sweeps the floor off the union of every process Omniscio floored AND every Omniscio process currently alive — so a child that spawned between refresh ticks cannot be left with a lingering floor.
- **Non-fatal failure mode.** Any `OpenProcess` / `SetProcessWorkingSetSizeEx` failure logs `[ResidentFloor] ...` and degrades to a no-op; Omniscio continues normally.
- **No-op on macOS / Linux.** `process.platform !== 'win32'` short-circuits before any kernel32 work, and the toggle is hidden in Settings on non-Windows.
- **Not touched by the session governors.** This floors Omniscio's OWN processes; it has nothing to do with the Claude CLI children's Job Object. The CPU-Burst window (which lifts the session limiters) deliberately leaves the floor in place — keeping Omniscio resident is wanted during a burst, not suspended.

### The honest trade-off

The reserved RAM is RAM the background sessions cannot use. Under genuine memory exhaustion that is an intentional choice — favour a responsive Omniscio window over a little extra memory for background turns — which is exactly why it is **opt-in and off by default**. It keeps a _floor_ resident; it does not lock the whole app in RAM, and Windows can still page beyond the floor. If you run 1–3 sessions you will never see the symptom it fixes; it is discoverable for the user who reports "Omniscio feels sluggish when I come back to it after a heavy run."

### Why these specific defaults

- **Off by default.** Situational — it trades a slice of RAM for window responsiveness under pressure, which most users do not need.
- **128 MB per process.** Big enough to keep each Electron process's hot pages resident, small enough that ×5 processes stays well under ~1 GB. A tunable constant, not a user-facing knob.
- **A hard floor, not a soft one.** A _soft_ `SetProcessWorkingSetSize` minimum is only an advisory hint Windows ignores under real pressure — a placebo for this feature's whole purpose. The hard-minimum flag is the version Windows actually honors, and it still needs no admin rights.

## For agents

### How this is verified

- **Pure-helper unit tests**: [tests/unit/process/resident-floor.test.ts](../../tests/unit/process/resident-floor.test.ts) — 22 tests covering the hard-min / max-disable flag table, the floor-size bounds math, the read-back "is it honored" predicate (including the historical silent-no-op case where the min flag is absent), the recycled-pid reconcile under churn, and the disable live-sweep union. The Win32 FFI path is left unmocked by design (it cannot be exercised without a real Windows kernel; see the contract).
- **Runtime self-check**: the read-back-and-warn described above is the field guard — a green unit run proves the logic, the self-check proves the OS actually honoured it on the user's machine.
- **Manual smoke** (Windows): enable the toggle, open Task Manager → Details → add the "Working set (memory)" column, and confirm Omniscio's processes hold at or above the floor while the box is under memory pressure from many sessions.

### Implementation pointers

- [src/main/process/resident-floor.ts](../../src/main/process/resident-floor.ts) — `applyAmcResidentFloor(settings)`. Win32 `SetProcessWorkingSetSizeEx` (hard-min | max-disable) on self + every Electron child via `app.getAppMetrics()`, with a `GetProcessWorkingSetSizeEx` read-back. 30s refresh catches new children; disable sweeps tracked ∪ live. Cross-platform shim no-ops off Windows.
- [src/main/process/win32-privileges.ts](../../src/main/process/win32-privileges.ts) — enables `SeIncreaseWorkingSetPrivilege` (shared with the existing working-set features).
- [src/main/index.ts](../../src/main/index.ts) — applies the floor at startup, right beside the priority-boost call.
- [src/main/services/settings-apply.ts](../../src/main/services/settings-apply.ts) — re-applies it live when the `keepAmcResidentInMemory` setting changes.
- [src/renderer/src/features/settings/PerformanceSettings-definitions.tsx](../../src/renderer/src/features/settings/sections/performance/PerformanceSettings-definitions.tsx) — the `keep-amc-resident-in-memory` toggle definition, listed in `WINDOWS_ONLY_PERFORMANCE_IDS` so it hides on macOS / Linux.
- Behavior contract: [resident-floor-contract.md](../../.claude/memory/contracts/resident-floor-contract.md).

## Related

- [Boost Omniscio interface priority + adaptive E-core delegation](amc-priority-boost.md) — the CPU-side siblings. Those keep Omniscio _scheduled_ under CPU contention; this keeps Omniscio _resident_ under memory pressure. Same Settings → Performance section, same Omniscio-self / Windows-only / off-by-default pattern.
- [Session memory paging (working-set trimming)](session-memory-paging.md) — the counterpart that pushes the _session children's_ idle pages out to the pagefile to free RAM. This toggle holds Omniscio's own pages in; that one pushes the children's out.
- [Session CPU cap](session-cpu-cap.md) — the session-side CPU limiter that started this family of performance controls.
