patchwork-os 0.2.0-beta.1 → 0.2.0-beta.3

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.
Files changed (191) hide show
  1. package/README.bridge.md +5 -5
  2. package/README.md +156 -12
  3. package/deploy/deploy-dashboard.sh +25 -1
  4. package/deploy/macos/README.md +153 -0
  5. package/deploy/macos/com.patchwork.bridge.plist.template +54 -0
  6. package/deploy/macos/com.patchwork.tunnel.plist.template +76 -0
  7. package/deploy/macos/install-mac-bridge.sh +244 -0
  8. package/deploy/macos/uninstall-mac-bridge.sh +22 -0
  9. package/dist/activityLog.d.ts +6 -0
  10. package/dist/activityLog.js +8 -0
  11. package/dist/activityLog.js.map +1 -1
  12. package/dist/analyticsPrefs.d.ts +35 -2
  13. package/dist/analyticsPrefs.js +120 -21
  14. package/dist/analyticsPrefs.js.map +1 -1
  15. package/dist/analyticsSend.js +5 -1
  16. package/dist/analyticsSend.js.map +1 -1
  17. package/dist/approvalHttp.d.ts +14 -0
  18. package/dist/approvalHttp.js +172 -1
  19. package/dist/approvalHttp.js.map +1 -1
  20. package/dist/approvalQueue.d.ts +27 -2
  21. package/dist/approvalQueue.js +44 -7
  22. package/dist/approvalQueue.js.map +1 -1
  23. package/dist/automation.d.ts +34 -3
  24. package/dist/automation.js +85 -10
  25. package/dist/automation.js.map +1 -1
  26. package/dist/bridge.d.ts +2 -0
  27. package/dist/bridge.js +114 -8
  28. package/dist/bridge.js.map +1 -1
  29. package/dist/bridgeLockDiscovery.d.ts +27 -1
  30. package/dist/bridgeLockDiscovery.js +37 -11
  31. package/dist/bridgeLockDiscovery.js.map +1 -1
  32. package/dist/claudeOrchestrator.js +5 -2
  33. package/dist/claudeOrchestrator.js.map +1 -1
  34. package/dist/commands/patchworkInit.d.ts +5 -0
  35. package/dist/commands/patchworkInit.js +86 -7
  36. package/dist/commands/patchworkInit.js.map +1 -1
  37. package/dist/commands/recipe.d.ts +51 -0
  38. package/dist/commands/recipe.js +363 -3
  39. package/dist/commands/recipe.js.map +1 -1
  40. package/dist/commands/recipeInstall.js +6 -3
  41. package/dist/commands/recipeInstall.js.map +1 -1
  42. package/dist/commands/task.js +2 -2
  43. package/dist/commands/task.js.map +1 -1
  44. package/dist/config.d.ts +17 -2
  45. package/dist/config.js +54 -17
  46. package/dist/config.js.map +1 -1
  47. package/dist/connectors/baseConnector.js +25 -3
  48. package/dist/connectors/baseConnector.js.map +1 -1
  49. package/dist/connectors/tokenStorage.js +46 -10
  50. package/dist/connectors/tokenStorage.js.map +1 -1
  51. package/dist/drivers/gemini/index.d.ts +22 -0
  52. package/dist/drivers/gemini/index.js +240 -129
  53. package/dist/drivers/gemini/index.js.map +1 -1
  54. package/dist/drivers/local/index.d.ts +17 -0
  55. package/dist/drivers/local/index.js +99 -0
  56. package/dist/drivers/local/index.js.map +1 -1
  57. package/dist/drivers/openai/index.js +30 -2
  58. package/dist/drivers/openai/index.js.map +1 -1
  59. package/dist/extensionClient.d.ts +8 -0
  60. package/dist/extensionClient.js +24 -2
  61. package/dist/extensionClient.js.map +1 -1
  62. package/dist/featureFlags.d.ts +76 -0
  63. package/dist/featureFlags.js +166 -2
  64. package/dist/featureFlags.js.map +1 -1
  65. package/dist/fp/automationInterpreter.d.ts +9 -1
  66. package/dist/fp/automationInterpreter.js +151 -34
  67. package/dist/fp/automationInterpreter.js.map +1 -1
  68. package/dist/fp/automationProgram.d.ts +30 -0
  69. package/dist/fp/automationProgram.js.map +1 -1
  70. package/dist/fp/automationState.d.ts +23 -4
  71. package/dist/fp/automationState.js +28 -4
  72. package/dist/fp/automationState.js.map +1 -1
  73. package/dist/fp/interpreterContext.d.ts +66 -1
  74. package/dist/fp/interpreterContext.js +140 -1
  75. package/dist/fp/interpreterContext.js.map +1 -1
  76. package/dist/fp/policyParser.js +29 -1
  77. package/dist/fp/policyParser.js.map +1 -1
  78. package/dist/index.js +765 -69
  79. package/dist/index.js.map +1 -1
  80. package/dist/lockfile.js +4 -1
  81. package/dist/lockfile.js.map +1 -1
  82. package/dist/oauth.d.ts +9 -0
  83. package/dist/oauth.js +33 -0
  84. package/dist/oauth.js.map +1 -1
  85. package/dist/patchworkConfig.d.ts +16 -0
  86. package/dist/patchworkConfig.js +5 -0
  87. package/dist/patchworkConfig.js.map +1 -1
  88. package/dist/recipeOrchestration.js +35 -1
  89. package/dist/recipeOrchestration.js.map +1 -1
  90. package/dist/recipeRoutes.d.ts +36 -0
  91. package/dist/recipeRoutes.js +231 -32
  92. package/dist/recipeRoutes.js.map +1 -1
  93. package/dist/recipes/agentExecutor.d.ts +25 -5
  94. package/dist/recipes/agentExecutor.js.map +1 -1
  95. package/dist/recipes/chainedRunner.js +16 -2
  96. package/dist/recipes/chainedRunner.js.map +1 -1
  97. package/dist/recipes/connectorPreflight.d.ts +53 -0
  98. package/dist/recipes/connectorPreflight.js +79 -0
  99. package/dist/recipes/connectorPreflight.js.map +1 -0
  100. package/dist/recipes/githubInstallSource.d.ts +62 -0
  101. package/dist/recipes/githubInstallSource.js +125 -0
  102. package/dist/recipes/githubInstallSource.js.map +1 -0
  103. package/dist/recipes/haltCategory.d.ts +80 -0
  104. package/dist/recipes/haltCategory.js +125 -0
  105. package/dist/recipes/haltCategory.js.map +1 -0
  106. package/dist/recipes/idempotencyKey.d.ts +126 -0
  107. package/dist/recipes/idempotencyKey.js +298 -0
  108. package/dist/recipes/idempotencyKey.js.map +1 -0
  109. package/dist/recipes/judgeSummary.d.ts +50 -0
  110. package/dist/recipes/judgeSummary.js +47 -0
  111. package/dist/recipes/judgeSummary.js.map +1 -0
  112. package/dist/recipes/judgeVerdict.d.ts +48 -0
  113. package/dist/recipes/judgeVerdict.js +174 -0
  114. package/dist/recipes/judgeVerdict.js.map +1 -0
  115. package/dist/recipes/migrations/index.d.ts +9 -0
  116. package/dist/recipes/migrations/index.js +133 -0
  117. package/dist/recipes/migrations/index.js.map +1 -1
  118. package/dist/recipes/runBudget.d.ts +70 -0
  119. package/dist/recipes/runBudget.js +109 -0
  120. package/dist/recipes/runBudget.js.map +1 -0
  121. package/dist/recipes/scheduler.d.ts +7 -0
  122. package/dist/recipes/scheduler.js +31 -14
  123. package/dist/recipes/scheduler.js.map +1 -1
  124. package/dist/recipes/schema.d.ts +36 -0
  125. package/dist/recipes/toolRegistry.js +19 -0
  126. package/dist/recipes/toolRegistry.js.map +1 -1
  127. package/dist/recipes/tools/file.js +5 -2
  128. package/dist/recipes/tools/file.js.map +1 -1
  129. package/dist/recipes/tools/http.d.ts +10 -0
  130. package/dist/recipes/tools/http.js +176 -0
  131. package/dist/recipes/tools/http.js.map +1 -0
  132. package/dist/recipes/tools/index.d.ts +1 -0
  133. package/dist/recipes/tools/index.js +1 -0
  134. package/dist/recipes/tools/index.js.map +1 -1
  135. package/dist/recipes/validation.js +1 -1
  136. package/dist/recipes/validation.js.map +1 -1
  137. package/dist/recipes/yamlRunner.d.ts +88 -7
  138. package/dist/recipes/yamlRunner.js +216 -25
  139. package/dist/recipes/yamlRunner.js.map +1 -1
  140. package/dist/recipesHttp.d.ts +3 -1
  141. package/dist/recipesHttp.js +9 -3
  142. package/dist/recipesHttp.js.map +1 -1
  143. package/dist/runLog.d.ts +28 -0
  144. package/dist/runLog.js +5 -0
  145. package/dist/runLog.js.map +1 -1
  146. package/dist/server.d.ts +111 -1
  147. package/dist/server.js +480 -6
  148. package/dist/server.js.map +1 -1
  149. package/dist/streamableHttp.d.ts +9 -4
  150. package/dist/streamableHttp.js +34 -15
  151. package/dist/streamableHttp.js.map +1 -1
  152. package/dist/tools/bridgeDoctor.js +6 -2
  153. package/dist/tools/bridgeDoctor.js.map +1 -1
  154. package/dist/tools/ccRoutines.d.ts +221 -0
  155. package/dist/tools/ccRoutines.js +264 -0
  156. package/dist/tools/ccRoutines.js.map +1 -0
  157. package/dist/tools/getCodeCoverage.js +7 -3
  158. package/dist/tools/getCodeCoverage.js.map +1 -1
  159. package/dist/tools/index.js +6 -0
  160. package/dist/tools/index.js.map +1 -1
  161. package/dist/tools/openInBrowser.js +6 -1
  162. package/dist/tools/openInBrowser.js.map +1 -1
  163. package/dist/tools/recentTracesDigest.js +56 -11
  164. package/dist/tools/recentTracesDigest.js.map +1 -1
  165. package/dist/tools/testRunners/vitestJest.js +3 -1
  166. package/dist/tools/testRunners/vitestJest.js.map +1 -1
  167. package/dist/tools/utils.js +13 -7
  168. package/dist/tools/utils.js.map +1 -1
  169. package/package.json +16 -5
  170. package/scripts/postinstall.mjs +27 -0
  171. package/scripts/smoke/run-all.mjs +162 -0
  172. package/scripts/start-all.mjs +513 -0
  173. package/scripts/start-all.ps1 +209 -0
  174. package/scripts/start-all.sh +73 -17
  175. package/scripts/start-orchestrator.ps1 +158 -0
  176. package/scripts/start-remote.mjs +122 -0
  177. package/templates/automation-policies/recipe-authoring.json +1 -1
  178. package/templates/automation-policies/security-first.json +1 -1
  179. package/templates/automation-policies/strict-lint.json +1 -1
  180. package/templates/automation-policies/test-driven.json +1 -1
  181. package/templates/automation-policy.example.json +1 -1
  182. package/templates/co.patchwork-os.bridge.plist +1 -1
  183. package/templates/recipes/approval-queue-ui-test.yaml +1 -1
  184. package/templates/recipes/ctx-loop-test.yaml +1 -1
  185. package/templates/recipes/webhook/apple-watch-health-log.yaml +145 -0
  186. package/dist/commands/marketplace.d.ts +0 -16
  187. package/dist/commands/marketplace.js +0 -32
  188. package/dist/commands/marketplace.js.map +0 -1
  189. package/dist/recipes/legacyRecipeCompat.d.ts +0 -10
  190. package/dist/recipes/legacyRecipeCompat.js +0 -131
  191. package/dist/recipes/legacyRecipeCompat.js.map +0 -1
package/README.bridge.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![Docker](https://img.shields.io/badge/docker-ghcr.io%2FOolab--labs%2Fclaude--ide--bridge-blue)](https://github.com/Oolab-labs/claude-ide-bridge/pkgs/container/claude-ide-bridge)
6
6
  [![License: MIT](https://img.shields.io/npm/l/claude-ide-bridge)](https://opensource.org/licenses/MIT)
7
7
 
8
- **MCP bridge giving Claude Code IDE superpowers: 141 tools for LSP, debugging, git, GitHub, terminals, and more.**
8
+ **MCP bridge giving Claude Code IDE superpowers 170+ tools for LSP, debugging, git, GitHub, terminals, and more (see [platform-docs](documents/platform-docs.md) for the full list).**
9
9
 
10
10
  A WebSocket bridge between Claude Code CLI and your VS Code extension. Claude sees what your IDE sees — live diagnostics, go-to-definition, call hierarchies, hover types, breakpoints, debugger state — and can act on it: edit files, run tests, commit, open PRs, all without you copy-pasting anything.
11
11
 
@@ -192,7 +192,7 @@ claude-ide-bridge start-task "Refactor the auth module for clarity, keep behavio
192
192
  claude-ide-bridge continue-handoff
193
193
  ```
194
194
 
195
- Requires `--claude-driver subprocess` on the running bridge. All three subcommands accept `--json`, `--port`, `--source`. Enforces a 5s bridge-global cooldown per preset (shared with the sidebar).
195
+ Requires `--driver subprocess` on the running bridge. All three subcommands accept `--json`, `--port`, `--source`. Enforces a 5s bridge-global cooldown per preset (shared with the sidebar).
196
196
 
197
197
  ---
198
198
 
@@ -223,7 +223,7 @@ Event-driven hooks that trigger Claude tasks automatically — no polling, no ma
223
223
 
224
224
  Start with:
225
225
  ```bash
226
- claude-ide-bridge --watch --automation --automation-policy ./policy.json --claude-driver subprocess
226
+ claude-ide-bridge --watch --automation --automation-policy ./policy.json --driver subprocess
227
227
  ```
228
228
 
229
229
  **18 hook events:** `onFileSave`, `onFileChanged`, `onDiagnosticsError`, `onDiagnosticsCleared`, `onGitCommit`, `onGitPush`, `onGitPull`, `onBranchCheckout`, `onPullRequest`, `onTestRun`, `onTestPassAfterFailure`, `onPostCompact`, `onInstructionsLoaded`, `onTaskCreated`, `onTaskSuccess`, `onPermissionDenied`, `onCwdChanged`, `onDebugSessionEnd`
@@ -299,7 +299,7 @@ claude-ide-bridge install claude-mem
299
299
  | `--fixed-token <uuid>` | — | Stable auth token across restarts |
300
300
  | `--automation` | off | Enable automation hooks |
301
301
  | `--automation-policy <path>` | — | Path to policy JSON |
302
- | `--claude-driver subprocess` | none | Enable Claude subprocess orchestration |
302
+ | `--driver subprocess` | none | Enable Claude subprocess orchestration |
303
303
  | `--plugin <path>` | — | Load a plugin (repeatable) |
304
304
  | `--plugin-watch` | off | Hot-reload plugins on change |
305
305
  | `--issuer-url <url>` | — | Activate OAuth 2.0 mode |
@@ -314,7 +314,7 @@ claude-ide-bridge install claude-mem
314
314
  | File | Description |
315
315
  |---|---|
316
316
  | [ARCHITECTURE.md](ARCHITECTURE.md) | System topology, request lifecycle, component map, design decisions |
317
- | [documents/platform-docs.md](documents/platform-docs.md) | Full tool reference — all 141 tools with parameters and examples |
317
+ | [documents/platform-docs.md](documents/platform-docs.md) | Full tool reference — all 170+ tools with parameters and examples |
318
318
  | [documents/prompts-reference.md](documents/prompts-reference.md) | All MCP prompts (31 prompts, 12 plugin skills, 4 subagents) |
319
319
  | [docs/automation.md](docs/automation.md) | Automation hooks reference — all 18 events, policy schema, condition filters |
320
320
  | [docs/troubleshooting.md](docs/troubleshooting.md) | Diagnostics, common errors, and fixes |
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  > Patchwork OS is a local-first personal AI runtime: pluggable model providers, hot-reloadable tools, YAML recipes, a delegation policy with approval queue, and a durable trace memory — all running on your machine, all under your policy.
6
6
 
7
- You decide which model. You decide which actions need a human nod. You own the credentials, the logs, and the deployment. Nothing phones home.
7
+ You decide which model. You decide which actions need a human nod. You own the credentials, the logs, and the deployment. Nothing phones home unless you [opt in to anonymous analytics](#telemetry).
8
8
 
9
9
  **Five primitives, one runtime:**
10
10
 
@@ -25,14 +25,38 @@ The same codebase ships **two ways to use it.** Pick the layer you need.
25
25
  | | What you get | Install | Best for |
26
26
  |---|---|---|---|
27
27
  | **🔌 Claude IDE Bridge** | MCP bridge connecting Claude Code to your IDE. 170+ tools — diagnostics, LSP, debugger, terminal, git, GitHub, file ops. | `npm i -g patchwork-os` then run `claude-ide-bridge` | Anyone who wants Claude Code to see and act on their editor state |
28
- | **🤖 Patchwork OS** | Everything in the bridge **plus** YAML recipes, approval queue, oversight dashboard, mobile push approvals, multi-model providers, JetBrains companion. | Same package, run `patchwork patchwork-init` | Power users running automation, agent workflows, or background tasks |
28
+ | **🤖 Patchwork OS** | Everything in the bridge **plus** YAML recipes, approval queue, oversight dashboard, mobile push approvals, multi-model providers, JetBrains companion. | Same package, run `patchwork init` | Power users running automation, agent workflows, or background tasks |
29
29
 
30
30
  Same codebase. Bridge is the foundation; Patchwork OS is the optional layer on top. **No vendor lock-in. Runs on your machine.**
31
31
 
32
32
  ---
33
33
 
34
+ ## Dashboard Only — No Code Editor Required
35
+
36
+ > You do not need VS Code, Windsurf, Cursor, or Claude Code CLI to use the Patchwork dashboard.
37
+
38
+ The dashboard is a standalone Next.js app that communicates with the bridge over HTTP. No editor extension required.
39
+
40
+ **Prereqs:** [Node.js 20+](https://nodejs.org) · tmux on macOS/Linux (`brew install tmux` / `apt install tmux`) — auto-detected, falls back to background mode if absent. **Windows:** natively supported — no WSL required.
41
+
42
+ ```bash
43
+ npm install -g patchwork-os
44
+ patchwork-os init # scaffolds ~/.patchwork and generates a dashboard login
45
+ patchwork start # launches bridge + dashboard (auto-detects tmux; falls back to background mode if absent)
46
+ ```
47
+
48
+ Open **http://localhost:3200** — that's it. `patchwork-os init` auto-generates a dashboard password and saves it to `~/.patchwork/.env` — it prints the password at the end of setup, save it for your first login.
49
+
50
+ **What you get:** run and schedule YAML recipes, connect external services (Gmail, Calendar, Slack), review AI drafts in the approval queue, read your AI inbox — all from the browser. No coding required.
51
+
52
+ > **Want IDE features too?** See [Claude IDE Bridge — Quick Start](#-claude-ide-bridge--quick-start) below to add LSP, debugger, and editor tools on top.
53
+
54
+ ---
55
+
34
56
  ## 🔌 Claude IDE Bridge — Quick Start
35
57
 
58
+ > Developers only — skip to [Dashboard Only](#dashboard-only--no-code-editor-required) above if you just want the web dashboard.
59
+
36
60
  **Prerequisites:** a supported code editor — **VS Code, Cursor, Windsurf, or Google Antigravity** (or JetBrains via the [companion plugin](#jetbrains-plugin)) — plus Node.js 20+ and the [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code). The bridge's LSP, debugger, and editor-state tools run through the editor extension; without one you're limited to the headless CLI subset.
37
61
 
38
62
  ```bash
@@ -72,7 +96,20 @@ The bridge runs without any flags. No recipes, no automation, no dashboard — j
72
96
  |---|---|
73
97
  | Claude Code CLI | WebSocket `ws://127.0.0.1:<port>` |
74
98
  | Claude Desktop | stdio shim → WebSocket |
75
- | Remote (claude.ai, Codex CLI) | Streamable HTTP + Bearer token |
99
+ | Gemini CLI, Codex CLI, claude.ai | Streamable HTTP + Bearer token |
100
+
101
+ **Connecting Gemini CLI:**
102
+
103
+ ```bash
104
+ # Get the auth token from the bridge's lock file
105
+ patchwork-os print-token
106
+
107
+ # Add the bridge as an MCP server
108
+ gemini mcp add patchwork http://127.0.0.1:<port>/mcp \
109
+ --header "Authorization: Bearer <token>"
110
+ ```
111
+
112
+ The bridge auto-responds to the GET probe Gemini sends before initializing, so it shows as **Connected** immediately.
76
113
 
77
114
  **Tool modes:**
78
115
 
@@ -85,10 +122,89 @@ Bridge-only docs: [documents/platform-docs.md](documents/platform-docs.md)
85
122
 
86
123
  ---
87
124
 
125
+ ## 🪟 Windows Quick Start
126
+
127
+ The bridge, VS Code extension, and full Patchwork OS orchestrator (`patchwork start`) all work natively on Windows — no WSL required. A PowerShell-native orchestrator is also available as `npm run start-all:win`.
128
+
129
+ ### Prerequisites
130
+
131
+ - Node.js 20+ (from [nodejs.org](https://nodejs.org))
132
+ - VS Code, Cursor, or Windsurf
133
+ - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code)
134
+ - PowerShell 5.1+ (built into Windows 10/11) or PowerShell 7+ (`pwsh`)
135
+
136
+ ### Bridge-only (recommended starting point)
137
+
138
+ Open **PowerShell** or **cmd.exe**:
139
+
140
+ ```powershell
141
+ # 1. Install
142
+ npm install -g patchwork-os
143
+
144
+ # 2. Install the VS Code extension
145
+ claude-ide-bridge install-extension
146
+
147
+ # 3. Start the bridge (bash-free entry point)
148
+ npm run start:bridge
149
+ # or equivalently:
150
+ node "$(npm root -g)/patchwork-os/dist/index.js" --workspace .
151
+
152
+ # 4. Connect Claude Code (new terminal)
153
+ claude --ide
154
+ ```
155
+
156
+ Type `/ide` in Claude Code to confirm the connection.
157
+
158
+ ### Full orchestrator (bridge + Claude + dashboard)
159
+
160
+ Two options — both work on Windows, macOS, and Linux:
161
+
162
+ ```powershell
163
+ # Option A: cross-platform Node.js orchestrator (recommended)
164
+ npm run start-all:node
165
+ npm run start-all:node -- --workspace C:\myproj --full --no-dashboard
166
+
167
+ # Option B: PowerShell-native orchestrator (Windows only, no Node wrapper overhead)
168
+ npm run start-all:win
169
+ npm run start-all:win -- -NoDashboard -Workspace C:\myproj -Full
170
+ ```
171
+
172
+ Both start the bridge, wait for the lock file, launch `claude --ide` and `remote-control`, start the Next.js dashboard on `http://localhost:3200`, poll until it's ready, then open it in your default browser. The health monitor restarts the bridge automatically if it crashes, with exponential backoff.
173
+
174
+ ```powershell
175
+ # Node orchestrator options (--key value form)
176
+ npm run start-all:node -- --full # all ~170 tools
177
+ npm run start-all:node -- --no-dashboard # skip dashboard
178
+ npm run start-all:node -- --dashboard-port 3300
179
+ npm run start-all:node -- --no-remote # skip remote-control
180
+ npm run start-all:node -- --notify my-topic # ntfy.sh push notifications
181
+ ```
182
+
183
+ ### Known limitations on native Windows
184
+
185
+ | Feature | Status |
186
+ |---|---|
187
+ | Bridge + extension (LSP, debugger, editor state) | ✅ Full support |
188
+ | `npm run start:bridge` | ✅ Supported |
189
+ | `npm run start-all:node` (Node.js orchestrator) | ✅ Supported — cross-platform |
190
+ | `npm run start-all:win` (PS1 orchestrator) | ✅ Supported — Windows-native |
191
+ | Dashboard (`http://localhost:3200`) | ✅ Opens automatically |
192
+ | `patchwork start` / `npm run start-all` | ⚠️ Requires WSL2 or Git Bash (uses bash + tmux) |
193
+ | `npm run remote:node` | ✅ Supported — cross-platform Node auto-restart wrapper |
194
+ | `npm run remote` / `npm run vps` | ⚠️ Requires WSL2 or Git Bash |
195
+ | Screenshot capture (standalone bridge) | ⚠️ Not yet supported; extension screenshot works via VS Code |
196
+ | Credential storage | ✅ Uses DPAPI (Windows Data Protection API) via PowerShell |
197
+
198
+ ### WSL2 alternative
199
+
200
+ For full Patchwork OS functionality including orchestrator, recipes, and morning-brief, run everything inside WSL2 and install the VS Code Remote-WSL extension. The bridge extension loads on the WSL side automatically (`extensionKind: ["workspace"]`), giving full tool coverage.
201
+
202
+ ---
203
+
88
204
  ## 🤖 Patchwork OS — Quick Start
89
205
 
90
206
  ```bash
91
- npx patchwork-os@beta patchwork-init
207
+ npx patchwork-os@beta init
92
208
  ```
93
209
 
94
210
  Sets up 5 local recipes, detects Ollama, and opens a terminal dashboard — under 90 seconds.
@@ -99,7 +215,7 @@ Get an AI digest of your Gmail, calendar, and tasks every morning — or on dema
99
215
 
100
216
  ```bash
101
217
  # First-time setup (connect Gmail + Google Calendar)
102
- patchwork-os patchwork-init
218
+ patchwork-os init
103
219
  patchwork-os connections connect gmail
104
220
  patchwork-os connections connect google-calendar
105
221
 
@@ -125,15 +241,15 @@ Think of it as a background agent that acts on your behalf — but asks before s
125
241
 
126
242
  **Recipes** are plain YAML files. They declare a trigger (cron, file save, git commit, test run, webhook) and an action (run a prompt, write to inbox, call a connector). No code required. Share them like dotfiles.
127
243
 
128
- **Models** are yours. Claude, GPT, Gemini, Grok, or local Ollama. Swap at any time. Nothing phones home.
244
+ **Models** are yours. Claude, GPT, Gemini, Grok, or local Ollama. Swap at any time. Nothing phones home unless you opt in (see [Telemetry](#telemetry)).
129
245
 
130
- **Oversight** is non-negotiable. Every write or external action lands in `~/.patchwork/inbox/` for approval. The web UI at `http://localhost:3200` shows pending approvals, live sessions, recipe run history, and analytics.
246
+ **Oversight** is non-negotiable. Every write or external action lands in `~/.patchwork/inbox/` for approval. The web UI at `http://localhost:3200` shows pending approvals, live sessions, recipe run history, and local analytics (the dashboard's analytics panel is computed entirely from on-disk logs — it does not transmit anything).
131
247
 
132
248
  ### Patchwork commands
133
249
 
134
250
  ```bash
135
251
  # One-command setup: extension + CLAUDE.md + starter recipes
136
- patchwork patchwork-init
252
+ patchwork init
137
253
 
138
254
  # Explore
139
255
  patchwork recipe list # installed recipes
@@ -173,7 +289,7 @@ The package ships these in `templates/recipes/`. Recipes that need API keys are
173
289
 
174
290
  ### Automation hooks
175
291
 
176
- Event-driven hooks trigger Claude tasks automatically. Activate with `--automation --automation-policy <path.json> --claude-driver subprocess`.
292
+ Event-driven hooks trigger Claude tasks automatically. Activate with `--automation --automation-policy <path.json> --driver subprocess`.
177
293
 
178
294
  Key hooks:
179
295
 
@@ -225,7 +341,7 @@ Use whichever fits your mental model.
225
341
 
226
342
  ---
227
343
 
228
- ## Tool surface (v0.2.0-beta.0)
344
+ ## Tool surface
229
345
 
230
346
  170+ MCP tools across 15 categories. Highlights:
231
347
 
@@ -296,7 +412,7 @@ Systemd service and deploy scripts in [`deploy/`](deploy/). Full guide: [docs/re
296
412
  | 170+ MCP tools (LSP, git, tests, debugger, diagnostics) | **shipped** |
297
413
  | VS Code / Cursor / Windsurf / Antigravity extension | **shipped** |
298
414
  | JetBrains plugin (49 handlers) | **shipped** |
299
- | `patchwork-init` — one-command setup | **shipped** |
415
+ | `patchwork init` — one-command setup | **shipped** |
300
416
  | Terminal dashboard | **shipped** |
301
417
  | Web oversight UI (approvals, sessions, recipes) | **shipped** |
302
418
  | Recipe runner (YAML, cron, manual, webhook) | **shipped** |
@@ -320,11 +436,32 @@ npm install && npm run build
320
436
  # Symlink installs break the macOS LaunchAgent (EPERM at startup)
321
437
  npm pack
322
438
  npm install -g patchwork-os-*.tgz
323
- patchwork patchwork-init
439
+ patchwork init
324
440
  ```
325
441
 
326
442
  ---
327
443
 
444
+ ## Telemetry
445
+
446
+ Patchwork ships an **opt-in** anonymous usage summary. It is **disabled by default** — the bridge sends nothing unless you explicitly turn it on.
447
+
448
+ **If you opt in**, on bridge shutdown an aggregate summary is POSTed to `https://analytics.claude-ide-bridge.dev/v1/usage`:
449
+
450
+ - Total session count and total tool-call count (no per-call payloads)
451
+ - Tool name → call count + median/p95 latency, capped at the top-N tools
452
+ - Bridge version, Node version, OS family (`darwin` / `linux` / `win32`)
453
+ - A per-install random salt (regenerated at any time by deleting `~/.claude/ide/analytics-salt`) used to coalesce repeated installs from the same machine without sending machine identifiers
454
+
455
+ **What is never sent:** workspace paths, file contents, prompts, tool arguments, tool output, project names, git history, credentials, IPs (transport-level only, dropped server-side), or anything from `~/.patchwork/`.
456
+
457
+ **How to opt in:** set `analyticsEnabled: true` in the dashboard's Settings panel, or write `{"enabled": true, "decidedAt": "<iso>"}` to `~/.claude/ide/analytics.json` (mode 0600).
458
+
459
+ **How to opt out / stay out:** do nothing. Default state is `null` (no preference) which behaves as opt-out. To explicitly opt out and silence future prompts, write `{"enabled": false, ...}` to the same file.
460
+
461
+ **Source:** [src/analyticsSend.ts](src/analyticsSend.ts), [src/analyticsAggregator.ts](src/analyticsAggregator.ts), [src/analyticsPrefs.ts](src/analyticsPrefs.ts) — endpoint is hardcoded (not runtime-configurable, by design, to prevent redirect attacks).
462
+
463
+ ---
464
+
328
465
  ## Documentation
329
466
 
330
467
  | Doc | Contents |
@@ -345,6 +482,13 @@ patchwork patchwork-init
345
482
 
346
483
  ---
347
484
 
485
+ ## Support
486
+
487
+ - **Bugs & feature requests:** [GitHub Issues](https://github.com/Oolab-labs/patchwork-os/issues)
488
+ - **Questions & community:** [GitHub Discussions](https://github.com/Oolab-labs/patchwork-os/discussions)
489
+
490
+ ---
491
+
348
492
  ## License
349
493
 
350
494
  MIT © Oolab Labs
@@ -39,9 +39,17 @@ echo "==> Copying tarball to VPS..."
39
39
  scp "$TARBALL" "$VPS:/tmp/patchwork-dashboard.tar.gz"
40
40
 
41
41
  echo "==> Deploying on VPS..."
42
+ # Pass secrets as positional args (NOT inside the heredoc body) so the
43
+ # single-quoted heredoc still preserves remote-shell `$X` references but
44
+ # the operator's local env reaches the VPS. Without this, the previous
45
+ # `${PATCHWORK_BRIDGE_TOKEN:-REPLACE_ME}` inside the heredoc evaluated on
46
+ # the remote, where the var doesn't exist, and always wrote REPLACE_ME.
42
47
  # shellcheck disable=SC2087
43
- ssh "$VPS" bash <<'REMOTE'
48
+ ssh "$VPS" bash -s -- "${PATCHWORK_BRIDGE_TOKEN:-REPLACE_ME}" "${DASHBOARD_PASSWORD:-}" <<'REMOTE'
44
49
  set -euo pipefail
50
+ # `${N:-}` so an empty/missing positional arg doesn't trip `set -u`.
51
+ PATCHWORK_BRIDGE_TOKEN="${1:-REPLACE_ME}"
52
+ DASHBOARD_PASSWORD="${2:-}"
45
53
  REMOTE_DIR="/opt/patchwork-dashboard"
46
54
  PM2_NAME="patchwork-dashboard"
47
55
  PORT=3200
@@ -52,10 +60,26 @@ if pm2 list | grep -q "$PM2_NAME"; then
52
60
  pm2 delete "$PM2_NAME" || true
53
61
  fi
54
62
 
63
+ # Preserve .env.local across the deploy. Without this stash/restore, the
64
+ # `rm -rf "$REMOTE_DIR"` below blows away every secret the operator pasted
65
+ # (VAPID, PATCHWORK_PUSH_TOKEN, custom DASHBOARD_PASSWORD), and the "if
66
+ # already exists, preserve" branch later in this script never fires —
67
+ # the file no longer exists by then.
68
+ ENV_BACKUP=""
69
+ if [ -f "$REMOTE_DIR/.env.local" ]; then
70
+ ENV_BACKUP="$(mktemp /tmp/patchwork-env.XXXXXX)"
71
+ cp -p "$REMOTE_DIR/.env.local" "$ENV_BACKUP"
72
+ fi
73
+
55
74
  # Wipe and recreate deploy dir
56
75
  rm -rf "$REMOTE_DIR"
57
76
  mkdir -p "$REMOTE_DIR"
58
77
 
78
+ if [ -n "$ENV_BACKUP" ] && [ -f "$ENV_BACKUP" ]; then
79
+ cp -p "$ENV_BACKUP" "$REMOTE_DIR/.env.local"
80
+ rm -f "$ENV_BACKUP"
81
+ fi
82
+
59
83
  # Extract
60
84
  tar -xzf /tmp/patchwork-dashboard.tar.gz -C "$REMOTE_DIR"
61
85
  rm /tmp/patchwork-dashboard.tar.gz
@@ -0,0 +1,153 @@
1
+ # macOS launchd setup for the bridge
2
+
3
+ Make the local `claude-ide-bridge` and the SSH reverse tunnel to your
4
+ self-hosted dashboard persistent on your Mac:
5
+
6
+ - Auto-start at login
7
+ - Auto-restart on crash (bridge has its own `--watch` supervisor; launchd
8
+ is the supervisor of the supervisor)
9
+ - Auto-reconnect on network change / sleep / wake (autossh)
10
+ - No tmux session to keep alive, no terminal to leave open
11
+
12
+ ## One-time setup
13
+
14
+ 1. **Install the patchwork CLI globally** (not via `npm link`). LaunchAgents
15
+ run in a tighter sandbox; symlinked installs into `~/Documents` /
16
+ `~/Desktop` / `~/Downloads` fail with `EPERM`:
17
+ ```bash
18
+ npm install -g patchwork-os
19
+ # or, from a local repo:
20
+ # npm pack && npm install -g patchwork-os-*.tgz
21
+ ```
22
+
23
+ 2. **Make sure you can SSH to the VPS without a password prompt.** The
24
+ tunnel runs unattended; if SSH would prompt for a key passphrase,
25
+ add the key to your agent (`ssh-add ~/.ssh/id_ed25519`) or use a
26
+ passphrase-less key.
27
+
28
+ 3. **(Recommended) Pin the SSH target in `~/.ssh/config` first.** Using
29
+ the public domain as the SSH target is fragile — DNS drifts during
30
+ redeploys (CDN edges, transient IPs), so SSH lands on a different
31
+ machine and the host key changes. Add an alias once and use it
32
+ everywhere:
33
+
34
+ ```ssh-config
35
+ # ~/.ssh/config
36
+ Host pw-bridge
37
+ HostName 185.167.97.141 # your VPS IP — stable across DNS shifts
38
+ User wesh # or root, whatever your VPS allows
39
+ IdentityFile ~/.ssh/id_ed25519
40
+ ServerAliveInterval 30
41
+ ServerAliveCountMax 3
42
+ UserKnownHostsFile ~/.ssh/known_hosts.patchwork
43
+ ```
44
+
45
+ Verify it works once: `ssh pw-bridge "echo ok"`. The host key is
46
+ accepted into the dedicated `known_hosts.patchwork` file and stays
47
+ there even if you `ssh-keygen -R` your global known_hosts later.
48
+
49
+ 4. **Run the installer** with the alias (cleanest):
50
+ ```bash
51
+ VPS_HOST=pw-bridge bash deploy/macos/install-mac-bridge.sh
52
+ ```
53
+ The installer detects the alias via `ssh -G` and lets ssh_config
54
+ own user + identity + hostname resolution. On a VPS rebuild, you
55
+ only update `~/.ssh/config` — the LaunchAgents pick it up.
56
+
57
+ Without an alias (interactive, prompts for VPS host):
58
+ ```bash
59
+ bash deploy/macos/install-mac-bridge.sh
60
+ # → prompts; recommend the IP (185.167.97.141) over the domain
61
+ ```
62
+ Or fully env-driven:
63
+ ```bash
64
+ VPS_HOST=185.167.97.141 VPS_USER=root \
65
+ BRIDGE_PORT=63906 VPS_PORT=3285 \
66
+ bash deploy/macos/install-mac-bridge.sh
67
+ ```
68
+
69
+ 5. **Sync the bridge token to the VPS** (the installer prints the exact
70
+ `ssh … sed … pm2 restart` command — copy-paste).
71
+
72
+ ## What runs after install
73
+
74
+ ```
75
+ ~/Library/LaunchAgents/com.patchwork.bridge.plist
76
+ ~/Library/LaunchAgents/com.patchwork.tunnel.plist
77
+ ```
78
+
79
+ Both are loaded into the per-user `gui/$UID` launchd domain at install
80
+ time and at every login.
81
+
82
+ ```
83
+ [claude-ide-bridge --port 63906 --fixed-token <…> --watch]
84
+
85
+ │ 127.0.0.1:63906
86
+
87
+ [autossh -R 127.0.0.1:3285:localhost:63906]
88
+
89
+ │ encrypted SSH reverse tunnel
90
+
91
+ VPS:3285 ──── nginx ──── dashboard `/api/bridge/*`
92
+ ```
93
+
94
+ ## Logs
95
+
96
+ ```bash
97
+ tail -f ~/Library/Logs/patchwork-bridge.log
98
+ tail -f ~/Library/Logs/patchwork-tunnel.log
99
+ ```
100
+
101
+ ## Status
102
+
103
+ ```bash
104
+ launchctl print gui/$UID/com.patchwork.bridge
105
+ launchctl print gui/$UID/com.patchwork.tunnel
106
+ ```
107
+
108
+ ## Restart manually
109
+
110
+ ```bash
111
+ launchctl kickstart -k gui/$UID/com.patchwork.bridge
112
+ launchctl kickstart -k gui/$UID/com.patchwork.tunnel
113
+ ```
114
+
115
+ ## Uninstall
116
+
117
+ ```bash
118
+ bash deploy/macos/uninstall-mac-bridge.sh
119
+ ```
120
+
121
+ ## Troubleshooting
122
+
123
+ - **`com.patchwork.bridge` exits with status 78 / `EPERM`** — the bridge
124
+ CLI is installed via `npm link` and points into `~/Documents`. The
125
+ macOS sandbox blocks LaunchAgents from reading that tree. Reinstall
126
+ globally as a real package (see step 1).
127
+ - **`com.patchwork.tunnel` keeps respawning** — check the SSH key is
128
+ added to `ssh-agent` (`ssh-add -l`). LaunchAgents run before the
129
+ user's shell rc, so an interactive `ssh-add` from `.zshrc` doesn't
130
+ apply. Use a passphrase-less key, or store the key in macOS Keychain
131
+ with `ssh-add --apple-use-keychain`.
132
+ - **Tunnel succeeds but dashboard says offline** — VPS port already in
133
+ use by an old leftover bridge. SSH to the VPS and `pkill -f "autossh\|sshd: .*\@notty"`,
134
+ or pick a different `VPS_PORT`.
135
+ - **Dashboard 401s on every bridge call** — `PATCHWORK_BRIDGE_TOKEN`
136
+ on the VPS doesn't match the `--fixed-token` value the bridge is
137
+ using. Re-run the install script's printed `sed … pm2 restart`
138
+ command.
139
+ - **`Host key for X has changed and you have requested strict
140
+ checking`** every now and then — the SSH target is moving. Two
141
+ causes:
142
+ 1. **DNS drift.** The public domain resolves to a different IP than
143
+ it did last time (CDN edge, redeploy churn). `dig +short
144
+ bridge.your.tld` vs your known VPS IP — if those differ, switch
145
+ the `VPS_HOST` to the IP or a `~/.ssh/config` alias and re-run
146
+ the installer.
147
+ 2. **VPS rebuild.** A reimage regenerates `/etc/ssh/ssh_host_*_key`
148
+ files. Either back them up before the rebuild and restore after,
149
+ or accept the new key once with `ssh-keygen -R <host> && ssh
150
+ <host>`. The launchd tunnel uses `StrictHostKeyChecking=accept-new`
151
+ (only auto-trusts on first connect, not after change), so you'll
152
+ see the warning, accept the new key interactively once, and the
153
+ tunnel resumes.
@@ -0,0 +1,54 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>com.patchwork.bridge</string>
7
+
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>{{BRIDGE_BIN}}</string>
11
+ <string>--port</string>
12
+ <string>{{BRIDGE_PORT}}</string>
13
+ <string>--fixed-token</string>
14
+ <string>{{BRIDGE_TOKEN}}</string>
15
+ <string>--watch</string>
16
+ <string>--workspace</string>
17
+ <string>{{WORKSPACE}}</string>
18
+ </array>
19
+
20
+ <key>RunAtLoad</key>
21
+ <true/>
22
+ <!-- KeepAlive is redundant with `--watch` (which has its own
23
+ exponential-backoff supervisor and recovers from crashes faster
24
+ than launchd's per-second relaunch). Leave it true as belt-and-
25
+ suspenders in case `--watch` itself dies (its supervisor process
26
+ is a single Node, and that's the one launchd is keeping alive). -->
27
+ <key>KeepAlive</key>
28
+ <true/>
29
+
30
+ <key>StandardOutPath</key>
31
+ <string>{{HOME}}/Library/Logs/patchwork-bridge.log</string>
32
+ <key>StandardErrorPath</key>
33
+ <string>{{HOME}}/Library/Logs/patchwork-bridge.log</string>
34
+
35
+ <key>WorkingDirectory</key>
36
+ <string>{{WORKSPACE}}</string>
37
+
38
+ <key>EnvironmentVariables</key>
39
+ <dict>
40
+ <!-- launchd's default PATH doesn't include Homebrew. Bridge spawns
41
+ child processes (claude CLI, git, npm) via PATH lookup, so
42
+ missing /opt/homebrew/bin breaks half the tools. -->
43
+ <key>PATH</key>
44
+ <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
45
+ <key>HOME</key>
46
+ <string>{{HOME}}</string>
47
+ </dict>
48
+
49
+ <!-- Throttle: don't relaunch faster than every 10 s on rapid crash
50
+ loops, prevents spinning up if the binary is broken. -->
51
+ <key>ThrottleInterval</key>
52
+ <integer>10</integer>
53
+ </dict>
54
+ </plist>
@@ -0,0 +1,76 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>com.patchwork.tunnel</string>
7
+
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>{{AUTOSSH_BIN}}</string>
11
+ <!-- AUTOSSH_PORT=0 disables the legacy monitoring-port heartbeat in
12
+ favor of SSH's own ServerAliveInterval/CountMax. Modern autossh
13
+ docs recommend this; the monitoring port is unreliable behind
14
+ NAT and consumes another tunnel slot. -->
15
+ <string>-M</string>
16
+ <string>0</string>
17
+ <!-- -N: no remote command -T: no pseudo-tty -->
18
+ <string>-N</string>
19
+ <string>-T</string>
20
+ <string>-R</string>
21
+ <string>127.0.0.1:{{VPS_PORT}}:localhost:{{BRIDGE_PORT}}</string>
22
+ <!-- ServerAliveInterval=30 + CountMax=3 = ssh kills the link if
23
+ the server doesn't respond for 90 s, autossh restarts. Critical
24
+ for laptop sleep/wake and Wi-Fi switches. -->
25
+ <string>-o</string>
26
+ <string>ServerAliveInterval=30</string>
27
+ <string>-o</string>
28
+ <string>ServerAliveCountMax=3</string>
29
+ <!-- ExitOnForwardFailure=yes makes autossh exit + retry if the
30
+ remote port is already bound. Otherwise the tunnel "succeeds"
31
+ but no traffic flows. -->
32
+ <string>-o</string>
33
+ <string>ExitOnForwardFailure=yes</string>
34
+ <!-- Don't auto-add new host keys (security: surface key changes
35
+ instead of silently trusting). Initial setup expects the user
36
+ to have already SSH'd at least once and accepted the key. -->
37
+ <string>-o</string>
38
+ <string>StrictHostKeyChecking=accept-new</string>
39
+ <string>-i</string>
40
+ <string>{{SSH_KEY}}</string>
41
+ <!-- SSH_TARGET is rendered by install-mac-bridge.sh:
42
+ - "user@host" form when host is an IP or hostname
43
+ - bare alias when host matches a `~/.ssh/config` Host entry
44
+ (so ssh_config's User + HostName + IdentityFile resolution
45
+ works as designed; passing user@alias would override the
46
+ config's User directive and confuse the alias case). -->
47
+ <string>{{SSH_TARGET}}</string>
48
+ </array>
49
+
50
+ <key>RunAtLoad</key>
51
+ <true/>
52
+ <key>KeepAlive</key>
53
+ <true/>
54
+
55
+ <key>StandardOutPath</key>
56
+ <string>{{HOME}}/Library/Logs/patchwork-tunnel.log</string>
57
+ <key>StandardErrorPath</key>
58
+ <string>{{HOME}}/Library/Logs/patchwork-tunnel.log</string>
59
+
60
+ <key>EnvironmentVariables</key>
61
+ <dict>
62
+ <key>PATH</key>
63
+ <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
64
+ <key>HOME</key>
65
+ <string>{{HOME}}</string>
66
+ <!-- AUTOSSH_GATETIME=0: don't require a "stable" connection time
67
+ before counting reconnect attempts. Default 30 s makes startup
68
+ after a long sleep slower than necessary. -->
69
+ <key>AUTOSSH_GATETIME</key>
70
+ <string>0</string>
71
+ </dict>
72
+
73
+ <key>ThrottleInterval</key>
74
+ <integer>10</integer>
75
+ </dict>
76
+ </plist>