|
| 1 | +# @wolfcola/devtools-standalone |
| 2 | + |
| 3 | +Standalone Electron desktop app for OIDC/OAuth2 debugging — no browser extension required. Apps connect via WebSocket using [`@wolfcola/devtools-bridge`](../devtools-bridge). Also runs as a headless MCP server for AI agent integration. |
| 4 | + |
| 5 | +## Contents |
| 6 | + |
| 7 | +- [Quick start](#quick-start) |
| 8 | +- [Modes](#modes) |
| 9 | +- [WebSocket protocol](#websocket-protocol) |
| 10 | +- [MCP tools](#mcp-tools) |
| 11 | +- [Architecture](#architecture) |
| 12 | +- [Effect services](#effect-services) |
| 13 | + |
| 14 | +--- |
| 15 | + |
| 16 | +## Quick start |
| 17 | + |
| 18 | +```bash |
| 19 | +# Build (requires devtools-ui to be built first) |
| 20 | +pnpm --filter @wolfcola/devtools-ui build |
| 21 | +pnpm --filter @wolfcola/devtools-standalone build |
| 22 | + |
| 23 | +# Run the Electron app |
| 24 | +pnpm --filter @wolfcola/devtools-standalone start |
| 25 | + |
| 26 | +# Run as headless MCP server |
| 27 | +electron dist/src/main.cjs --mcp |
| 28 | +``` |
| 29 | + |
| 30 | +Connect your app: |
| 31 | + |
| 32 | +```ts |
| 33 | +import { attachDebugger } from '@wolfcola/devtools-bridge'; |
| 34 | + |
| 35 | +const handle = await attachDebugger({ name: 'my-app' }); |
| 36 | +// handle.connected → true if WebSocket is open |
| 37 | +// handle.detach() → cleanup |
| 38 | +``` |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +## Modes |
| 43 | + |
| 44 | +### GUI mode (default) |
| 45 | + |
| 46 | +Electron window (1200x800) with the Elm UI. A WebSocket server binds to `127.0.0.1:19417` (localhost only). Connected apps appear as sessions; events flow into the same timeline/flow/diagnosis views as the browser extension. |
| 47 | + |
| 48 | +```bash |
| 49 | +electron dist/src/main.cjs # default port |
| 50 | +electron dist/src/main.cjs --port 9000 # custom port |
| 51 | +``` |
| 52 | + |
| 53 | +### MCP mode (`--mcp`) |
| 54 | + |
| 55 | +Headless stdio-based MCP server for Claude and other AI agents. Same session management and tools, no UI. |
| 56 | + |
| 57 | +```bash |
| 58 | +electron dist/src/main.cjs --mcp |
| 59 | +``` |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +## WebSocket protocol |
| 64 | + |
| 65 | +All messages are JSON. The server validates incoming messages with Effect Schema. |
| 66 | + |
| 67 | +### Handshake |
| 68 | + |
| 69 | +``` |
| 70 | +Client → { "type": "HANDSHAKE", "name": "my-app", "pid": 1234, "framework": "react" } |
| 71 | +Server → { "type": "CONNECTED", "sessionId": "550e8400-..." } |
| 72 | +``` |
| 73 | + |
| 74 | +### Event ingestion |
| 75 | + |
| 76 | +``` |
| 77 | +Client → { "type": "SDK_EVENT", "payload": { ... } } |
| 78 | +Client → { "type": "NETWORK_EVENT", "payload": { "request": ..., "response": ..., "time": ... } } |
| 79 | +``` |
| 80 | + |
| 81 | +### Clear |
| 82 | + |
| 83 | +``` |
| 84 | +Client → { "type": "CLEAR" } |
| 85 | +``` |
| 86 | + |
| 87 | +### Errors |
| 88 | + |
| 89 | +``` |
| 90 | +Server → { "type": "ERROR", "message": "Failed to process message" } |
| 91 | +``` |
| 92 | + |
| 93 | +--- |
| 94 | + |
| 95 | +## MCP tools |
| 96 | + |
| 97 | +| Tool | Purpose | |
| 98 | +| ------------------------ | ----------------------------------------------------- | |
| 99 | +| `list-sessions` | List all connected/disconnected sessions | |
| 100 | +| `get-events` | Get events with optional type/time filtering | |
| 101 | +| `get-flow-summary` | Summary metrics (node count, error count, etc.) | |
| 102 | +| `get-diagnosis` | Run diagnosis engine on session events | |
| 103 | +| `get-event-detail` | Full event details (headers, body, OIDC semantics) | |
| 104 | +| `search-events` | Find events by URL pattern, error-only, or OIDC phase | |
| 105 | +| `clear-flow` | Clear all events in a session | |
| 106 | +| `export-json` | Redacted JSON export | |
| 107 | +| `export-markdown` | Redacted Markdown export with diagnosis | |
| 108 | +| `set-clear-on-reconnect` | Toggle auto-clear on session reconnect | |
| 109 | + |
| 110 | +All queries apply `redactFlowState` before returning data. |
| 111 | + |
| 112 | +--- |
| 113 | + |
| 114 | +## Architecture |
| 115 | + |
| 116 | +``` |
| 117 | +┌─────────────────────────────────────────────────┐ |
| 118 | +│ Electron Main │ |
| 119 | +│ │ |
| 120 | +│ SessionManager (Ref<Session[]>) │ |
| 121 | +│ • create / reconnect / disconnect │ |
| 122 | +│ • per-session ManagedRuntime + EventStore │ |
| 123 | +│ │ |
| 124 | +│ ┌────────────┐ ┌───────────┐ ┌───────────┐ │ |
| 125 | +│ │ WsServer │ │ IpcBridge │ │ MCP Server│ │ |
| 126 | +│ │ (Effect) │ │ (Electron)│ │ (Stdio) │ │ |
| 127 | +│ └─────┬──────┘ └─────┬─────┘ └───────────┘ │ |
| 128 | +│ │ │ │ |
| 129 | +└────────┼───────────────┼────────────────────────┘ |
| 130 | + │ │ |
| 131 | + WebSocket IPC Channels |
| 132 | + │ │ |
| 133 | + ▼ ▼ |
| 134 | + ┌──────────┐ ┌─────────────┐ |
| 135 | + │ SDK / │ │ Elm UI │ |
| 136 | + │ App │ │ (Renderer) │ |
| 137 | + └──────────┘ └─────────────┘ |
| 138 | +``` |
| 139 | + |
| 140 | +Events flow: `StandaloneClient → WsServer → SessionManager.ingestEvent → handleMessage → EventStoreService → DiagnosisEngine → IPC → Elm UI` |
| 141 | + |
| 142 | +--- |
| 143 | + |
| 144 | +## Effect services |
| 145 | + |
| 146 | +| Service | Layer | Purpose | |
| 147 | +| ----------------- | --------------------- | ---------------------------------------------------------------------------- | |
| 148 | +| `SessionManager` | `SessionManagerLive` | In-memory session state (`Ref<Session[]>`) with per-session `ManagedRuntime` | |
| 149 | +| `WsServer` | `WsServerLive` | `@effect/platform-node` WebSocket server with Schema-validated protocol | |
| 150 | +| `WolfcolaToolkit` | `WolfcolaToolkitLive` | `@effect/ai` MCP tool definitions | |
| 151 | + |
| 152 | +--- |
| 153 | + |
| 154 | +## Testing |
| 155 | + |
| 156 | +```bash |
| 157 | +pnpm --filter @wolfcola/devtools-standalone test |
| 158 | +``` |
| 159 | + |
| 160 | +Unit tests cover protocol schema validation, session manager operations, WebSocket handshake/event flow, and MCP tool invocation. |
| 161 | + |
| 162 | +## License |
| 163 | + |
| 164 | +MIT |
0 commit comments