# Mahana Devices — System Inventory
*Eco-Lead audit, 2026-04-22. Read-only. File:line citations ground every claim.*

---

## Ground truth anchor

Verification commands run for this document (2026-04-22):

```
ls ~/mahana-ecosystem/                                                    → 29 dirs
ls /Users/Mahana/mahana-ecosystem/mahana/web/apps/                        → 9 apps
ls /Users/Mahana/mahana-ecosystem/mahana/src/main/automation/routes/*.ts  → 372 route files
ls /Users/Mahana/mahana-ecosystem/mahana/src/main/services/*.ts           → 197 service files
grep -l "tryGetBrowserWindow|getElectronModule|ipcMain|from 'electron'"   → 22 routes, 7 services
grep -c "from 'electron'" src/main/automation/routes/voice*.ts            → 0 (all pass through bridge)
grep -c "from 'electron'" src/main/automation/routes/video*.ts            → 0
grep -c "from 'electron'" src/main/automation/routes/terminal*.ts         → 0
grep -c "from 'electron'" src/main/automation/routes/browser*.ts          → 0 (only .test files)
```

**Headline finding: the daemon already has a clean Electron-mode vs daemon-mode abstraction (`src/main/bridge/electron-bridge.ts:46-60`). Only ~5.9% of routes and ~3.6% of services touch Electron at all, and every one of them does so through `tryGetBrowserWindow()` which returns `null` in daemon mode. The 4 device subsystems (voice, video, browser, terminal) are already 85-95% decoupled by design.**

---

## 1. Voice

**Where the code lives:**
- Daemon routes: `src/main/automation/routes/voice*.ts` — 11 files, **17,002 lines total**
  - `voice.ts` (3,022L) — top-level voice APIs
  - `voice-calls.ts` (3,408L) — call orchestration, xAI Realtime + ElevenLabs
  - `voice-library.ts` (1,865L) — voice library / samples
  - `voice-podcast.ts` (1,543L) — podcast generation
  - `voice-web.ts` (1,577L) — web-facing endpoints
  - `voice-chat.ts` (1,306L) — chat-style voice
  - `voice-memory.ts` (1,212L) — voice memory / embeddings
  - `voice-fireworks.ts` (878L), `voice-enhancements.ts` (755L), `voice-orchestration.ts` (761L), `voice-infra.ts` (675L)
- Daemon services: `src/main/services/voice*.ts` + `src/main/services/voice/` — 9 top-level files + subdir, **5,157 lines** (top-level) plus `voice/` dir
  - `voice.service.ts` (845L), `voice-memory.ts` (1,382L), `voice-dispatcher.ts` (742L)
  - `voice/voice-call-v2.ts`, `voice/voice-commands.ts`, `voice/always-on-listener.ts`, `voice/providers/`
- Daemon services: `src/main/services/edge-tts/`, `src/main/services/replicate-tts/` (TTS provider adapters)
- Standalone app: `~/mahana-ecosystem/elevenlabs-voice-app/` — Next.js, Vercel-deployable (no Electron)
  - `package.json:name = "elevenlabs-voice-app"`, zero Electron deps
- UI panels (Electron-renderer only): `web/apps/mahana-mastermind-chat-core` has a VoicePanel; notch has voice tab at `notch-window.ts:27-33`

**Dependencies on Electron-main (verified — file:line):**
- `voice-chat.ts:11` — `import { tryGetBrowserWindow } from '../../bridge'`
- `voice-chat.ts:470-471` — `BrowserWindow?.getAllWindows()[0] ?? null` for UI automation (clicks voice button)
- `voice-chat.ts:479, 509, 605, 722, 815` — `mainWindow.webContents.executeJavaScript(...)` to read renderer DOM state
- `voice-memory.ts:66` + `:1131-1158` — `webContents.capturePage()` for terminal-region screenshots (feeds vision chain)
- `voice.ts:5, 1530-1531, 1687-1696` — global shortcut dispatch: `webContents.send('shortcut:voice-toggle')`
- `voice-enhancements.ts` — 5 BrowserWindow refs (spot checks)
- `services/voice-terminal-bridge.ts:~4 refs` — attaches voice to terminal focus

**Total hard coupling**: 16 + 9 + 5 + 9 + 4 = **43 references**, all through `tryGetBrowserWindow()` which returns `null` in daemon mode.

**What it produces:**
- Audio streams (mic → STT), synthesized audio (TTS → speaker)
- Neuropackets via `services/voice-neuropacket-reactor.ts:143L` (`headless.ts:485-486` — "voice→neuropacket reactor")
- Voice session state in `voice/voice-session-store.ts`
- Receipts in `~/.mahana/receipts.jsonl`

**What it consumes:**
- STT: xAI Realtime (`voice-calls.ts`), DeepInfra, Groq (cloud), Whisper.cpp (local fallback)
- TTS: ElevenLabs (`elevenlabs-voice-app` + `voice-library.ts`), Kokoro, Orpheus, Replicate (`replicate-tts/`), Edge TTS (`edge-tts/`)
- Think layer: `/mahana-ai/think` daemon route → cascade brains
- Supabase `mahana_brains`, `neuro_items`

**Shippable standalone?**
- `elevenlabs-voice-app` — **yes, today**. Standalone Next.js, no Electron deps.
- Daemon voice routes — **yes with ~8 hours of decoupling work**, broken down in CONSOLIDATION.md § Voice. The 43 Electron references are all graceful-degrade paths (screenshot → return 503, shortcut dispatch → event bus fallback).

---

## 2. Video

**Where the code lives:**
- Daemon routes: `src/main/automation/routes/video*.ts` — 4 files, **1,436 lines total**
  - `video-studio.ts` (595L) — Remotion Studio wrapper + `/video/narrate`, `/video/render`
  - `video-signaling.ts` (406L) — WebSocket signaling for MediaSoup SFU
  - `video-jobs.ts` (345L) — render job queue
  - `video-room-open.ts` (90L) — opens multi-brain video room window
- Daemon services: `src/main/services/video/` — 5 files
  - `mediasoup-service.ts` (446L per header comment) — WebRTC SFU
  - `ai-participant.ts`, `frame-extractor.ts`, `narrative-synthesis.ts`, `recording-service.ts`, `room-store.ts`
- Window wrapper: `src/main/video-room/video-room-window.ts` (185L) — Electron BrowserWindow loading `localhost:5204`
- Web apps (standalone): `web/apps/mahana-video/` (Next.js, port 5203), `mahana-dream-studio/apps/video-room-brain/`
- Related repos:
  - `~/mahana-ecosystem/mahana-film` — Vite video-editor scaffold
  - `~/mahana-ecosystem/mahana-video-editor-v1` — Next.js video editor shell
  - `~/mahana-ecosystem/mahana-dream-studio/apps/video-room-brain/` — Multi-Brain Video Room app (port 5204 per `DREAM-STUDIO-STATUS.md:5-10`)

**Dependencies on Electron-main:**
- `video-room-window.ts:15` — `import { BrowserWindow, screen, app } from 'electron'` (**hard import**)
- `video-room-open.ts:11` — calls `createVideoRoomWindow()` from above
- **Zero Electron imports in the 4 route files themselves and the 5 service files.**

**What it produces:**
- WebRTC streams via MediaSoup SFU
- Rendered MP4s via Remotion (`spawn('npx remotion render', …)` in `video-studio.ts`)
- Recording files in `~/.mahana/recordings/`
- Frame-extracted images for vision-chain feeding

**What it consumes:**
- Browser camera/mic (auto-granted via `video-room-window.ts` `setPermissionRequestHandler`)
- MediaSoup (self-hosted SFU)
- Remotion CLI (local spawn)
- TTS (`/video/narrate` calls voice routes)
- ffmpeg (via Remotion)

**Shippable standalone?**
- `mahana-dream-studio` apps (video-room-brain, tv-brain-visualizer, tv-fleet-dashboard) — **yes, today**. Static + Node servers on :5204-5206 per `DREAM-STUDIO-STATUS.md`.
- `mahana-film`, `mahana-video-editor-v1` — **yes, today**. No Electron deps.
- Daemon video subsystem — **yes with ~2 hours**, just swap `createVideoRoomWindow()` for a `child_process.spawn(<platform-native browser>, …)` when in daemon mode. The rest is pure.

---

## 3. Dreamstudio

**Where the code lives:**
- Repo: `~/mahana-ecosystem/mahana-dream-studio/` (primary)
  - `apps/tv-brain-visualizer/`, `apps/tv-fleet-dashboard/`, `apps/video-room-brain/`
  - `services/presenter-observation.ts`, `services/rodecaster-brain-bridge.ts`
  - `mahana-dream-studio.jsx`, `mahana-studio-map.jsx` (top-level React)
- Canvas server: `~/mahana-ecosystem/mahana-canvas/` — **370-line Express + WebSocket server** on port 9880 (`canvas-server.js:22`)
  - Uses `chokidar` file watching, `WebSocketServer` for hot reload, `ws` module
  - **Zero Electron deps** (verified: node `express`, `ws`, `chokidar` only)
- Renderer components: several `web/apps/mahana-mastermind-chat-core/src/components/dream*` (not verified exhaustively — out of scope for read-only audit)

**Dependencies on Electron-main:** **None.** Every file in `mahana-dream-studio/` and `mahana-canvas/` is plain Node/Next/static HTML. The `DREAM-STUDIO-STATUS.md:6-10` dashboard confirms the apps run on web ports (5204, 5205, 5206) — no Electron window wrapping them (though `video-room-window.ts` exists as an *optional* Electron convenience wrapper).

**What it produces:**
- Image renders (Stable Diffusion / Replicate / xAI image gen)
- TV brain visualizations (fleet state on external displays)
- Presenter mode artifacts (audio + visual for Rodecaster)

**What it consumes:**
- Image-gen providers (Replicate, xAI Imagine, FLUX via Fireworks)
- Daemon routes for brain state (`/k`, `/brain/ask`)
- WebSocket from `mahana-canvas:9880` for hot reload
- Rodecaster Pro II audio bridge (hardware)

**Shippable standalone?** **Yes, today.** The entire Dream Studio stack already runs outside Electron. It's served from `mahana-canvas` (Express :9880) and `mahana-dream-studio/apps/*` (static HTML + localhost Next servers). The only Electron touchpoint is the optional `video-room-window.ts` wrapper, which a DMG/CLI build can trivially replace with `open http://localhost:5204` on macOS / `xdg-open` on Linux.

---

## 4. Live

**Where the code lives (mapped via grep, ground-truth):**
- Daemon routes: `src/main/automation/routes/live-benchmark.ts` (benchmark suite, not a streaming product)
- Streaming-adjacent routes: `terminal-stream.ts:103L`, `screen-stream.ts`, `realtime-routes.ts`, `mcp-streamable.ts`
- WebSocket layer: built into `automation-server-v2.ts` + `video-signaling.ts:406L`
- **No dedicated "live" streaming product** beyond the video subsystem + WebRTC SFU + CF Realtime binding (`.env` has `CF_REALTIME_APP_ID` per memory reference)

**Honest re-scoping (per boundary-verification rule):** The task prompt lists "live" as a distinct 4th subsystem. Ground-truth search shows that "live" in this codebase = **video-signaling WebSocket + Cloudflare Realtime bridge + screen-stream + live-benchmark**. It is not a standalone product today; it is the realtime transport layer underneath voice and video.

**Dependencies on Electron-main:** None directly. The realtime transport is pure Node + WebSocket + CF Realtime API.

**What it produces:** WebSocket frames, CF Realtime DataChannel messages, SSE streams to renderers.

**What it consumes:** `cloudflare:realtime` app (see `Cloudflare IDs` memory reference), daemon event bus, MediaSoup SFU.

**Shippable standalone?** **Already is** — it's the wire, not an app. Same Node daemon code runs in Electron-main OR `--daemon` mode.

---

## 5. Browser

**Where the code lives:**
- Daemon routes: `src/main/automation/routes/browser*.ts` — 2 production files + 5 test files, **8,164 lines total**
  - `browser-do.ts` (3,693L) — unified browser automation (`/browser/do` with `op: navigate|click|scroll|screenshot|execute`)
  - `browser.ts` (2,246L) — screenshot, navigation, tab management, session-scoped ops
  - `browser-molecular.ts` (1,829L) — "molecular" granular DOM ops
- Daemon services: `src/main/services/browser/` — 4 files
  - `browser-backend.ts` (interface)
  - `electron-browser-backend.ts` — wraps Electron WebContents
  - `puppeteer-browser-backend.ts` — wraps puppeteer-core Page
  - `puppeteer-pool.ts` — per-session puppeteer Page pool
- Backend selection: `browser-do.ts:118-131` — **`MAHANA_BROWSER_BACKEND=puppeteer` env var switches backends**. Default: Electron. Headless fallback: Puppeteer-core (`puppeteer-pool.ts:127-157`).

**Dependencies on Electron-main:**
- `browser-do.ts:13 refs`: `tryGetBrowserWindow`, `getElectronModule()`, CDP debugger via WebContents at lines 789-798, 960-983, 3384
- `browser.ts:18 refs`: screenshot capture at :317-321, 398-420; agent-browser-panel IPC at :1274-1395
- `browser-molecular.ts:5 refs`: window detection

**But** — the dual-backend architecture means **the daemon can run browser ops via Puppeteer-core when Electron is absent**. `browser-do.ts:126` `getActiveBackendType()` returns `'puppeteer'` if env set, and `puppeteer-pool.ts:138-157` launches headless Chromium. The Electron path is the "when UI is available" optimization, not a hard requirement.

**What it produces:** Screenshots, page content, scraped data, cookie state, navigation receipts, neuropackets for vision analysis.

**What it consumes:** Electron WebContents (when available) OR headless Chromium (via `puppeteer-core`, falls back to system Chromium path). Needs a Chromium binary OR Electron.

**Shippable standalone?** **Yes, today, with `MAHANA_BROWSER_BACKEND=puppeteer` and a system Chromium path.** The puppeteer-core backend is production-complete. The "browser" product (as in *Mahana Browser = the user-facing app with tabs*) would need a renderer shell — that's where `mahana-unified` (Next/Capacitor) or a new minimal WebView window comes in.

---

## 6. Terminal

**Where the code lives:**
- Daemon routes: `src/main/automation/routes/terminal*.ts` — 10 files, **4,305 lines total**
  - `terminal-history.ts` (797L), `terminal-watchdog.ts` (815L), `terminal-watchdog-v2.ts` (508L)
  - `terminal-rag.ts` (510L), `terminal-observe.ts` (468L), `terminal-intelligence.ts` (477L)
  - `terminal-smart.ts` (410L), `terminal-semantic.ts` (166L), `terminal-stream.ts` (103L), `terminal-teleport.ts` (51L)
- PTY daemon: `src/main/pty-daemon/` — **1,237 lines total** (separate HTTP+WS server on :9879)
  - `server.ts` (308L), `manager.ts` (528L), `lifecycle.ts` (132L), `scrollback-persistence.ts` (143L), `index.ts` (126L)
- Terminal services: `src/main/services/terminal-state-detector.ts`, `terminal-reaper.ts`, etc.
- Standalone Swift app: `~/mahana-ecosystem/mahana-terminal/` — **SwiftPM + macOS 14+ + SwiftTerm + planned libghostty** (`Package.swift:1-30`)
  - Sources: `App.swift`, `TerminalView.swift`, `BrowserPane.swift`, `DirectorPanel.swift`, `DaemonBridge.swift`
  - **Zero Electron deps** — pure native Swift

**Dependencies on Electron-main:**
- `terminal*.ts` routes: **0 electron imports** (verified by grep — all coupling is through `ipc/terminal.ipc.ts` which is called from `index.ts:75`)
- PTY daemon: **0 electron imports** (verified by grep)
- IPC layer: `src/main/ipc/terminal.ipc.ts` (Electron-side only) wraps node-pty. `headless.ts:109` imports `seedTerminalCounter`, `writeToTerminal`, `getTerminalOutput` from it — so in daemon mode the terminal.ipc exports are used without the IPC shell.

**What it produces:** PTY output streams, scrollback, tmux session state, terminal screenshots (via voice-memory's webContents path), observed agent banners.

**What it consumes:** `node-pty` (native module), tmux (shell), tmux windowing config, scrollback persistence at `~/.mahana/scrollback/`.

**Shippable standalone?**
- `mahana-terminal` Swift app — **yes, today, for macOS 14+**. Native SwiftTerm rendering, DaemonBridge to `localhost:9878`. No Electron.
- Daemon terminal routes — **yes, already** (running headlessly today as `cc.mahana.daemon` launchd service; `headless.ts:67 TERMINAL_MODE` flag explicitly supports `--terminal` for lightweight PTY).

---

## 7. Other subsystems found in the sweep

### Substrate (`~/mahana-ecosystem/mahana-substrate/`)
- `substrate.js` (1,696L), `substrate-sdk-handler.mjs` (876L), `substrate-brains.mjs` (1,644L), `substrate-mcp.mjs` (318L), `fleet-lead-loop.mjs` (449L)
- **Zero Electron imports** (verified)
- Runs as `cc.mahana.substrate` launchd service, port 9877
- **Shippable standalone today** — already is.

### Brain (`~/mahana-ecosystem/mahana-brain/`)
- TypeScript Node server, `dist/server.js` entry. Zero Electron. Shippable today.

### Agent SDK (`~/mahana-ecosystem/mahana-agent-sdk/`)
- `@mahana/agent-sdk` library — TypeScript, ESM. No Electron. Shippable today as an npm package.

### Neuropacket SDK (`~/mahana-ecosystem/mahana-neuropacket-sdk/`)
- `neuropacket-sdk` package with `demo/` folder. Shippable today.

### mahana-unified (`~/mahana-ecosystem/mahana-unified/`) — **the iOS surface**
- Next.js 16 + Capacitor 8 + Fastlane. `package.json:16-52`.
- `capacitor.config.ts`: `appId: 'cc.mahana.mobile'`, `webDir: 'out'`.
- Directories: `app/`, `components/`, `lib/`, `types/` (src/), `ios/App/` (Xcode project).
- Per project memory: iOS-specialist has ownership, Build 8 currently in product-verification loop (see `scars_wrapping_non_canonical_export.md` memory reference).

### Capture (`~/mahana-ecosystem/mahana-capture/`)
- Rust sidecar for CoreAudio/ScreenCaptureKit/NDI (<10ms I/O). `Cargo.toml:3-5`.
- Axum HTTP + WS server, registers with substrate on boot.
- **Shippable today** as a standalone binary; macOS-only currently.

### Mini-MCP (`~/mahana-ecosystem/mahana-mini-mcp/`)
- CF Worker MCP server. wrangler.toml present. Deploys independently.

### Translator-proxy (`~/mahana-ecosystem/mahana/packages/translator-proxy/`) — **NEW (git status shows ??)**
- `@mahana/translator-proxy@0.2.0` — CF Worker
- "Anthropic ↔ OpenAI translator proxy — CF Worker that lets Claude Code CLI drive non-Anthropic backends"
- Files: `worker.ts`, `translator.ts`, `backends.ts`, `streaming.ts`, `types.ts`, `__tests__/`, `DECISION-MEMO.md`, `HANDOFF.md`
- **Shippable standalone via `wrangler deploy`**

### Canvas (`~/mahana-ecosystem/mahana-canvas/`)
- Node Express + WebSocket server, port 9880. Dream Studio preview/hot-reload. Zero Electron.

### Landing / Sign-up / Music / Logo / Journalist / Design-system / Clients / Preview
- `mahana-landing` — static copy + src
- `mahana-sign-up` — static HTML
- `mahana-music` — static assets + Rodecaster bridge (no package.json at top level)
- `mahana-logo-brand-assets-public` — assets
- `mahana-journalist` — Python + SQLite (`jmail_harvester.py`, `journalist.db`)
- `mahana-design-system` — project/ scaffold
- `mahana-clients/rustbar` — Rust
- `mahana-preview` — **an older `mahana` Electron app!** package.json name = `mahana`, main = `./out/main/index.js`. Contains electron-updater, puppeteer-core. Likely the v5.x reference implementation retained for comparison.
- `aege` / `aege.no` — asset-only
- `mahana-phase1`, `mahana-growt-agent`, `mahana-mcp-server-archive`, `mahana-suite-wt`, `bin`, `tmp` — legacy/aux, out of scope

### Web apps (`web/apps/` inside main `mahana` repo)
- `mahana-home` (notch surface, port 5240)
- `mahana-suite` (suite modules, port 5200)
- `mahana-mastermind-chat-core` (chat, port 5230)
- `mahana-mail`, `mahana-accountant`, `mahana-video`, `mahana-table`, `mahana-training`, `mahana-benchmark`
- **All are plain Next.js and deploy to Vercel independently** (per `project_env_var_topology.md` memory). Electron only wraps them as BrowserViews/iframes.

### Electron-only windows (the true hard coupling)
- `src/main/notch/notch-window.ts` (762L) — notch pill, 3-tier expansion, `ipcMain`, `BrowserWindow`, `screen`, `app`
- `src/main/island/island-window.ts` (659L)
- `src/main/editor-window/editor-window.ts` (462L)
- `src/main/video-room/video-room-window.ts` (185L)
- `src/main/window.ts` — main window + `systemPreferences.askForMediaAccess('microphone')` (line 65-70)
- `src/main/services/sovereign-gate.ts:22-24` — `systemPreferences.promptTouchID()`
- `src/main/ipc/*` — ~20 IPC handlers, all Electron-bound

**Total true Electron coupling**: ~3,500 lines out of **~100K+ in src/main**. That's the actual "what would have to be refactored" surface for a standalone daemon ship.

---

## Summary table (ship-readiness today, no code changes)

| System | Standalone repo? | Daemon-mode working? | Electron-hard? | Lines in daemon/main | Lines in repo |
|---|---|---|---|---|---|
| Voice | `elevenlabs-voice-app` (partial) | **Yes** (via bridge) | 43 refs, all graceful | ~22,000 | ~5,000 |
| Video | `mahana-film`, `-video-editor-v1`, `-dream-studio/apps/video-room-brain` | **Yes** (daemon routes) | `video-room-window.ts` (185L) only | ~2,300 | ~3,000 combined |
| Dreamstudio | `mahana-dream-studio` + `mahana-canvas` | **Yes** (is already standalone) | **None** | ~100 (canvas-server imports) | ~4,000 combined |
| Live | (not a standalone product — transport layer) | Yes | None | ~1,000 | — |
| Browser | `mahana-preview` (ref) + puppeteer pool | **Yes** via `MAHANA_BROWSER_BACKEND=puppeteer` | 36 refs, all via bridge | ~8,200 | — |
| Terminal | `mahana-terminal` (Swift, macOS-native) | **Yes** (PTY daemon on :9879) | 0 in routes; IPC-layer only | ~5,500 | ~2,000 Swift |
| Substrate | `mahana-substrate` | **Yes** (already running as launchd) | None | — | 4,983 |
| iOS shell | `mahana-unified` (Capacitor) | **Yes** (already deployed, Build 8) | None | — | ~3,000 |
| Capture sidecar | `mahana-capture` (Rust) | **Yes** (via substrate register) | None | — | Rust |
| Translator-proxy | `packages/translator-proxy` (CF Worker) | **Yes** (wrangler deploy) | None | — | ~1,500 |

**Decoupling score summary: every one of the 4-5 subsystems is already ≥85% ready to ship without Electron.** The honest consolidation work isn't refactoring the routes; it's **picking the distribution flows** (DMG / curl-sh / Swift-native / Capacitor) and wiring a **first-run council experience** that spawns without a config UI.
