AIDE Architecture — Phase 9: Extension Host + Marketplace
SkillDev toolsPhase 9 SOP for the AIDE offline-first IDE rebuild, a VS Code-class extension ecosystem: extension host as a separate Node process spawned by the daemon (fork/child), VS Code-compatible package.json manifest + contribution registry, Open VSX-compatible OFFLINE marketplace (local registry, vsix cache, sha256-verified installs, deny-by-default sandbox, network opt-in only), activation events, and a minimal vscode-like API surface. Use whenever wiring extension install/activate/execute/uninstall, building the marketplace UI, parsing manifests, or debugging extension-host failures. Research-grounded (VS Code extension host architecture docs, Open VSX, the verified aide-phase9-extension-host skill).
Use AIDE Architecture — Phase 9: Extension Host + Marketplace in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add AIDE Architecture — Phase 9: Extension Host + Marketplace and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the AIDE Architecture skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by anonymousnomad/covert-coder in skills/packs/aide-arch-extensions/SKILL.md and read by Ahel’s review.
Doctrine
- Isolation is the point. Extensions are third-party code running on the user's machine — they get a SEPARATE Node process (the extension host) with its own lifecycle, memory, and failure domain. An extension crash must NEVER take down the daemon (the VS Code model: extension host dies, IDE lives).
- Deny by default. Extensions have NO network (offline-first); no fs access beyond the workspace unless declared in manifest + granted; no process spawn unless the manifest declares an activation permission (VS Code extensions historically could do anything — WE choose stricter; the user opted into AIDE's safety model).
- VS Code manifest compatible.
package.jsonwithcontributes,activationEvents,main,engines.aide(plus engines.vscode for compat) — real VS Code extensions (the millions on Open VSX) are the supply chain; AIDE is the runtime. - Offline marketplace by default. The marketplace is a LOCAL registry (vsix files + index, sha256-verified); remote sync is an explicit opt-in (Phase 4 egress audit flag).
- Verify before claiming: install → activate (real activation event) → contribution visible (command runs) → uninstall, with an extension that crashes mid-run proving the host dies but the daemon lives.
What
Phase 9 delivers:
- Extension host process (
node/extension-host/): a forked Node process with a typed IPC protocol (JSON-RPC overfork()channel or MessagePort). Owns: extension loading, activation, API surface, command registry. - Extension manager (daemon side):
extensions/dir, install (unzip vsix → manifest parse → sha256 verify → move into place), uninstall, enable/disable, status. - Manifest schema (
common/contracts/extensions.ts): a zod schema covering the VS Code subset we support:main,activationEvents(onCommand:x,onLanguage:y,*),contributes(commands, languages, themes, keybindings — subset),engines,capabilities(AIDE extension:network: false|true,spawn: false|true— deny by default; unknown capability = denied). - API surface (
vscode-like): commands (registerCommand/executeCommand), workspace (fs ops via the daemon contract ONLY — the host proxies to the daemon, never touches fs directly... on second thought: the extension host is a privileged-ish process, but keep it consistent: it goes through the daemon's workspace service so containment rules apply uniformly), window (status bar, quick pick subset), languages (registerCompletionItemProvider etc. → bridged to Monaco via the Phase 5 protocol paths or a typed bridge), env, Disposable pattern, Event emitter util. This is the biggest single chunk — scope it: Phase 9.1 API core (commands + workspace fs read/write + window messages), Phase 9.2 language contributions (if time permits; the LSP bridge already gives languages without extensions). - Activation: lazy — a command contribution activates on first execute;
*activates on host start (with a warning badge "eagerly activated"). Host reports activation timing; the UI shows loaded/activated extensions. - Marketplace UI: LOCAL registry view (installed + available-in-cache), install-from-vsix file picker (the real offline path: user downloads a vsix elsewhere or receives it and drops it in), verify + quarantine flow. Remote registry = opt-in flag + explicit button.
- Sandbox: capability checks before EVERY privileged call (network/spawn denied by default); manifest hash recorded at install; the host runs with
NODE_OPTIONSminimal and no NODE_PATH; extension code gets a frozenprocess(no child_process, no net in the host's exposed globals — the host wraps them and denies unless capability granted).
How
1. Host process + IPC
child_process.fork('node/extension-host/main.js', [], { stdio: ['pipe','pipe','pipe','ipc'] })(or spawn with--experimental-...; fork gives the IPC channel for free).- Protocol: JSON-RPC-style messages over
process.send/process.on('message'):{ type:'invoke', id, method, args }(browser↔daemon methods proxied),{ type:'event', name, payload }(host → daemon → WS to browser),{ type:'log', level, message }. - Heartbeat: daemon pings every 30s; host replies; 2 missed → considered hung → kill + restart with backoff (Phase 5 restart pattern).
- Crash isolation: host exit ≠ daemon exit. On host death: extensions deactivate, commands unavailable, UI shows "extension host restarted" + auto-restart with backoff (cap 3 restarts/min, then manual).
- Extension code runs in the host's module loader;
mainis resolved relative to the extension dir;requireis sandboxed (the host provides a restricted loader: only thevscodemodule + safe builtins; nofs/child_process/net— deny by default, capability-granted wrappers only).
2. Manifest validation (zod, strict)
package.jsoninside the vsix must parse + validate against the manifest schema;engines.aidesemver range must match the running AIDE version (reject otherwise, clear message).activationEventsentries must be SUPPORTED kinds (onCommand/onLanguage/onView/onStartupFinished/*); unsupported kind = reject with a specific error (fail closed — silent non-activation is the worst outcome).contributesvalidated per kind: commands need id+title; languages need id+extensions; unknown contribution kinds are IGNORED (with a logged warning) — forward compat, but never silently broken for known kinds.
3. Install/uninstall (offline, verified)
- Install: user picks a .vsix (or the local registry has it) → daemon: sha256 compute → manifest parse → capability check → unzip (no
unzipshell command: use a JS unzip lib ortar -xfvia execFile with args — choose one, test on Windows; systemunzipoften absent) → write toextensions/<id>@<version>/→ record inextensions/index.json(id, version, sha256, installedAt, capabilities). - Integrity check at load: re-hash the main files? (vsix content hash suffices; files are immutable after install — index records the tree hash; a mismatch at load = "extension modified on disk" → disabled with warning).
- Uninstall: stop host → remove dir → index update → reload host (if extensions remain).
- Quarantine: on manifest/capability failure, the vsix is moved to
extensions/quarantine/(never deleted silently) with the reason in the log/UI.
4. Capability enforcement (the security line)
capabilities.network: if false (default) the host'snet/httpmodules are replaced with throwers; if true, still proxied through the daemon's egress audit (Phase 4) — network is NEVER raw.capabilities.spawn: if false (default) child_process spawn/fork/exec are throwers in the host; if true, spawn goes through the daemon's process manager (so tree-kill/containment/limits apply).capabilities.fs— workspace-scoped by default via the daemon contract; absolute-path fs denied unlesscapabilities.fsWide: true(rare; requires user confirm at install — a dialog naming the extension).- The daemon enforces, not the host: host requests a capability-gated op → daemon checks the extension's granted capabilities → denies with reason. Host-side throwing is belt, daemon-side check is suspenders.
5. Marketplace (offline-first)
- Local registry:
marketplace/with an index.json (available extensions: id, version, size, sha256, description) — seeded empty; populated by (a) user-dropped vsix files (auto-indexed on drop into a watched folder), (b) opt-in remote sync (Phase 4 egress flag + explicit button; the sync fetches Open VSX metadata into the local index — the cache IS the registry; after sync, installs are still offline). - Install from registry: read from cache + sha256 verify → same install path as vsix picker.
- The UI always shows install source: local file / local cache / (remote sync) — no surprise network.
Why (research grounding)
- VS Code docs (extension host architecture): a separate process for extension isolation, lazy activation via activationEvents, contributions from package.json — the proven model; we keep its shape and STRICTEN its sandbox (VS Code extensions historically get full node; ours get deny-by-default).
- Open VSX: the compatible ecosystem — manifest format and vsix layout (extension.vsixmanifest + extension/package.json) are the interoperable standard; offline mirroring is the documented distribution practice.
- Theia: extension hosts as separate processes with IPC; contribution registry pattern.
- Verified project lesson: the existing aide-phase9-extension-host skill (24.7KB) already encodes the registry/install/activate/execute/uninstall flow + Open VSX compatibility — this arch skill is its architecture doctrine; the old skill remains the operational detail reference.
- Offline-first: the user's requirement is absolute here — a marketplace that phones home is a violation; the local cache registry design makes offline the default and the only mode until opt-in.
Dependencies
Node 20+ (fork IPC), zod, an unzip lib (or tested tar -xf path — tar.exe ships with Windows 10+), Phase 1 process manager (host spawn + tree kill + heartbeat/timeout), Phase 4 WS (host events → browser), Phase 6 egress audit (opt-in sync path), Phase 5 protocol bridge (language contributions reuse it), the existing aide-phase9-extension-host skill as operational reference.
Known issues / bugs (watch these)
- Extension crash loop: a buggy extension crashing at load → host restarts → crash again → infinite loop. Backoff + restart cap (3/min) + auto-DISABLE the crashing extension after 2 consecutive crash-on-activate (with the log) — the "disable loopers" rule.
*activation: eager extensions slow host start + surface bugs on every boot; badge them in the UI; default suggestion "disable if unused".- VSIX zip bombs: unzip with size caps (total uncompressed limit, e.g. 500MB; file count limit) — a malicious vsix filling the disk is a real attack.
- Symlinks in vsix: a vsix containing symlinks pointing outside the extension dir — extract with link resolution disabled (store as regular files) or reject.
- IPC message floods: a chatty extension spamming host→daemon events — per-extension event rate cap (e.g. 100/s) with a warning; the browser WS has its own caps (Phase 4).
- NODE_OPTIONS leaks: the host must NOT inherit NODE_OPTIONS from the daemon env (extensions could read secrets via NODE_OPTIONS tricks) — strip it in the host spawn env.
- Module resolution: extension
mainrequiring its own deps (node_modules inside the vsix) — the restricted loader must resolve relative to the extension dir FIRST, then builtins; wrong order breaks real extensions. - Windows path in manifests: extension code doing path joins with hardcoded
/breaks on Windows — that's the extension's bug, but surface it clearly in the activation error log (host wraps uncaught exceptions with extension id + stack). - Engine version drift: AIDE upgrades breaking installed extensions — engines.aide range check at upgrade (Phase 11 release notes must flag extension compat).
Phase 9 audit checklist (applied to the existing extension-host work)
- Host is a separate forked process; daemon survives host crash (verify by killing the host mid-session).
- Manifest zod schema covers main/activationEvents/contributes/engines/capabilities; strict validation with clear errors; unknown contribution kinds logged-not-fatal.
- Install from local vsix: sha256 + manifest + capabilities + unzip caps + symlink rejection; index.json records; uninstall clean.
- Capability enforcement REAL: an extension with capabilities.network=false cannot fetch (egress audit catches it); spawn=false cannot spawn (daemon-side denial).
- Activation: lazy onCommand/onLanguage works;
*badges; crash-loop disable rule works. - Marketplace: local cache registry + opt-in remote sync behind the Phase 4 flag; UI shows install source.
npm run checkgreen; live: install a real small vsix (e.g. a theme), activate, command fires, uninstall.
Signals
- GitHub stars
- 43
- Forks
- 14
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
aide-arch-extensions- Source
- github.com/anonymousnomad/covert-coder
github.com/anonymousnomad/covert-coder
Related picks
Skill · thedaviddias
The pick for JavaScriptmodern-javascript-patterns
Skill · wshobson
The pick for JavaScriptsetup-ts-deep-modules
Skill · mattpocock
The pick for TypeScripttypescript-pro
Skill · jeffallan
The pick for TypeScriptsecrets-exposure-review
Skill · naodeng
The pick for Secretssecrets-with-git-crypt
Skill · derailed-dash
The pick for Secrets