App is already running, or frozen — restart the stuck copy
What happens when you launch Omniscio while another copy is already running: normally the existing window comes to the front, and if that copy has frozen you get a one-click Restart Omniscio dialog instead of nothing at all — plus the safety rules behind it.
What it is
The short version
Omniscio only lets one copy run at a time. If you try to launch it while it's already open:
Normal case: the copy already running comes to the front and you see a small notification, "Omniscio is already running — brought the existing window to the front." Nothing new opens because nothing needs to.
Frozen case (new): if the copy already running has frozen — it's still there but has stopped responding — Omniscio now notices, and instead of doing nothing it shows you a dialog:
Omniscio is not responding Omniscio is already running but has stopped responding. You can restart it now — this closes the frozen copy and opens a fresh one. Any unsaved work in the frozen copy may be lost. [ Restart Omniscio ] [ Cancel ]
Click Restart Omniscio and it force-closes the stuck copy, waits for it to fully exit, and opens a fresh, working one. Click Cancel and the launch simply closes (the frozen copy is left as-is).
Why this exists
Before this, launching Omniscio while the running copy was frozen did nothing at all — no window, no message. It looked like the app "won't open," and the only fix was to hunt down the stuck process in Task Manager or reinstall. Now the app tells you what's wrong and offers a one-click fix. It also quietly records a diagnostic when this happens, so the problem can be investigated even though the frozen copy itself can't report anything.
And after an automatic restart, the fresh copy leaves a short, informational note in your inbox — "Omniscio recovered from a freeze" — so you have a durable, visible record that it happened. It needs no action (the app has already recovered); it's there so a one-off freeze isn't invisible and a repeating one is easy to spot.
Where to find it
There is nothing to switch on or open — this is automatic, and it happens at the moment you launch Omniscio while another copy is already running. The running copy comes to the front with a small notification, or, if it has frozen, a dialog offers Restart Omniscio and Cancel. After an automatic restart, the record of it appears in your Inbox as the "Omniscio recovered from a freeze" note.
How it behaves
The safety rules (so it never restarts the wrong thing)
Force-closing a running program is a big hammer, so Omniscio is careful:
- Won't mistake "busy" or "just starting" for "frozen". A copy that's still starting up is never treated as frozen, and a busy one only counts as frozen after about 10 minutes with no sign of life (Omniscio's internal heartbeat has gone quiet). Even then it waits 30 seconds and checks again, and confirms the process really is Omniscio, before it records anything or shows the dialog.
- Double-checks before closing anything. When you click Restart, it re-confirms the copy is still frozen (if it recovered in the meantime, it tells you so and closes nothing) and verifies the process it's about to close is genuinely Omniscio — never some unrelated program.
- Won't loop forever. If restarting doesn't help and Omniscio keeps freezing, it stops offering to restart and instead says: "Omniscio keeps freezing — please reinstall Omniscio or contact support."
- If it can't close the stuck copy (for example your security software blocks it), it tells you plainly to close it from Task Manager (or restart your computer) rather than leaving you stuck.
- The extra copy always closes itself. Whatever you choose, the copy you just launched closes on its own once its diagnostic report has gone out, or been saved to send on the next launch. After a restart it waits only a few seconds, so the fresh copy isn't held up.
- It respects your crash-email settings. Before the extra copy sends its diagnostic, it reads your saved settings (without ever changing them), so if you've turned crash emails off, none is sent. A second launch also no longer wipes the running copy's crash record, so if that copy crashes later, the next start still notices.
What this does NOT cover
If Omniscio won't open for a reason outside the app itself — a corrupted install, antivirus blocking it, a missing system component, or a graphics-driver problem — none of Omniscio's own code runs, so it can't show you anything. In that case a reinstall (or checking your antivirus/quarantine) is the right move.
For agents
Under the hood (for agents)
The single-instance gate (single-instance.ts) has a losing
(duplicate-launch) copy read the primary's heartbeat sentinel
(single-instance-liveness.ts) to classify it
HEALTHY / HUNG / UNKNOWN — read-only, never touching the primary's state. A HUNG result is written
to a durable bootstrap-log line and routed (via index.ts) to a post-whenReady recovery handler
(hung-primary-recovery.ts +
hung-primary-recovery-deps.ts) that captures a
diagnostic, shows the dialog, and — on confirm — verifies-then-force-restarts. Every outcome then ends
the duplicate itself: it waits for its crash report to send or spool, bounded by the crash email's
give-up time (a few seconds on a restart), and exits (contract I17). That recovery runs in
the dying secondary, which has no database, so it can't raise a durable inbox card there; instead the
RELAUNCHED primary raises a deduped, informational primary-hung-recovered card on its next boot
(hung-recovery-boot-alert.ts, F054) — after the DB
is open, by reading the persisted restart-state within a tight recency window. Invariants:
single-instance-liveness-contract.md.
When the lock is enforced (2026-07-23 fix). The machine single-instance lock is keyed on the
isolated-instance marker AMC_INSTANCE_ID, NOT on DATA_DIR
(single-instance-policy.ts) — so a user who
relocated their data dir with DATA_DIR (e.g. to another drive) is still their PRIMARY and keeps
single-instance protection: a second launch can't run two copies on one database. Only a
deliberately-isolated NAMED instance (E2E AMC_INSTANCE_ID=e2e, the sandbox claude-sandbox) skips
the lock and coexists (contract I10). Separately, a developer npm run dev that finds a HEALTHY
primary already running on the same data dir hands off to the in-app restart instead of stacking a
second copy — the "restart shortcut = restart" path
(dev-single-instance.js →
electron-dev.js). That hand-off is GUARDED: it fires ONLY for an
interactive human launch — an agent-initiated (AMC_SESSION_ID set) or non-interactive (no TTY)
npm run dev is DECLINED (it exits cleanly without a second copy and raises a dev-relaunch-blocked
inbox card naming the source session), so a stray agent/script npm run dev can never silently
restart the user's live app. A stale/hung sentinel or unreachable CLI server falls through to a
normal launch where the lock is the backstop; kill switch AMC_DISABLE_DEV_RELAUNCH_TAKEOVER
(contract I11).
The dev launcher and a frozen app (developers running npm run dev)
The plain version. The program that starts the app in development (npm run dev) also
restarts it when a build-config file changes on disk. It asks the app to restart politely, and if
the app cannot answer it now checks the app's heartbeat, the "I am alive" note the app writes every
5 seconds, before doing anything drastic. A fresh heartbeat means the app is just busy, so it is
left alone. A heartbeat that has gone quiet while the app's process is still there means the app is
frozen: the launcher waits, checking every 10 seconds for up to 30 minutes, asks politely again
the moment the app thaws, and never force-closes it. Only an app whose process is genuinely gone
gets cleaned up. If a restart was accepted, the pre-launch checks that run before the relaunch now
have a 15-minute limit, so a stuck check can no longer leave the app dead for the evening. Pressing
Ctrl+C while those checks are running stops them at once and the app is not relaunched — the
launcher writes down that it skipped the relaunch on your request. And every one of these decisions
is written to a log file, so an outage is never a mystery afterwards.
For agents. electron-dev.js requestConfigRestart reads
devAppLiveness (alive / frozen / gone / unknown, from
dev-single-instance.js classifyDevAppLiveness) and
waits out frozen (awaitThawOrGone, 10 s polls, 30 min cap, 'deferred' past the cap, a
required shouldAbort tied to the child); the relaunch refresh is bounded by
AMC_DEV_PREDEV_TIMEOUT_MS (default 15 min, 0 = none) and abortable (shutdown() fires the
AbortController behind refreshForRelaunch; a relaunch during shutdown is a relaunch-skipped
row); decisions go to ~/.amc/dev-crash-forensics.log through
dev-supervisor-log.js, every kind a value of its
SUPERVISOR_EVENT_KIND map.
Invariants: restart-amc-contract.md I5 /
I8(d) / I19. A launcher change takes effect only at the next top-down npm run dev — the running
launcher keeps the code it loaded at start.
Related
Sibling pages on the same machinery: crash-recovery.md covers what Omniscio does with your sessions after an unexpected exit, blank-screen-recovery-button.md covers recovering a window that comes up blank, and main-heartbeat.md documents the heartbeat the freeze classification reads.
Last verified 2026-09-26