@different-ai/opencode-browser 1.0.5 → 2.0.1

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/bin/cli.js CHANGED
@@ -1,16 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * OpenCode Browser - CLI Installer
4
- *
5
- * Installs the Chrome extension and native messaging host for browser automation.
4
+ *
5
+ * Installs the Chrome extension for browser automation.
6
+ * v2.0: Plugin-based architecture (no daemon, no MCP server)
6
7
  */
7
8
 
8
- import { createInterface } from "readline";
9
- import { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, readdirSync } from "fs";
9
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, readdirSync, unlinkSync } from "fs";
10
10
  import { homedir, platform } from "os";
11
11
  import { join, dirname } from "path";
12
12
  import { fileURLToPath } from "url";
13
13
  import { execSync } from "child_process";
14
+ import { createInterface } from "readline";
14
15
 
15
16
  const __filename = fileURLToPath(import.meta.url);
16
17
  const __dirname = dirname(__filename);
@@ -35,20 +36,20 @@ function log(msg) {
35
36
  }
36
37
 
37
38
  function success(msg) {
38
- console.log(color("green", "" + msg));
39
+ console.log(color("green", " " + msg));
39
40
  }
40
41
 
41
42
  function warn(msg) {
42
- console.log(color("yellow", "" + msg));
43
+ console.log(color("yellow", " " + msg));
43
44
  }
44
45
 
45
46
  function error(msg) {
46
- console.log(color("red", "" + msg));
47
+ console.log(color("red", " " + msg));
47
48
  }
48
49
 
49
50
  function header(msg) {
50
51
  console.log("\n" + color("cyan", color("bright", msg)));
51
- console.log(color("cyan", "".repeat(msg.length)));
52
+ console.log(color("cyan", "-".repeat(msg.length)));
52
53
  }
53
54
 
54
55
  const rl = createInterface({
@@ -71,12 +72,8 @@ async function confirm(question) {
71
72
 
72
73
  async function main() {
73
74
  console.log(`
74
- ${color("cyan", color("bright", "╔═══════════════════════════════════════════════════════════╗"))}
75
- ${color("cyan", color("bright", "║"))} ${color("bright", "OpenCode Browser")} - Browser Automation for OpenCode ${color("cyan", color("bright", "║"))}
76
- ${color("cyan", color("bright", "║"))} ${color("cyan", color("bright", "║"))}
77
- ${color("cyan", color("bright", "║"))} Inspired by Claude in Chrome - browser automation that ${color("cyan", color("bright", "║"))}
78
- ${color("cyan", color("bright", "║"))} works with your existing logins and bookmarks. ${color("cyan", color("bright", "║"))}
79
- ${color("cyan", color("bright", "╚═══════════════════════════════════════════════════════════╝"))}
75
+ ${color("cyan", color("bright", "OpenCode Browser v2.0"))}
76
+ ${color("cyan", "Browser automation for OpenCode")}
80
77
  `);
81
78
 
82
79
  const command = process.argv[2];
@@ -85,28 +82,18 @@ ${color("cyan", color("bright", "╚══════════════
85
82
  await install();
86
83
  } else if (command === "uninstall") {
87
84
  await uninstall();
88
- } else if (command === "daemon") {
89
- await startDaemon();
90
- } else if (command === "daemon-install") {
91
- await installDaemon();
92
- } else if (command === "start") {
93
- rl.close();
94
- await import("../src/server.js");
95
- return;
85
+ } else if (command === "status") {
86
+ await status();
96
87
  } else {
97
88
  log(`
98
89
  ${color("bright", "Usage:")}
99
- npx @different-ai/opencode-browser install Install extension
100
- npx @different-ai/opencode-browser daemon-install Install background daemon
101
- npx @different-ai/opencode-browser daemon Run daemon (foreground)
102
- npx @different-ai/opencode-browser start Run MCP server
103
- npx @different-ai/opencode-browser uninstall Remove installation
90
+ npx @different-ai/opencode-browser install Install extension
91
+ npx @different-ai/opencode-browser uninstall Remove installation
92
+ npx @different-ai/opencode-browser status Check lock status
104
93
 
105
- ${color("bright", "With bun:")}
106
- bunx @different-ai/opencode-browser install
107
-
108
- ${color("bright", "For scheduled jobs:")}
109
- Run 'daemon-install' to enable browser tools in background jobs.
94
+ ${color("bright", "v2.0 Changes:")}
95
+ - Plugin-based architecture (no daemon needed)
96
+ - Add plugin to opencode.json, load extension in Chrome, done
110
97
  `);
111
98
  }
112
99
 
@@ -124,7 +111,7 @@ async function install() {
124
111
  }
125
112
  success(`Platform: ${os === "darwin" ? "macOS" : "Linux"}`);
126
113
 
127
- header("Step 2: Install Extension Directory");
114
+ header("Step 2: Copy Extension Files");
128
115
 
129
116
  const extensionDir = join(homedir(), ".opencode-browser", "extension");
130
117
  const srcExtensionDir = join(PACKAGE_ROOT, "extension");
@@ -135,7 +122,7 @@ async function install() {
135
122
  for (const file of files) {
136
123
  const srcPath = join(srcExtensionDir, file);
137
124
  const destPath = join(extensionDir, file);
138
-
125
+
139
126
  try {
140
127
  const stat = readdirSync(srcPath);
141
128
  mkdirSync(destPath, { recursive: true });
@@ -147,7 +134,7 @@ async function install() {
147
134
 
148
135
  success(`Extension files copied to: ${extensionDir}`);
149
136
 
150
- header("Step 3: Load Extension in Browser");
137
+ header("Step 3: Load Extension in Chrome");
151
138
 
152
139
  log(`
153
140
  Works with: ${color("cyan", "Chrome")}, ${color("cyan", "Brave")}, ${color("cyan", "Arc")}, ${color("cyan", "Edge")}, and other Chromium browsers.
@@ -164,281 +151,194 @@ To load the extension:
164
151
  4. Select this folder:
165
152
  ${color("cyan", extensionDir)}
166
153
  ${os === "darwin" ? color("yellow", "Tip: Press Cmd+Shift+G and paste the path above") : ""}
167
-
168
- 5. Copy the ${color("bright", "Extension ID")} shown under the extension name
169
- (looks like: abcdefghijklmnopqrstuvwxyz123456)
170
154
  `);
171
155
 
172
- log("");
173
- const extensionId = await ask(color("bright", "Enter your Extension ID: "));
174
-
175
- if (!extensionId) {
176
- error("Extension ID is required");
177
- process.exit(1);
178
- }
179
-
180
- if (!/^[a-z]{32}$/.test(extensionId)) {
181
- warn("Extension ID format looks unusual (expected 32 lowercase letters)");
182
- const proceed = await confirm("Continue anyway?");
183
- if (!proceed) process.exit(1);
184
- }
185
-
186
- header("Step 4: Register Native Messaging Host");
187
-
188
- const nativeHostDir = os === "darwin"
189
- ? join(homedir(), "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts")
190
- : join(homedir(), ".config", "google-chrome", "NativeMessagingHosts");
191
-
192
- mkdirSync(nativeHostDir, { recursive: true });
193
-
194
- const nodePath = process.execPath;
195
- const hostScriptPath = join(PACKAGE_ROOT, "src", "host.js");
196
-
197
- const wrapperDir = join(homedir(), ".opencode-browser");
198
- const wrapperPath = join(wrapperDir, "host-wrapper.sh");
199
-
200
- writeFileSync(wrapperPath, `#!/bin/bash
201
- exec "${nodePath}" "${hostScriptPath}" "$@"
202
- `, { mode: 0o755 });
203
-
204
- const manifest = {
205
- name: "com.opencode.browser_automation",
206
- description: "OpenCode Browser Automation Native Messaging Host",
207
- path: wrapperPath,
208
- type: "stdio",
209
- allowed_origins: [`chrome-extension://${extensionId}/`],
210
- };
156
+ await ask(color("bright", "Press Enter when you've loaded the extension..."));
211
157
 
212
- const manifestPath = join(nativeHostDir, "com.opencode.browser_automation.json");
213
- writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
214
-
215
- success(`Native host registered at: ${manifestPath}`);
216
-
217
- const logsDir = join(homedir(), ".opencode-browser", "logs");
218
- mkdirSync(logsDir, { recursive: true });
158
+ header("Step 4: Configure OpenCode");
219
159
 
220
- header("Step 5: Install Background Daemon");
221
-
222
- if (os === "darwin") {
223
- const daemonPath = join(PACKAGE_ROOT, "src", "daemon.js");
224
-
225
- const plist = `<?xml version="1.0" encoding="UTF-8"?>
226
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
227
- <plist version="1.0">
228
- <dict>
229
- <key>Label</key>
230
- <string>com.opencode.browser-daemon</string>
231
- <key>ProgramArguments</key>
232
- <array>
233
- <string>${nodePath}</string>
234
- <string>${daemonPath}</string>
235
- </array>
236
- <key>RunAtLoad</key>
237
- <true/>
238
- <key>KeepAlive</key>
239
- <true/>
240
- <key>StandardOutPath</key>
241
- <string>${logsDir}/daemon.log</string>
242
- <key>StandardErrorPath</key>
243
- <string>${logsDir}/daemon.log</string>
244
- </dict>
245
- </plist>`;
246
-
247
- const plistPath = join(homedir(), "Library", "LaunchAgents", "com.opencode.browser-daemon.plist");
248
- writeFileSync(plistPath, plist);
249
-
250
- try {
251
- execSync(`launchctl unload "${plistPath}" 2>/dev/null || true`, { stdio: "ignore" });
252
- execSync(`launchctl load "${plistPath}"`, { stdio: "ignore" });
253
- success("Daemon installed and started");
254
- } catch (e) {
255
- warn("Could not start daemon automatically. Run: launchctl load " + plistPath);
256
- }
257
- } else {
258
- warn("On Linux, create a systemd service for the daemon manually.");
259
- log(`Daemon script: ${join(PACKAGE_ROOT, "src", "daemon.js")}`);
260
- }
261
-
262
- header("Step 6: Configure OpenCode");
263
-
264
- const serverPath = join(PACKAGE_ROOT, "src", "server.js");
265
- const mcpConfig = {
266
- browser: {
267
- type: "local",
268
- command: ["node", serverPath],
269
- enabled: true,
270
- },
271
- };
160
+ const pluginConfig = `{
161
+ "$schema": "https://opencode.ai/config.json",
162
+ "plugin": ["@different-ai/opencode-browser"]
163
+ }`;
272
164
 
273
165
  log(`
274
- Add this to your ${color("cyan", "opencode.json")} under "mcp":
166
+ Add the plugin to your ${color("cyan", "opencode.json")}:
275
167
 
276
- ${color("bright", JSON.stringify(mcpConfig, null, 2))}
168
+ ${color("bright", pluginConfig)}
169
+
170
+ Or if you already have an opencode.json, just add to the "plugin" array:
171
+ ${color("bright", '"plugin": ["@different-ai/opencode-browser"]')}
277
172
  `);
278
173
 
279
174
  const opencodeJsonPath = join(process.cwd(), "opencode.json");
280
- let shouldUpdateConfig = false;
281
175
 
282
176
  if (existsSync(opencodeJsonPath)) {
283
- shouldUpdateConfig = await confirm(`Found opencode.json in current directory. Add browser config automatically?`);
284
-
285
- if (shouldUpdateConfig) {
177
+ const shouldUpdate = await confirm(`Found opencode.json. Add plugin automatically?`);
178
+
179
+ if (shouldUpdate) {
286
180
  try {
287
181
  const config = JSON.parse(readFileSync(opencodeJsonPath, "utf-8"));
288
- config.mcp = config.mcp || {};
289
- config.mcp.browser = mcpConfig.browser;
182
+ config.plugin = config.plugin || [];
183
+ if (!config.plugin.includes("@different-ai/opencode-browser")) {
184
+ config.plugin.push("@different-ai/opencode-browser");
185
+ }
186
+ // Remove old MCP config if present
187
+ if (config.mcp?.browser) {
188
+ delete config.mcp.browser;
189
+ if (Object.keys(config.mcp).length === 0) {
190
+ delete config.mcp;
191
+ }
192
+ warn("Removed old MCP browser config (replaced by plugin)");
193
+ }
290
194
  writeFileSync(opencodeJsonPath, JSON.stringify(config, null, 2) + "\n");
291
- success("Updated opencode.json with browser MCP config");
195
+ success("Updated opencode.json with plugin");
292
196
  } catch (e) {
293
197
  error(`Failed to update opencode.json: ${e.message}`);
294
- log("Please add the config manually.");
198
+ log("Please add the plugin manually.");
295
199
  }
296
200
  }
297
201
  } else {
298
- const shouldCreate = await confirm(`No opencode.json found. Create one with browser config?`);
299
-
202
+ const shouldCreate = await confirm(`No opencode.json found. Create one?`);
203
+
300
204
  if (shouldCreate) {
301
205
  try {
302
- const config = { "$schema": "https://opencode.ai/config.json", mcp: mcpConfig };
206
+ const config = {
207
+ $schema: "https://opencode.ai/config.json",
208
+ plugin: ["@different-ai/opencode-browser"],
209
+ };
303
210
  writeFileSync(opencodeJsonPath, JSON.stringify(config, null, 2) + "\n");
304
- success("Created opencode.json with browser MCP config");
305
- shouldUpdateConfig = true;
211
+ success("Created opencode.json with plugin");
306
212
  } catch (e) {
307
213
  error(`Failed to create opencode.json: ${e.message}`);
308
214
  }
309
- } else {
310
- log(`Add the config above to your project's opencode.json manually.`);
311
215
  }
312
216
  }
313
217
 
218
+ // Clean up old daemon if present
219
+ header("Step 5: Cleanup (v1.x migration)");
220
+
221
+ const oldDaemonPlist = join(homedir(), "Library", "LaunchAgents", "com.opencode.browser-daemon.plist");
222
+ if (existsSync(oldDaemonPlist)) {
223
+ try {
224
+ execSync(`launchctl unload "${oldDaemonPlist}" 2>/dev/null || true`, { stdio: "ignore" });
225
+ unlinkSync(oldDaemonPlist);
226
+ success("Removed old daemon (no longer needed in v2.0)");
227
+ } catch {
228
+ warn("Could not remove old daemon plist. Remove manually if needed.");
229
+ }
230
+ } else {
231
+ success("No old daemon to clean up");
232
+ }
233
+
314
234
  header("Installation Complete!");
315
235
 
316
236
  log(`
317
- ${color("green", "")} Extension installed at: ${extensionDir}
318
- ${color("green", "")} Native host registered
319
- ${shouldUpdateConfig ? color("green", "✓") + " opencode.json updated" : color("yellow", "○") + " Remember to update opencode.json"}
237
+ ${color("green", "")} Extension: ${extensionDir}
238
+ ${color("green", "")} Plugin: @different-ai/opencode-browser
320
239
 
321
- ${color("bright", "Next steps:")}
322
- 1. ${color("cyan", "Restart Chrome")} (close all windows and reopen)
323
- 2. Click the extension icon to verify connection
324
- 3. Restart OpenCode to load the new MCP server
240
+ ${color("bright", "How it works:")}
241
+ 1. OpenCode loads the plugin on startup
242
+ 2. Plugin starts WebSocket server on port 19222
243
+ 3. Chrome extension connects automatically
244
+ 4. Browser tools are available!
325
245
 
326
246
  ${color("bright", "Available tools:")}
327
- browser_navigate - Go to a URL
328
- browser_click - Click an element
329
- browser_type - Type into an input
330
- browser_screenshot - Capture the page
331
- browser_snapshot - Get accessibility tree
332
- browser_get_tabs - List open tabs
333
- browser_scroll - Scroll the page
334
- browser_wait - Wait for duration
335
- browser_execute - Run JavaScript
336
-
337
- ${color("bright", "Logs:")} ~/.opencode-browser/logs/
338
-
339
- ${color("bright", "Test it out:")}
340
- Open OpenCode and try: ${color("cyan", '"Navigate to google.com and take a snapshot"')}
247
+ browser_status - Check if browser is available
248
+ browser_kill_session - Take over from another session
249
+ browser_navigate - Go to a URL
250
+ browser_click - Click an element
251
+ browser_type - Type into an input
252
+ browser_screenshot - Capture the page
253
+ browser_snapshot - Get accessibility tree
254
+ browser_get_tabs - List open tabs
255
+ browser_scroll - Scroll the page
256
+ browser_wait - Wait for duration
257
+ browser_execute - Run JavaScript
258
+
259
+ ${color("bright", "Multi-session:")}
260
+ Only one OpenCode session can use browser at a time.
261
+ Use browser_status to check, browser_kill_session to take over.
262
+
263
+ ${color("bright", "Test it:")}
264
+ Restart OpenCode and try: ${color("cyan", '"Check browser status"')}
341
265
  `);
342
266
  }
343
267
 
344
- async function startDaemon() {
345
- const { spawn } = await import("child_process");
346
- const daemonPath = join(PACKAGE_ROOT, "src", "daemon.js");
347
- log("Starting daemon...");
348
- const child = spawn(process.execPath, [daemonPath], { stdio: "inherit" });
349
- child.on("exit", (code) => process.exit(code || 0));
350
- }
268
+ async function status() {
269
+ header("Browser Lock Status");
351
270
 
352
- async function installDaemon() {
353
- header("Installing Background Daemon");
354
-
355
- const os = platform();
356
- if (os !== "darwin") {
357
- error("Daemon auto-install currently supports macOS only");
358
- log("On Linux, create a systemd service manually.");
359
- process.exit(1);
360
- }
361
-
362
- const nodePath = process.execPath;
363
- const daemonPath = join(PACKAGE_ROOT, "src", "daemon.js");
364
- const logsDir = join(homedir(), ".opencode-browser", "logs");
365
-
366
- mkdirSync(logsDir, { recursive: true });
367
-
368
- const plist = `<?xml version="1.0" encoding="UTF-8"?>
369
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
370
- <plist version="1.0">
371
- <dict>
372
- <key>Label</key>
373
- <string>com.opencode.browser-daemon</string>
374
- <key>ProgramArguments</key>
375
- <array>
376
- <string>${nodePath}</string>
377
- <string>${daemonPath}</string>
378
- </array>
379
- <key>RunAtLoad</key>
380
- <true/>
381
- <key>KeepAlive</key>
382
- <true/>
383
- <key>StandardOutPath</key>
384
- <string>${logsDir}/daemon.log</string>
385
- <key>StandardErrorPath</key>
386
- <string>${logsDir}/daemon.log</string>
387
- </dict>
388
- </plist>`;
389
-
390
- const plistPath = join(homedir(), "Library", "LaunchAgents", "com.opencode.browser-daemon.plist");
391
- writeFileSync(plistPath, plist);
392
- success(`Created launchd plist: ${plistPath}`);
393
-
394
- try {
395
- execSync(`launchctl unload "${plistPath}" 2>/dev/null || true`);
396
- execSync(`launchctl load "${plistPath}"`);
397
- success("Daemon started");
398
- } catch (e) {
399
- error(`Failed to load daemon: ${e.message}`);
400
- }
401
-
402
- log(`
403
- ${color("green", "✓")} Daemon installed and running
271
+ const lockFile = join(homedir(), ".opencode-browser", "lock.json");
404
272
 
405
- The daemon bridges Chrome extension ↔ MCP server.
406
- It runs automatically on login and enables browser
407
- tools in scheduled OpenCode jobs.
273
+ if (!existsSync(lockFile)) {
274
+ success("Browser available (no lock file)");
275
+ return;
276
+ }
408
277
 
409
- ${color("bright", "Logs:")} ${logsDir}/daemon.log
278
+ try {
279
+ const lock = JSON.parse(readFileSync(lockFile, "utf-8"));
280
+ log(`
281
+ Lock file: ${lockFile}
410
282
 
411
- ${color("bright", "Control:")}
412
- launchctl stop com.opencode.browser-daemon
413
- launchctl start com.opencode.browser-daemon
414
- launchctl unload ~/Library/LaunchAgents/com.opencode.browser-daemon.plist
283
+ PID: ${lock.pid}
284
+ Session: ${lock.sessionId}
285
+ Started: ${lock.startedAt}
286
+ Working directory: ${lock.cwd}
415
287
  `);
288
+
289
+ // Check if process is alive
290
+ try {
291
+ process.kill(lock.pid, 0);
292
+ warn(`Process ${lock.pid} is running. Browser is locked.`);
293
+ } catch {
294
+ success(`Process ${lock.pid} is dead. Lock is stale and will be auto-cleaned.`);
295
+ }
296
+ } catch (e) {
297
+ error(`Could not read lock file: ${e.message}`);
298
+ }
416
299
  }
417
300
 
418
301
  async function uninstall() {
419
302
  header("Uninstalling OpenCode Browser");
420
303
 
304
+ // Remove old daemon
421
305
  const os = platform();
422
- const nativeHostDir = os === "darwin"
423
- ? join(homedir(), "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts")
424
- : join(homedir(), ".config", "google-chrome", "NativeMessagingHosts");
306
+ if (os === "darwin") {
307
+ const plistPath = join(homedir(), "Library", "LaunchAgents", "com.opencode.browser-daemon.plist");
308
+ if (existsSync(plistPath)) {
309
+ try {
310
+ execSync(`launchctl unload "${plistPath}" 2>/dev/null || true`, { stdio: "ignore" });
311
+ unlinkSync(plistPath);
312
+ success("Removed daemon plist");
313
+ } catch {}
314
+ }
315
+ }
425
316
 
426
- const manifestPath = join(nativeHostDir, "com.opencode.browser_automation.json");
317
+ // Remove native host registration (v1.x)
318
+ const nativeHostDir =
319
+ os === "darwin"
320
+ ? join(homedir(), "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts")
321
+ : join(homedir(), ".config", "google-chrome", "NativeMessagingHosts");
427
322
 
323
+ const manifestPath = join(nativeHostDir, "com.opencode.browser_automation.json");
428
324
  if (existsSync(manifestPath)) {
429
- const { unlinkSync } = await import("fs");
430
325
  unlinkSync(manifestPath);
431
326
  success("Removed native host registration");
432
- } else {
433
- warn("Native host manifest not found");
327
+ }
328
+
329
+ // Remove lock file
330
+ const lockFile = join(homedir(), ".opencode-browser", "lock.json");
331
+ if (existsSync(lockFile)) {
332
+ unlinkSync(lockFile);
333
+ success("Removed lock file");
434
334
  }
435
335
 
436
336
  log(`
437
- ${color("bright", "Note:")} The extension files at ~/.opencode-browser/ were not removed.
438
- Remove them manually if needed:
337
+ ${color("bright", "Note:")} Extension files at ~/.opencode-browser/ were not removed.
338
+ Remove manually if needed:
439
339
  rm -rf ~/.opencode-browser/
440
340
 
441
- Also remove the "browser" entry from your opencode.json.
341
+ Also remove "@different-ai/opencode-browser" from your opencode.json plugin array.
442
342
  `);
443
343
  }
444
344
 
@@ -1,4 +1,4 @@
1
- const DAEMON_URL = "ws://localhost:19222";
1
+ const PLUGIN_URL = "ws://localhost:19222";
2
2
  const KEEPALIVE_ALARM = "keepalive";
3
3
 
4
4
  let ws = null;
@@ -23,10 +23,10 @@ function connect() {
23
23
  }
24
24
 
25
25
  try {
26
- ws = new WebSocket(DAEMON_URL);
26
+ ws = new WebSocket(PLUGIN_URL);
27
27
 
28
28
  ws.onopen = () => {
29
- console.log("[OpenCode] Connected to daemon");
29
+ console.log("[OpenCode] Connected to plugin");
30
30
  isConnected = true;
31
31
  updateBadge(true);
32
32
  };
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "OpenCode Browser Automation",
4
- "version": "1.0.0",
5
- "description": "Browser automation for OpenCode via Native Messaging",
4
+ "version": "2.0.0",
5
+ "description": "Browser automation for OpenCode",
6
6
  "permissions": [
7
7
  "tabs",
8
8
  "activeTab",
9
9
  "scripting",
10
- "nativeMessaging",
11
10
  "storage",
12
11
  "notifications",
13
12
  "alarms"
package/package.json CHANGED
@@ -1,14 +1,23 @@
1
1
  {
2
2
  "name": "@different-ai/opencode-browser",
3
- "version": "1.0.5",
4
- "description": "Browser automation for OpenCode via Chrome extension + Native Messaging. Inspired by Claude in Chrome.",
3
+ "version": "2.0.1",
4
+ "description": "Browser automation plugin for OpenCode. Control your real Chrome browser with existing logins and cookies.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "opencode-browser": "./bin/cli.js"
8
8
  },
9
- "main": "./src/server.js",
9
+ "main": "./src/plugin.ts",
10
+ "exports": {
11
+ ".": "./src/plugin.ts",
12
+ "./plugin": "./src/plugin.ts"
13
+ },
14
+ "files": [
15
+ "bin",
16
+ "src",
17
+ "extension",
18
+ "README.md"
19
+ ],
10
20
  "scripts": {
11
- "start": "node src/server.js",
12
21
  "install-extension": "node bin/cli.js install"
13
22
  },
14
23
  "keywords": [
@@ -16,8 +25,7 @@
16
25
  "browser",
17
26
  "automation",
18
27
  "chrome",
19
- "mcp",
20
- "claude"
28
+ "plugin"
21
29
  ],
22
30
  "author": "Benjamin Shafii",
23
31
  "license": "MIT",
@@ -29,8 +37,11 @@
29
37
  "url": "https://github.com/different-ai/opencode-browser/issues"
30
38
  },
31
39
  "homepage": "https://github.com/different-ai/opencode-browser#readme",
32
- "dependencies": {
33
- "@modelcontextprotocol/sdk": "^1.0.0",
34
- "ws": "^8.18.3"
40
+ "peerDependencies": {
41
+ "@opencode-ai/plugin": "*"
42
+ },
43
+ "devDependencies": {
44
+ "@opencode-ai/plugin": "*",
45
+ "bun-types": "*"
35
46
  }
36
47
  }