Skip to content

Commit 4b2b276

Browse files
ryanbas21claude
andcommitted
docs: add changeset, standalone README, and update bridge README
- Add minor changeset for devtools-bridge and devtools-core - Add README for the new devtools-standalone package covering modes, WebSocket protocol, MCP tools, architecture, and Effect services - Update bridge README with standalone debugger section, attachDebugger API docs, Node HTTP interceptor, and updated architecture diagram Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent fac11fc commit 4b2b276

3 files changed

Lines changed: 249 additions & 1 deletion

File tree

.changeset/standalone-debugger.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@wolfcola/devtools-bridge': minor
3+
'@wolfcola/devtools-core': minor
4+
---
5+
6+
Add standalone Electron debugger with MCP integration
7+
8+
New `attachDebugger()` API in devtools-bridge connects apps to the standalone
9+
debugger via WebSocket. Includes auto-launch, fetch/XHR/Node HTTP interceptors,
10+
and reconnection with session management. The standalone app runs as an Electron
11+
desktop app or headless MCP server (`--mcp` flag) with 10 tools for session
12+
inspection, event querying, diagnosis, and export.

packages/devtools-bridge/README.md

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# @wolfcola/devtools-bridge
22

3-
Opt-in SDK adapter that connects your Ping Identity / ForgeRock application to WolfCola DevTools — either the [browser extension](../devtools-extension) or the [VS Code extension](../vscode-extension). Add it to your app in one line — it is a no-op when the extension is not installed, so it is safe to ship in production builds.
3+
Opt-in SDK adapter that connects your Ping Identity / ForgeRock application to WolfCola DevTools — the [browser extension](../devtools-extension), the [VS Code extension](../vscode-extension), or the [standalone debugger](../devtools-standalone). Add it to your app in one line — it is a no-op when no debugger is available, so it is safe to ship in production builds.
44

55
## Contents
66

@@ -9,6 +9,7 @@ Opt-in SDK adapter that connects your Ping Identity / ForgeRock application to W
99
- [DaVinci — `attachDevToolsBridge`](#davinci--attachdevtoolsbridge)
1010
- [AM Journey — `attachJourneyBridge`](#am-journey--attachjourneybridge)
1111
- [OIDC / OAuth — `attachOidcBridge`](#oidc--oauth--attachoidcbridge)
12+
- [Standalone debugger — `attachDebugger`](#standalone-debugger--attachdebugger)
1213
- [Low-level API](#low-level-api)
1314
- [How it works](#how-it-works)
1415
- [Safety](#safety)
@@ -134,6 +135,61 @@ attachOidcBridge(client, { clientId: 'my-spa-client', ...rest });
134135

135136
---
136137

138+
## Standalone debugger — `attachDebugger`
139+
140+
Connects your app to the [standalone Electron debugger](../devtools-standalone) via WebSocket instead of the browser extension. Works in both browser and Node.js environments.
141+
142+
```ts
143+
import { attachDebugger } from '@wolfcola/devtools-bridge';
144+
145+
const handle = await attachDebugger({
146+
name: 'my-spa',
147+
port: 19417, // default
148+
autoLaunch: true, // launch debugger if not running (default true)
149+
network: true, // install fetch interceptor (default true)
150+
framework: 'react', // optional metadata
151+
});
152+
153+
// Later:
154+
handle.detach(); // cleanup interceptors and close WebSocket
155+
```
156+
157+
**Options:**
158+
159+
| Option | Type | Default | Purpose |
160+
| ------------ | --------- | ------- | ---------------------------------------------------------- |
161+
| `name` | `string` || App name shown in session list (required) |
162+
| `port` | `number` | `19417` | WebSocket server port |
163+
| `autoLaunch` | `boolean` | `true` | Launch debugger binary if not already running |
164+
| `network` | `boolean` | `true` | Install fetch interceptor to capture auth-related requests |
165+
| `pid` | `number` || Process ID (optional metadata) |
166+
| `framework` | `string` || Framework name (optional metadata) |
167+
168+
**What happens on `attachDebugger()`:**
169+
170+
1. Opens a WebSocket to `ws://localhost:{port}` and sends a handshake
171+
2. If not connected and `autoLaunch` is enabled, finds `wolfcola-devtools` in PATH, spawns it, and retries with exponential backoff (~2.5s max)
172+
3. If connected and `network` is enabled, installs a fetch interceptor that forwards auth-related requests to the debugger
173+
4. Returns `{ connected, detach() }`
174+
175+
**Node.js HTTP interceptor** — for server-side apps that use `http`/`https` instead of `fetch`:
176+
177+
```ts
178+
import {
179+
installNodeHttpInterceptor,
180+
uninstallNodeHttpInterceptor,
181+
} from '@wolfcola/devtools-bridge';
182+
183+
installNodeHttpInterceptor((entry) => {
184+
client.sendNetworkEvent(entry);
185+
});
186+
187+
// Later:
188+
uninstallNodeHttpInterceptor();
189+
```
190+
191+
---
192+
137193
## Low-level API
138194

139195
If you need to emit events from outside a supported client, use the primitives directly.
@@ -191,10 +247,26 @@ Your app
191247
│ Runtime.bindingCalled('__wolfcolaBridge', payload)
192248
193249
VS Code extension host ──▶ TreeView + WebView (Elm)
250+
251+
── OR (Standalone debugger) ──
252+
253+
Your app
254+
└── attachDebugger({ name: 'my-app' })
255+
256+
│ WebSocket to ws://localhost:19417
257+
│ HANDSHAKE → SDK_EVENT / NETWORK_EVENT
258+
259+
Electron main process ──▶ SessionManager ──▶ EventStore
260+
261+
│ IPC (wolfcola:event, wolfcola:diagnosis)
262+
263+
Electron renderer ──▶ Elm UI (same panel as extension)
194264
```
195265

196266
The VS Code extension captures SDK events via a CDP-injected script that listens for the same `__pingDevtools` postMessage — no browser extension needed.
197267

268+
The standalone debugger receives events over WebSocket. `attachDebugger()` handles connection, auto-launch, and network interception automatically.
269+
198270
Each bridge function:
199271

200272
1. Subscribes to the client store
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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

Comments
 (0)