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

Mandatory Claude Extensions (now all optional, and no longer installed at setup)

How Omniscio used to force-install the extensions it depended on during first-run setup, and why nothing is force-installed any more. It covers what Setup v2 installs instead (CLI tools only), the launch-time banner that survives but stays quiet, and the one-time offer existing users get to drop the old plugin in favour of the built-in pipeline.

What it is

Update (2026-07-29): Superpowers is now OPTIONAL too — NO extension is force-installed anymore. Omniscio ships its own built-in Dev Pipeline (plan → build → verify → ready-to-merge), so the Superpowers plugin is no longer needed as a hard dependency. Its registry entry flipped to required: false (src/shared/extension-types.ts), which — exactly like the 2026-06-22 Playwright change — drops it from onboarding's force-install AND retires the launch-time nag banner (the banner lists required-missing extensions only, and there are now none). Existing users who already installed Superpowers get a one-time, dismissible inbox card offering to uninstall it and adopt Dev Pipeline instead — raised at most once ever (stamped in settings.superpowersMigrationNudgedAt), with a desktop-only Remove Superpowers button behind a confirm dialog that calls the new EXTENSIONS_UNINSTALL IPC. See "Superpowers migration nudge" below. Net effect: EXTENSION_DEFINITIONS still lists both extensions, but BOTH are required: false, so onboarding's "Install Missing Tools" and the launch banner act on an empty required set. Treat the "required extension" language in the sections below as historical for BOTH entries.

Update (2026-06-22): Playwright MCP is now OPTIONAL, not required. A redesign (commit 1f88b21992) turned Playwright MCP into a bundled, composed per-session built-in that is off by default (settings.playwrightMcpEnabled) and enabled on demand via Settings → MCP, per-project, or per-session — it no longer auto-registers a mcpServers.playwright entry in ~/.claude.json. Its registry entry is now required: false (commit a245b9ae41), so the launch banner and onboarding no longer list Playwright; they act on genuinely-required missing extensions only. The sections below still describe Playwright's original always-required, ~/.claude.json-registered design — treat Playwright's "required"/registration details as historical. Background: mandatory-claude-extensions-postmortem.md.

Beyond the CLI binaries listed in the Tools view (claude-code, codex, gh, ffmpeg, tailscale, …), Omniscio also depends on two Claude Code extensions that aren't CLIs at all — they're features registered inside Claude Code's own configuration.

Because they're not binaries, they don't fit the existing toolchain pipeline; they get a parallel installer, a parallel onboarding row, and a launch-time nudge banner for users who already finished onboarding before the extensions feature shipped.

The two required extensions are:

  1. Playwright MCP — a Model Context Protocol server (a way for Claude to talk to outside services like a browser) that gives agents a controllable Chromium browser. Registered in Claude Code's ~/.claude.json under mcpServers as playwright, with an npx @playwright/mcp@latest command. Install also runs npx playwright install chrome to fetch the ~170 MB Chromium binary so sessions don't pay that cost on first use. Used by the agent-browser, browser-use, and other browser-automation skills.
  2. Superpowers — a Claude Code plugin loaded from the obra/superpowers-marketplace repository. Provides eleven foundational skills — brainstorming, writing-plans, executing-plans, subagent-driven-development, test-driven-development, systematic-debugging, verification-before-completion, using-git-worktrees, requesting-code-review, receiving-code-review, writing-skills, using-superpowers, dispatching-parallel-agents, finishing-a-development-branch — that Omniscio's recipes and routine prompts assume are present. Registered in Claude Code's plugin storage under a key like superpowers@superpowers-marketplace. Where that record lives changed between Claude Code versions: legacy installs (Claude Code v1.x) wrote enabledPlugins: { "superpowers@…": true } into ~/.claude.json; current installs (Claude Code v2.x) write a per-plugin install record into ~/.claude/plugins/installed_plugins.json instead. Omniscio's probe reads both — see "Why two sources for the Superpowers probe" below.

Why a separate concept from "tools". A tool in Omniscio is a CLI binary on $PATH (e.g. the claude binary, git.exe). Probing means running <tool> --version; installing means npm install -g, winget, brew, or a direct download. An extension is a record inside Claude Code's JSON config that Claude Code itself reads — installing means claude mcp add … or claude plugin install …, and "is it installed?" means "does the right key exist in ~/.claude.json?" Mixing them into one pipeline would force every probe and install function to know about both shapes, so they live in separate EXTENSION_DEFINITIONS / TOOL_DEFINITIONS tables. This is why the Tools view and Settings → Connected Tools don't list these two.

Tailscale, by contrast, is a tool, not an extension — a system binary on $PATH — so it lives in TOOL_DEFINITIONS, appears in the Tools view, and is installed by the regular toolchain pipeline (winget on Windows, brew on macOS). It is not part of this extensions feature.

Where to find it

The onboarding step appears during first-run setup. The one-time offer to existing users arrives as a dismissible inbox card, and the extensions themselves are listed under Settings → Extensions.

How it behaves

How to use it

First-time users (first-run setup)

The extensions step is RETIRED — first-run no longer installs, probes or mentions either extension. Setup v2 (the Cinematic Cascade, the one canonical first-run flow) has an Install the essentials step, and it installs only the required CLI tools: Claude Code and Git, both blocking, plus browser automation, which is non-blocking because it is a large download. No extension row appears there, and no extensions phase follows it.

What replaced it is the composition described at the top of this page: Playwright MCP became a bundled, composed per-session built-in instead of an installed MCP server, and Superpowers was dropped in favour of Omniscio's own built-in Dev Pipeline. With required: false on both (src/shared/extension-types.ts), the launch banner has nothing to report either — it only lists genuinely-required missing extensions, and there are currently none.

You can still see and manage both under Settings → Extensions, and install them by hand if you want them.

Existing users (post-onboarding banner)

Users who finished onboarding before this feature shipped see a dismissible amber banner at the top of the app on every launch when any required extension is missing (rendered by src/renderer/src/features/extensions/ExtensionsBanner.tsx):

Omniscio needs Superpowers. Install for full functionality.

(Before the 2026-06-22 fix the banner also listed Playwright MCP; now that Playwright is optional, the banner lists only genuinely-required missing extensions, so Playwright never appears. The example above shows the post-fix banner when only Superpowers is missing.)

Two buttons:

  • Install — runs the install-all flow (EXTENSIONS_INSTALL_ALL) for the missing required set. While running, the button shows "Installing…" and is disabled. On success the banner disappears. On failure a toast surfaces the per-extension error ("playwright-mcp: Cleanup failed after partial install: …").
  • Later — snoozes the banner for 24 hours (SNOOZE_MS in src/renderer/src/hooks/useExtensionsLaunchCheck.ts). It won't reappear until the snooze expires. Snooze state persists across app restarts.

The banner only mounts after onboarding is complete (settings.onboardingCompleted === true). That gate was added as a double-prompt fix while the retired wizard step ran the same install UI; the step is gone now, and the gate is kept so the banner counts as a post-onboarding surface. In practice it is currently quiet: with required: false on both extensions, the missing-required set is empty, so the banner has nothing to show. The gate and the surface remain for whenever a genuinely required extension is added.

Superpowers migration nudge (un-forcing Superpowers)

When Superpowers was un-forced (2026-07-29), existing users who already installed it needed a graceful off-ramp rather than a silent config change. That off-ramp is a one-time, dismissible inbox card, deliberately built on the existing inbox-alert primitive + the AlertInboxViewer "carve-out button" pattern (the same shape the cache-cap, safe-catch-up, and quick-reply cards use) — not a full bloat-style integration, so it needs no new DB table, migration, store, or approval pane.

  • Producer — src/main/app/superpowers-migration-nudge.ts, wired into the StartupTask registry (src/main/startup/registry.ts) as a leaf task (no dependsOn; startup tasks run well after db-init, so the alert's SQLite write always lands). It mirrors src/main/app/hotkey-conflict-alert.ts: a pure decision (shouldRaiseSuperpowersMigrationNudge), a pure copy builder (buildSuperpowersMigrationAlertInput), and a bulletproof orchestrator (maybeSurfaceSuperpowersMigrationNudge) that lazy-imports config-store / extensions-installer / alert-service so the SQLite + inbox graph stays off this leaf's static import path.
  • Raise-once-ever — the orchestrator reads settings.superpowersMigrationNudgedAt; if set, it returns immediately (never re-nags). Otherwise it probes isSuperpowersInstalled() — a user WITHOUT Superpowers (every fresh install) is never nudged and never stamped. If installed, it raises the card via raiseAgentAlert (dedupKey superpowers-migration-nudge, so re-fires coalesce into one row) and stamps superpowersMigrationNudgedAt — the stamp is written even if the raise was suppressed by the notifications off-switch, because a one-shot nudge must not retry every launch.
  • The card's action — the card carries a hand-wired, desktop-only Remove Superpowers button in src/renderer/src/features/alerts/AlertInboxViewer.tsx (recognised via isSuperpowersMigrationDedupKey; the shared dedupKey + predicate live in src/shared/alert-features/superpowers-migration-alert.ts). It sits behind a ConfirmDialog; on confirm it invokes EXTENSIONS_UNINSTALL, toasts success, and archives the card. The card ALSO keeps the universal additive Start-session button (inbox-alert-contract I8). Because the predicate is registered in LEGACY_ACTION_PREDICATES (src/shared/alert-primary-actions.ts), the alert-directive-needs-action guard sees the card as actioned.
  • The uninstall — uninstallSuperpowers() in src/main/services/extensions-installer.ts runs claude plugin uninstall superpowers@superpowers-marketplace. It is idempotent (an already-absent plugin resolves success via isNotInstalledError) and reversible (reinstall from the same marketplace anytime — the confirm copy says so). Raw CLI stderr stays in the log; the returned error is plain, humanized copy.

For agents

How it works

The implementation lives in two parallel layers, mirroring the existing toolchain pipeline but kept separate because the install paths and probe mechanics differ.

Definitions and probes. src/main/services/extensions-installer.ts exports EXTENSION_DEFINITIONS (currently two entries: playwright-mcp and superpowers), EXT_CHECK_FNS (probe functions returning ExtensionCheckResult), and EXT_INSTALL_FNS (install functions that emit progress and return ExtensionInstallResult). Probing reads JSON files from the user's home directory via src/main/services/claude-config.ts — readClaudeConfig() parses ~/.claude.json and readClaudeInstalledPlugins() parses ~/.claude/plugins/installed_plugins.json. The Playwright probe looks for a playwright key in mcpServers (in ~/.claude.json) and validates the config is healthy — if the entry's args array contains --cdp-endpoint, the probe returns misconfigured instead of installed, because a CDP-dependent config silently breaks when the external Chrome isn't running. The installer treats misconfigured the same as not-installed (the banner shows, the user clicks Install, and the repair flow removes-then-re-adds a clean self-managing config). The Superpowers probe runs both reads in parallel via Promise.all and returns "installed" if either source confirms: a key containing superpowers set to true in ~/.claude.json's enabledPlugins, OR a key containing superpowers mapped to a non-empty install array in ~/.claude/plugins/installed_plugins.json's plugins map. No claude binary is invoked for probing, so it's fast and offline-safe.

Why two sources for the Superpowers probe. Claude Code v2.x changed where it stores plugin enablement records. v1.x (and prior) wrote a flat boolean map enabledPlugins: { "superpowers@superpowers-marketplace": true } into ~/.claude.json. v2.x writes a richer install record into a separate file ~/.claude/plugins/installed_plugins.json of shape { version: 2, plugins: { "superpowers@superpowers-marketplace": [{ scope, version, installPath, … }] } }, and may or may not also keep the legacy enabledPlugins field populated. A previous version of this probe checked only the legacy field, so every user on Claude Code v2.x was false-flagged as missing Superpowers and shown the install banner — even though their plugin was installed and working. The current dual-source probe reads both files in parallel and treats the plugin as installed if either source confirms it. Reading both is intentional belt-and-suspenders: users mid-upgrade may have only the legacy field; users on a fresh v2.x install only have the new file. I/O errors (EACCES, EBUSY) propagate from readWithRetry; only JSON.parse failures retry once after 50ms (concurrent CLI writes can produce a truncated file mid-read).

Install paths. Both installs shell out via cmd.exe /c <claude|npx> … on Windows (Node's execFile doesn't honor PATHEXT, so .cmd shims like claude.cmd and npx.cmd won't resolve without going through cmd.exe). All arguments are constants — no user input — so no shell-escape is needed. Playwright MCP first does a best-effort claude mcp remove playwright (ignoring errors if the key doesn't exist) to clear any stale or misconfigured entry, then runs claude mcp add playwright -- npx @playwright/mcp@latest followed by npx playwright install chrome; if the Chromium step fails after the add succeeded, a cleanup claude mcp remove playwright removes the dangling MCP entry so sessions don't fail at spawn time pointing at a missing Chromium. Superpowers runs claude plugin marketplace add https://github.com/obra/superpowers-marketplace (tolerating "already added" exit codes via stderr matching) then claude plugin install superpowers@superpowers-marketplace.

IPC. src/main/ipc/extensions-ipc-handlers.ts registers five channels — EXTENSIONS_CHECK_ALL, EXTENSIONS_GET_DEFINITIONS, EXTENSIONS_INSTALL (single, by id), EXTENSIONS_INSTALL_ALL, and EXTENSIONS_UNINSTALL (Superpowers only — the migration card's Remove action) — plus the EXTENSIONS_INSTALL_PROGRESS push event (definitions in src/shared/ipc-channels/index.ts). All handlers are wrapped in wrapHandler() for Zod validation; EXTENSIONS_UNINSTALL validates against extensionUninstallInputSchema ({ id: z.literal('superpowers') }), so the channel can never remove any other plugin. Progress events use emitPush() from push-bus.ts, listened in the renderer via useIpcListener(IPC.EXTENSIONS_INSTALL_PROGRESS, …). EXTENSIONS_UNINSTALL is desktop-only — it mutates this computer's local ~/.claude plugin config, so it is in the mobile/web WS bridge's BLOCKED_CHANNELS denylist (src/main/services/web/web-access-ws-channels.ts) and its inbox button is hidden on mobile; it is cli-parity-classified dev-diagnostic.

Onboarding integration — RETIRED. This was src/renderer/src/features/onboarding/steps/ToolchainStep.tsx, which fetched tools and extensions in parallel, merged them into separate tools / extensions arrays, and rendered a unified list. Nothing in the live first-run path calls it: the shipped cascade's install step is src/renderer/src/features/onboarding/setup-v2/frames/InstallFrame.tsx, and a search of src/renderer/src/features/onboarding/setup-v2/ for EXTENSIONS_CHECK_ALL / EXTENSIONS_INSTALL_ALL returns nothing — the cascade installs CLI tools only. ToolchainStep is kept in the tree for reference and still compiles, so this description is of what it did, not of what ships. Extension probe failures are soft-fail — wrapped in Promise.resolve(...).catch(() => undefined) so a missing IPC handler doesn't crash the wizard. The install loop has a deliberate two-phase shape: all missing tools first (serial), then all missing extensions (serial). A compile-time guard _IdNamespacesDisjoint asserts ToolId & ExtensionId extends never so a future id collision (both tables sharing the installingIds Set) fails to typecheck.

Launch-time banner. src/renderer/src/hooks/useExtensionsLaunchCheck.ts drives the post-onboarding banner. On mount, if settings.extensionsPromptSnoozedUntil is in the future the effect bails out immediately (no IPC traffic). Otherwise it calls EXTENSIONS_CHECK_ALL + EXTENSIONS_GET_DEFINITIONS and computes the missing set. The hook returns { missing, install, snooze, installing }. install() calls EXTENSIONS_INSTALL_ALL, surfaces toasts on full or partial failure, then re-runs the check to clear newly-installed extensions from the banner. snooze() writes new Date(Date.now() + 24h).toISOString() to extensionsPromptSnoozedUntil and clears the missing list locally.

Banner gating. The banner is rendered by ExtensionsBannerMount inside src/renderer/src/App.tsx, conditionally on settings.onboardingCompleted. This is the double-prompt fix: onboarding's wizard step already shows the same install UI, so we mount the banner only after onboarding has been completed — otherwise a user mid-wizard would see both. The banner uses role="status" (aria-live polite), not role="alert", because a launch-time nudge for missing optional features shouldn't interrupt screen-reader flow on every re-render.

Soft-fail design. The continue button stays enabled even when extensions failed in the wizard, the banner can be snoozed indefinitely (re-snoozing each day), and the rest of Omniscio works without these extensions. The only cost is that browser-automation skills and Superpowers-dependent recipes will fail at runtime if they're invoked. This is intentional: we'd rather let the user proceed with a clear failure path than block app startup behind a dependency they may not need today.

Settings field. src/shared/types.ts adds extensionsPromptSnoozedUntil: string | null to AppSettings (default null). It's also wired into updateSettingsSchema so the IPC layer doesn't silently strip it — without that, the snooze write would round-trip cleanly in the store but never persist to config.json. The migration nudge adds a second marker of the same shape, superpowersMigrationNudgedAt: string | null (default null), wired the same way.

Related

  • tools-view.md — the dedicated virtual project for CLI binaries; explains why these two extensions don't appear there
  • toolchain-update-v3.md — how the parallel tool pipeline handles updates, deferred queues, and preflight checks (the model this extensions feature is shaped after)
  • use-skills.md — the Skills view; many catalogued skills depend on Playwright MCP or on Superpowers' foundational skills

Last verified 2026-09-28