opengstack 0.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +47 -0
- package/CLAUDE.md +370 -0
- package/LICENSE +21 -0
- package/README.md +80 -0
- package/SKILL.md +226 -0
- package/autoplan/SKILL.md +96 -0
- package/autoplan/SKILL.md.tmpl +694 -0
- package/benchmark/SKILL.md +358 -0
- package/benchmark/SKILL.md.tmpl +222 -0
- package/browse/SKILL.md +396 -0
- package/browse/SKILL.md.tmpl +131 -0
- package/canary/SKILL.md +89 -0
- package/canary/SKILL.md.tmpl +212 -0
- package/careful/SKILL.md +58 -0
- package/careful/SKILL.md.tmpl +56 -0
- package/codex/SKILL.md +90 -0
- package/codex/SKILL.md.tmpl +417 -0
- package/connect-chrome/SKILL.md +87 -0
- package/connect-chrome/SKILL.md.tmpl +195 -0
- package/cso/SKILL.md +93 -0
- package/cso/SKILL.md.tmpl +606 -0
- package/design-consultation/SKILL.md +94 -0
- package/design-consultation/SKILL.md.tmpl +415 -0
- package/design-review/SKILL.md +94 -0
- package/design-review/SKILL.md.tmpl +290 -0
- package/design-shotgun/SKILL.md +91 -0
- package/design-shotgun/SKILL.md.tmpl +285 -0
- package/docs/designs/CHROME_VS_CHROMIUM_EXPLORATION.md +84 -0
- package/docs/designs/CONDUCTOR_CHROME_SIDEBAR_INTEGRATION.md +57 -0
- package/docs/designs/CONDUCTOR_SESSION_API.md +108 -0
- package/docs/designs/DESIGN_SHOTGUN.md +451 -0
- package/docs/designs/DESIGN_TOOLS_V1.md +622 -0
- package/docs/skills.md +880 -0
- package/document-release/SKILL.md +91 -0
- package/document-release/SKILL.md.tmpl +359 -0
- package/freeze/SKILL.md +78 -0
- package/freeze/SKILL.md.tmpl +77 -0
- package/gstack-upgrade/SKILL.md +224 -0
- package/gstack-upgrade/SKILL.md.tmpl +222 -0
- package/guard/SKILL.md +78 -0
- package/guard/SKILL.md.tmpl +77 -0
- package/investigate/SKILL.md +105 -0
- package/investigate/SKILL.md.tmpl +194 -0
- package/land-and-deploy/SKILL.md +88 -0
- package/land-and-deploy/SKILL.md.tmpl +881 -0
- package/office-hours/SKILL.md +96 -0
- package/office-hours/SKILL.md.tmpl +645 -0
- package/package.json +43 -0
- package/plan-ceo-review/SKILL.md +94 -0
- package/plan-ceo-review/SKILL.md.tmpl +811 -0
- package/plan-design-review/SKILL.md +92 -0
- package/plan-design-review/SKILL.md.tmpl +446 -0
- package/plan-eng-review/SKILL.md +93 -0
- package/plan-eng-review/SKILL.md.tmpl +303 -0
- package/qa/SKILL.md +95 -0
- package/qa/SKILL.md.tmpl +316 -0
- package/qa-only/SKILL.md +89 -0
- package/qa-only/SKILL.md.tmpl +101 -0
- package/retro/SKILL.md +89 -0
- package/retro/SKILL.md.tmpl +820 -0
- package/review/SKILL.md +92 -0
- package/review/SKILL.md.tmpl +281 -0
- package/scripts/cleanup.py +100 -0
- package/scripts/filter-skills.sh +114 -0
- package/scripts/filter_skills.py +140 -0
- package/setup-browser-cookies/SKILL.md +216 -0
- package/setup-browser-cookies/SKILL.md.tmpl +81 -0
- package/setup-deploy/SKILL.md +92 -0
- package/setup-deploy/SKILL.md.tmpl +215 -0
- package/ship/SKILL.md +90 -0
- package/ship/SKILL.md.tmpl +636 -0
- package/unfreeze/SKILL.md +37 -0
- package/unfreeze/SKILL.md.tmpl +36 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Chrome vs Chromium: Why We Use Playwright's Bundled Chromium
|
|
2
|
+
|
|
3
|
+
## The Original Vision
|
|
4
|
+
|
|
5
|
+
When we built `$B connect`, the plan was to connect to the user's **real Chrome browser** — the one with their cookies, sessions, extensions, and open tabs. No more cookie import. The design called for:
|
|
6
|
+
|
|
7
|
+
1. `chromium.connectOverCDP(wsUrl)` connecting to a running Chrome via CDP
|
|
8
|
+
2. Quit Chrome gracefully, relaunch with `--remote-debugging-port=9222`
|
|
9
|
+
3. Access the user's real browsing context
|
|
10
|
+
|
|
11
|
+
This is why `chrome-launcher.ts` existed (361 LOC of browser binary discovery, CDP port probing, and runtime detection) and why the method was called `connectCDP()`.
|
|
12
|
+
|
|
13
|
+
## What Actually Happened
|
|
14
|
+
|
|
15
|
+
Real Chrome silently blocks `--load-extension` when launched via Playwright's `channel: 'chrome'`. The extension wouldn't load. We needed the extension for the side panel (activity feed, refs, chat).
|
|
16
|
+
|
|
17
|
+
The implementation fell back to `chromium.launchPersistentContext()` with Playwright's bundled Chromium — which reliably loads extensions via `--load-extension` and `--disable-extensions-except`. But the naming stayed: `connectCDP()`, `connectionMode: 'cdp'`, `BROWSE_CDP_URL`, `chrome-launcher.ts`.
|
|
18
|
+
|
|
19
|
+
The original vision (access user's real browser state) was never implemented. We launched a fresh browser every time — functionally identical to Playwright's Chromium, but with 361 lines of dead code and misleading names.
|
|
20
|
+
|
|
21
|
+
## The Discovery (2026-03-22)
|
|
22
|
+
|
|
23
|
+
During a `/office-hours` design session, we traced the architecture and discovered:
|
|
24
|
+
|
|
25
|
+
1. `connectCDP()` doesn't use CDP — it calls `launchPersistentContext()`
|
|
26
|
+
2. `connectionMode: 'cdp'` is misleading — it's just "headed mode"
|
|
27
|
+
3. `chrome-launcher.ts` is dead code — its only import was in an unreachable `attemptReconnect()` method
|
|
28
|
+
4. `preExistingTabIds` was designed for protecting real Chrome tabs we never connect to
|
|
29
|
+
5. `$B handoff` (headless → headed) used a different API (`launch()` + `newContext()`) that couldn't load extensions, creating two different "headed" experiences
|
|
30
|
+
|
|
31
|
+
## The Fix
|
|
32
|
+
|
|
33
|
+
### Renamed
|
|
34
|
+
- `connectCDP()` → `launchHeaded()`
|
|
35
|
+
- `connectionMode: 'cdp'` → `connectionMode: 'headed'`
|
|
36
|
+
- `BROWSE_CDP_URL` → `BROWSE_HEADED`
|
|
37
|
+
|
|
38
|
+
### Deleted
|
|
39
|
+
- `chrome-launcher.ts` (361 LOC)
|
|
40
|
+
- `attemptReconnect()` (dead method)
|
|
41
|
+
- `preExistingTabIds` (dead concept)
|
|
42
|
+
- `reconnecting` field (dead state)
|
|
43
|
+
- `cdp-connect.test.ts` (tests for deleted code)
|
|
44
|
+
|
|
45
|
+
### Converged
|
|
46
|
+
- `$B handoff` now uses `launchPersistentContext()` + extension loading (same as `$B connect`)
|
|
47
|
+
- One headed mode, not two
|
|
48
|
+
- Handoff gives you the extension + side panel for free
|
|
49
|
+
|
|
50
|
+
### Gated
|
|
51
|
+
- Sidebar chat behind `--chat` flag
|
|
52
|
+
- `$B connect` (default): activity feed + refs only
|
|
53
|
+
- `$B connect --chat`: + experimental standalone chat agent
|
|
54
|
+
|
|
55
|
+
## Architecture (after)
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Browser States:
|
|
59
|
+
HEADLESS (default) ←→ HEADED ($B connect or $B handoff)
|
|
60
|
+
Playwright Playwright (same engine)
|
|
61
|
+
launch() launchPersistentContext()
|
|
62
|
+
invisible visible + extension + side panel
|
|
63
|
+
|
|
64
|
+
Sidebar (orthogonal add-on, headed only):
|
|
65
|
+
Activity tab — always on, shows live browse commands
|
|
66
|
+
Refs tab — always on, shows @ref overlays
|
|
67
|
+
Chat tab — opt-in via --chat, experimental standalone agent
|
|
68
|
+
|
|
69
|
+
Data Bridge (sidebar → workspace):
|
|
70
|
+
Sidebar writes to .context/sidebar-inbox/*.json
|
|
71
|
+
Workspace reads via $B inbox
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Why Not Real Chrome?
|
|
75
|
+
|
|
76
|
+
Real Chrome blocks `--load-extension` when launched by Playwright. This is a Chrome security feature — extensions loaded via command-line args are restricted in Chromium-based browsers to prevent malicious extension injection.
|
|
77
|
+
|
|
78
|
+
Playwright's bundled Chromium doesn't have this restriction because it's designed for testing and automation. The `ignoreDefaultArgs` option lets us bypass Playwright's own extension-blocking flags.
|
|
79
|
+
|
|
80
|
+
If we ever want to access the user's real cookies/sessions, the path is:
|
|
81
|
+
1. Cookie import (already works via `$B cookie-import`)
|
|
82
|
+
2. Conductor session injection (future — sidebar sends messages to workspace agent)
|
|
83
|
+
|
|
84
|
+
Not reconnecting to real Chrome.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Chrome Sidebar + Conductor: What We Need
|
|
2
|
+
|
|
3
|
+
## What we're building
|
|
4
|
+
|
|
5
|
+
Right now when Claude is working in a Conductor workspace — editing files, running tests, browsing your app — you can only watch from Conductor's chat window. If Claude is doing QA on your website, you see tool calls scrolling by but you can't actually *see* the browser.
|
|
6
|
+
|
|
7
|
+
We built a Chrome sidebar that fixes this. When you run `$B connect`, Chrome opens with a side panel that shows everything Claude is doing in real time. You can type messages in the sidebar and Claude acts on them — "click the signup button", "go to the settings page", "summarize what you see."
|
|
8
|
+
|
|
9
|
+
The problem: the sidebar currently runs its own separate Claude instance. It can't see what the main Conductor session is doing, and the main session can't see what the sidebar is doing. They're two separate agents that don't talk to each other.
|
|
10
|
+
|
|
11
|
+
The fix is simple: make the sidebar a *window into* the Conductor session, not a separate thing.
|
|
12
|
+
|
|
13
|
+
## What we need from Conductor (3 things)
|
|
14
|
+
|
|
15
|
+
### 1. Let us watch what the agent is doing
|
|
16
|
+
|
|
17
|
+
We need a way to subscribe to the active session's events. Something like an SSE stream or WebSocket that sends us events as they happen:
|
|
18
|
+
|
|
19
|
+
- "Claude is editing `src/App.tsx`"
|
|
20
|
+
- "Claude is running `npm test`"
|
|
21
|
+
- "Claude says: I'll fix the CSS issue..."
|
|
22
|
+
|
|
23
|
+
The sidebar already knows how to render these events — tool calls show as compact badges, text shows as chat bubbles. We just need a pipe from Conductor's session to our extension.
|
|
24
|
+
|
|
25
|
+
### 2. Let us send messages into the session
|
|
26
|
+
|
|
27
|
+
When the user types "click the other button" in the Chrome sidebar, that message should appear in the Conductor session as if the user typed it in the workspace chat. The agent picks it up on its next turn and acts on it.
|
|
28
|
+
|
|
29
|
+
This is the magic moment: user is watching Chrome, sees something wrong, types a correction in the sidebar, and Claude responds — without the user ever switching windows.
|
|
30
|
+
|
|
31
|
+
### 3. Let us create a workspace from a directory
|
|
32
|
+
|
|
33
|
+
When `$B connect` launches, it creates a git worktree for file isolation. We want to register that worktree as a Conductor workspace so the user can see the sidebar agent's file changes in Conductor's file tree. This also sets up the foundation for multiple browser sessions, each with their own workspace.
|
|
34
|
+
|
|
35
|
+
## Why this matters
|
|
36
|
+
|
|
37
|
+
Today, `/qa` and `/design-review` feel like a black box. Claude says "I found 3 issues" but you can't see what it's looking at. With the sidebar connected to Conductor:
|
|
38
|
+
|
|
39
|
+
- **You watch Claude test your app** in real time — every click, every navigation, every screenshot appears in Chrome while you watch
|
|
40
|
+
- **You can interrupt** — "no, test the mobile view" or "skip that page" — without switching windows
|
|
41
|
+
- **One agent, two views** — the same Claude that's editing your code is also controlling the browser. No context duplication, no stale state
|
|
42
|
+
|
|
43
|
+
## What's already built (gstack side)
|
|
44
|
+
|
|
45
|
+
Everything on our side is done and shipping:
|
|
46
|
+
|
|
47
|
+
- Chrome extension that auto-loads when you run `$B connect`
|
|
48
|
+
- Side panel that auto-opens (zero setup for the user)
|
|
49
|
+
- Streaming event renderer (tool calls, text, results)
|
|
50
|
+
- Chat input with message queuing
|
|
51
|
+
- Reconnect logic with status banners
|
|
52
|
+
- Session management with persistent chat history
|
|
53
|
+
- Agent lifecycle (spawn, stop, kill, timeout detection)
|
|
54
|
+
|
|
55
|
+
The only change on our side: swap the data source from "local `claude -p` subprocess" to "Conductor session stream." The extension code stays the same.
|
|
56
|
+
|
|
57
|
+
**Estimated effort:** 2-3 days Conductor engineering, 1 day gstack integration.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Conductor Session Streaming API Proposal
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
When Claude controls your real browser via CDP (gstack `$B connect`), you look at two
|
|
6
|
+
windows: **Conductor** (to see Claude's thinking) and **Chrome** (to see Claude's actions).
|
|
7
|
+
|
|
8
|
+
gstack's Chrome extension Side Panel shows browse activity — every command, result,
|
|
9
|
+
and error. But for *full* session mirroring (Claude's thinking, tool calls, code edits),
|
|
10
|
+
the Side Panel needs Conductor to expose the conversation stream.
|
|
11
|
+
|
|
12
|
+
## What this enables
|
|
13
|
+
|
|
14
|
+
A "Session" tab in the gstack Chrome extension Side Panel that shows:
|
|
15
|
+
- Claude's thinking/content (truncated for performance)
|
|
16
|
+
- Tool call names + icons (Edit, Bash, Read, etc.)
|
|
17
|
+
- Turn boundaries with cost estimates
|
|
18
|
+
- Real-time updates as the conversation progresses
|
|
19
|
+
|
|
20
|
+
The user sees everything in one place — Claude's actions in their browser + Claude's
|
|
21
|
+
thinking in the Side Panel — without switching windows.
|
|
22
|
+
|
|
23
|
+
## Proposed API
|
|
24
|
+
|
|
25
|
+
### `GET http://127.0.0.1:{PORT}/workspace/{ID}/session/stream`
|
|
26
|
+
|
|
27
|
+
Server-Sent Events endpoint that re-emits Claude Code's conversation as NDJSON events.
|
|
28
|
+
|
|
29
|
+
**Event types** (reuse Claude Code's `--output-format stream-json` format):
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
event: assistant
|
|
33
|
+
data: {"type":"assistant","content":"Let me check that page...","truncated":true}
|
|
34
|
+
|
|
35
|
+
event: tool_use
|
|
36
|
+
data: {"type":"tool_use","name":"Bash","input":"$B snapshot","truncated_input":true}
|
|
37
|
+
|
|
38
|
+
event: tool_result
|
|
39
|
+
data: {"type":"tool_result","name":"Bash","output":"[snapshot output...]","truncated_output":true}
|
|
40
|
+
|
|
41
|
+
event: turn_complete
|
|
42
|
+
data: {"type":"turn_complete","input_tokens":1234,"output_tokens":567,"cost_usd":0.02}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Content truncation:** Tool inputs/outputs capped at 500 chars in the stream. Full
|
|
46
|
+
data stays in Conductor's UI. The Side Panel is a summary view, not a replacement.
|
|
47
|
+
|
|
48
|
+
### `GET http://127.0.0.1:{PORT}/api/workspaces`
|
|
49
|
+
|
|
50
|
+
Discovery endpoint listing active workspaces.
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"workspaces": [
|
|
55
|
+
{
|
|
56
|
+
"id": "abc123",
|
|
57
|
+
"name": "gstack",
|
|
58
|
+
"branch": "garrytan/chrome-extension-ctrl",
|
|
59
|
+
"directory": "/Users/garry/gstack",
|
|
60
|
+
"pid": 12345,
|
|
61
|
+
"active": true
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The Chrome extension auto-selects a workspace by matching the browse server's git repo
|
|
68
|
+
(from `/health` response) to a workspace's directory or name.
|
|
69
|
+
|
|
70
|
+
## Security
|
|
71
|
+
|
|
72
|
+
- **Localhost-only.** Same trust model as Claude Code's own debug output.
|
|
73
|
+
- **No auth required.** If Conductor wants auth, include a Bearer token in the
|
|
74
|
+
workspace listing that the extension passes on SSE requests.
|
|
75
|
+
- **Content truncation** is a privacy feature — long code outputs, file contents, and
|
|
76
|
+
sensitive tool results never leave Conductor's full UI.
|
|
77
|
+
|
|
78
|
+
## What gstack builds (extension side)
|
|
79
|
+
|
|
80
|
+
Already scaffolded in the Side Panel "Session" tab (currently shows placeholder).
|
|
81
|
+
|
|
82
|
+
When Conductor's API is available:
|
|
83
|
+
1. Side Panel discovers Conductor via port probe or manual entry
|
|
84
|
+
2. Fetches `/api/workspaces`, matches to browse server's repo
|
|
85
|
+
3. Opens `EventSource` to `/workspace/{id}/session/stream`
|
|
86
|
+
4. Renders: assistant messages, tool names + icons, turn boundaries, cost
|
|
87
|
+
5. Falls back gracefully: "Connect Conductor for full session view"
|
|
88
|
+
|
|
89
|
+
Estimated effort: ~200 LOC in `sidepanel.js`.
|
|
90
|
+
|
|
91
|
+
## What Conductor builds (server side)
|
|
92
|
+
|
|
93
|
+
1. SSE endpoint that re-emits Claude Code's stream-json per workspace
|
|
94
|
+
2. `/api/workspaces` discovery endpoint with active workspace list
|
|
95
|
+
3. Content truncation (500 char cap on tool inputs/outputs)
|
|
96
|
+
|
|
97
|
+
Estimated effort: ~100-200 LOC if Conductor already captures the Claude Code stream
|
|
98
|
+
internally (which it does for its own UI rendering).
|
|
99
|
+
|
|
100
|
+
## Design decisions
|
|
101
|
+
|
|
102
|
+
| Decision | Choice | Rationale |
|
|
103
|
+
|----------|--------|-----------|
|
|
104
|
+
| Transport | SSE (not WebSocket) | Unidirectional, auto-reconnect, simpler |
|
|
105
|
+
| Format | Claude's stream-json | Conductor already parses this; no new schema |
|
|
106
|
+
| Discovery | HTTP endpoint (not file) | Chrome extensions can't read filesystem |
|
|
107
|
+
| Auth | None (localhost) | Same as browse server, CDP port, Claude Code |
|
|
108
|
+
| Truncation | 500 chars | Side Panel is ~300px wide; long content useless |
|