surfagent 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # webpilot
1
+ # surfagent
2
2
 
3
3
  A local API that gives AI agents structured page data from your Chrome browser. Instead of guessing selectors or taking screenshots, your agent gets a complete map of every element, form, and link on the page — then acts on it precisely.
4
4
 
@@ -6,24 +6,23 @@ A local API that gives AI agents structured page data from your Chrome browser.
6
6
 
7
7
  ## Quick Start
8
8
 
9
- **1. Install**
10
9
  ```bash
11
- npm install webpilot
12
- npm install
10
+ npm install -g surfagent
11
+ surfagent start
13
12
  ```
14
13
 
15
- **2. Start Chrome with debugging**
16
- ```bash
17
- ./scripts/start-chrome.sh
18
- ```
14
+ That's it. Chrome opens with debug mode, API starts on `http://localhost:3456`. Your agent can start calling it immediately.
15
+
16
+ ### Other commands
19
17
 
20
- **3. Start the API**
21
18
  ```bash
22
- npm run api
19
+ surfagent start # Start Chrome + API (one command)
20
+ surfagent chrome # Start Chrome debug session only
21
+ surfagent api # Start API only (Chrome must be running)
22
+ surfagent health # Check if everything is running
23
+ surfagent help # Show all options
23
24
  ```
24
25
 
25
- That's it. The API is running on `http://localhost:3456`.
26
-
27
26
  ## Your First Recon
28
27
 
29
28
  Open any website in Chrome, then:
package/dist/api/act.d.ts CHANGED
@@ -70,17 +70,6 @@ export declare function readPage(tabPattern: string, options: {
70
70
  host?: string;
71
71
  selector?: string;
72
72
  }): Promise<any>;
73
- export declare function screenshotTab(tabPattern: string, options: {
74
- port?: number;
75
- host?: string;
76
- selector?: string;
77
- clip?: {
78
- x: number;
79
- y: number;
80
- width: number;
81
- height: number;
82
- };
83
- }): Promise<string>;
84
73
  export interface CaptchaRequest {
85
74
  tab: string;
86
75
  action: 'detect' | 'read' | 'next' | 'prev' | 'submit' | 'audio' | 'restart';
package/dist/api/act.js CHANGED
@@ -357,33 +357,6 @@ export async function readPage(tabPattern, options) {
357
357
  throw error;
358
358
  }
359
359
  }
360
- export async function screenshotTab(tabPattern, options) {
361
- const port = options.port || 9222;
362
- const host = options.host || 'localhost';
363
- const tab = await resolveTab(tabPattern, port, host);
364
- const client = await connectToTab(tab.id, port, host);
365
- try {
366
- // If selector provided, get its bounding rect and use as clip
367
- let clip = options.clip;
368
- if (options.selector && !clip) {
369
- const r = await client.Runtime.evaluate({
370
- expression: `(function(){ const el = document.querySelector(${JSON.stringify(options.selector)}); if(!el) return null; const r = el.getBoundingClientRect(); return { x: r.x, y: r.y, width: r.width, height: r.height, scale: 1 } })()`,
371
- returnByValue: true
372
- });
373
- clip = r.result.value;
374
- }
375
- const params = { format: 'png', fromSurface: true };
376
- if (clip)
377
- params.clip = { ...clip, scale: 2 }; // 2x for sharper zoom
378
- const result = await client.Page.captureScreenshot(params);
379
- await client.close();
380
- return result.data; // base64 PNG
381
- }
382
- catch (error) {
383
- await client.close();
384
- throw error;
385
- }
386
- }
387
360
  const CAPTCHA_DETECT_SCRIPT = `
388
361
  (function() {
389
362
  // Find captcha iframes on the page
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import http from 'node:http';
3
3
  import { reconUrl, reconTab } from './recon.js';
4
- import { fillFields, clickElement, scrollPage, navigatePage, evalInTab, focusTab, readPage, captchaInteract, screenshotTab } from './act.js';
4
+ import { fillFields, clickElement, scrollPage, navigatePage, evalInTab, focusTab, readPage, captchaInteract } from './act.js';
5
5
  import { getAllTabs } from '../chrome/tabs.js';
6
6
  const PORT = parseInt(process.env.API_PORT || '3456', 10);
7
7
  const CDP_PORT = parseInt(process.env.CDP_PORT || '9222', 10);
@@ -82,21 +82,6 @@ const server = http.createServer(async (req, res) => {
82
82
  const result = await scrollPage(body, { port: CDP_PORT, host: CDP_HOST });
83
83
  return json(res, 200, result);
84
84
  }
85
- // POST /screenshot — capture full page, element, or region at 2x resolution
86
- if (path === '/screenshot' && req.method === 'POST') {
87
- const body = JSON.parse(await readBody(req));
88
- if (!body.tab) {
89
- return json(res, 400, { error: 'Provide "tab", optional "selector" or "clip" {x,y,width,height}' });
90
- }
91
- const data = await screenshotTab(body.tab, { port: CDP_PORT, host: CDP_HOST, selector: body.selector, clip: body.clip });
92
- // Return as base64 or save to file
93
- if (body.output) {
94
- const fs = await import('node:fs');
95
- fs.writeFileSync(body.output, Buffer.from(data, 'base64'));
96
- return json(res, 200, { success: true, output: body.output });
97
- }
98
- return json(res, 200, { data });
99
- }
100
85
  // POST /captcha — detect and interact with captchas
101
86
  if (path === '/captcha' && req.method === 'POST') {
102
87
  const body = JSON.parse(await readBody(req));
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env node
2
+ import { execSync, spawn } from 'node:child_process';
3
+ import http from 'node:http';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ const CDP_PORT = parseInt(process.env.CDP_PORT || '9222', 10);
8
+ const API_PORT = parseInt(process.env.API_PORT || '3456', 10);
9
+ function log(msg) {
10
+ console.log(`[surfagent] ${msg}`);
11
+ }
12
+ function checkCDP() {
13
+ return new Promise((resolve) => {
14
+ const req = http.get(`http://localhost:${CDP_PORT}/json/version`, (res) => {
15
+ resolve(res.statusCode === 200);
16
+ });
17
+ req.on('error', () => resolve(false));
18
+ req.setTimeout(1000, () => { req.destroy(); resolve(false); });
19
+ });
20
+ }
21
+ function detectOS() {
22
+ const platform = process.platform;
23
+ if (platform === 'darwin')
24
+ return 'mac';
25
+ if (platform === 'win32')
26
+ return 'windows';
27
+ return 'linux';
28
+ }
29
+ function getChromePath() {
30
+ const os = detectOS();
31
+ const paths = {
32
+ mac: [
33
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
34
+ '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
35
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
36
+ ],
37
+ linux: [
38
+ '/usr/bin/google-chrome',
39
+ '/usr/bin/google-chrome-stable',
40
+ '/usr/bin/chromium-browser',
41
+ '/usr/bin/chromium',
42
+ '/snap/bin/chromium',
43
+ ],
44
+ windows: [
45
+ 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
46
+ 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
47
+ `${process.env.LOCALAPPDATA}\\Google\\Chrome\\Application\\chrome.exe`,
48
+ ],
49
+ };
50
+ for (const p of paths[os] || []) {
51
+ try {
52
+ execSync(`test -f "${p}"`, { stdio: 'ignore' });
53
+ return p;
54
+ }
55
+ catch {
56
+ continue;
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+ function startChrome(chromePath) {
62
+ const userDataDir = process.env.CHROME_USER_DATA_DIR || '/tmp/surfagent-chrome';
63
+ // Copy cookies from default Chrome profile if available and dir is fresh
64
+ const os = detectOS();
65
+ try {
66
+ execSync(`mkdir -p "${userDataDir}/Default"`, { stdio: 'ignore' });
67
+ if (os === 'mac') {
68
+ const defaultProfile = `${process.env.HOME}/Library/Application Support/Google/Chrome/Default`;
69
+ execSync(`cp "${defaultProfile}/Cookies" "${userDataDir}/Default/" 2>/dev/null || true`, { stdio: 'ignore' });
70
+ }
71
+ else if (os === 'linux') {
72
+ const defaultProfile = `${process.env.HOME}/.config/google-chrome/Default`;
73
+ execSync(`cp "${defaultProfile}/Cookies" "${userDataDir}/Default/" 2>/dev/null || true`, { stdio: 'ignore' });
74
+ }
75
+ }
76
+ catch { }
77
+ const args = [
78
+ `--user-data-dir=${userDataDir}`,
79
+ `--remote-debugging-port=${CDP_PORT}`,
80
+ '--disable-save-password-bubble',
81
+ '--disable-popup-blocking',
82
+ '--disable-notifications',
83
+ '--disable-infobars',
84
+ '--disable-translate',
85
+ '--disable-features=PasswordManager,AutofillSaveCardBubble,TranslateUI',
86
+ '--password-store=basic',
87
+ ];
88
+ const chrome = spawn(chromePath, args, {
89
+ detached: true,
90
+ stdio: 'ignore',
91
+ });
92
+ chrome.unref();
93
+ log(`Chrome started (pid ${chrome.pid}) on port ${CDP_PORT}`);
94
+ }
95
+ async function waitForCDP(maxWait = 10000) {
96
+ const start = Date.now();
97
+ while (Date.now() - start < maxWait) {
98
+ if (await checkCDP())
99
+ return true;
100
+ await new Promise(r => setTimeout(r, 500));
101
+ }
102
+ return false;
103
+ }
104
+ async function main() {
105
+ const command = process.argv[2];
106
+ if (command === 'help' || command === '--help' || command === '-h') {
107
+ console.log(`
108
+ surfagent — Browser Recon API for AI agents
109
+
110
+ Usage:
111
+ surfagent start Start Chrome + API server
112
+ surfagent api Start API only (Chrome must be running)
113
+ surfagent chrome Start Chrome debug session only
114
+ surfagent health Check if everything is running
115
+ surfagent help Show this message
116
+
117
+ Environment variables:
118
+ CDP_PORT Chrome debug port (default: 9222)
119
+ API_PORT API server port (default: 3456)
120
+ CHROME_USER_DATA_DIR Chrome profile directory (default: /tmp/surfagent-chrome)
121
+
122
+ After starting, your AI agent can call http://localhost:3456
123
+ Full API docs: https://github.com/AllAboutAI-YT/webpilot#readme
124
+ `);
125
+ return;
126
+ }
127
+ if (command === 'health') {
128
+ const cdp = await checkCDP();
129
+ console.log(`Chrome CDP (port ${CDP_PORT}): ${cdp ? 'connected' : 'not running'}`);
130
+ if (cdp) {
131
+ try {
132
+ const res = await fetch(`http://localhost:${API_PORT}/health`);
133
+ const data = await res.json();
134
+ console.log(`API (port ${API_PORT}): ${data.status} — ${data.tabCount} tabs`);
135
+ }
136
+ catch {
137
+ console.log(`API (port ${API_PORT}): not running`);
138
+ }
139
+ }
140
+ return;
141
+ }
142
+ if (command === 'chrome') {
143
+ const cdpRunning = await checkCDP();
144
+ if (cdpRunning) {
145
+ log(`Chrome already running on port ${CDP_PORT}`);
146
+ return;
147
+ }
148
+ const chromePath = getChromePath();
149
+ if (!chromePath) {
150
+ console.error('[surfagent] Chrome not found. Install Google Chrome and try again.');
151
+ process.exit(1);
152
+ }
153
+ startChrome(chromePath);
154
+ const connected = await waitForCDP();
155
+ if (!connected) {
156
+ console.error('[surfagent] Chrome started but CDP not responding. Check port ' + CDP_PORT);
157
+ process.exit(1);
158
+ }
159
+ log('Chrome ready');
160
+ return;
161
+ }
162
+ if (command === 'api') {
163
+ const cdpRunning = await checkCDP();
164
+ if (!cdpRunning) {
165
+ console.error(`[surfagent] Chrome not running on port ${CDP_PORT}. Run: surfagent chrome`);
166
+ process.exit(1);
167
+ }
168
+ await import('./api/server.js');
169
+ return;
170
+ }
171
+ if (command === 'start' || !command) {
172
+ log('Starting...');
173
+ // 1. Check/start Chrome
174
+ let cdpRunning = await checkCDP();
175
+ if (cdpRunning) {
176
+ log(`Chrome already running on port ${CDP_PORT}`);
177
+ }
178
+ else {
179
+ const chromePath = getChromePath();
180
+ if (!chromePath) {
181
+ console.error('[surfagent] Chrome not found. Install Google Chrome and try again.');
182
+ process.exit(1);
183
+ }
184
+ startChrome(chromePath);
185
+ cdpRunning = await waitForCDP();
186
+ if (!cdpRunning) {
187
+ console.error('[surfagent] Chrome failed to start. Try running it manually with --remote-debugging-port=9222');
188
+ process.exit(1);
189
+ }
190
+ log('Chrome ready');
191
+ }
192
+ // 2. Start API
193
+ await import('./api/server.js');
194
+ return;
195
+ }
196
+ console.error(`Unknown command: ${command}. Run: surfagent help`);
197
+ process.exit(1);
198
+ }
199
+ main().catch((err) => {
200
+ console.error('[surfagent]', err.message);
201
+ process.exit(1);
202
+ });
package/package.json CHANGED
@@ -1,13 +1,17 @@
1
1
  {
2
2
  "name": "surfagent",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Local API that gives AI agents structured page data from Chrome for fast, precise web navigation",
5
5
  "main": "dist/api/server.js",
6
6
  "type": "module",
7
+ "bin": {
8
+ "surfagent": "dist/cli.js"
9
+ },
7
10
  "scripts": {
8
11
  "build": "tsc",
9
12
  "dev": "tsc --watch",
10
- "api": "node dist/api/server.js"
13
+ "api": "node dist/api/server.js",
14
+ "start": "node dist/cli.js start"
11
15
  },
12
16
  "dependencies": {
13
17
  "chrome-remote-interface": "^0.33.0",
package/src/cli.ts ADDED
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync, spawn } from 'node:child_process';
4
+ import http from 'node:http';
5
+ import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const CDP_PORT = parseInt(process.env.CDP_PORT || '9222', 10);
10
+ const API_PORT = parseInt(process.env.API_PORT || '3456', 10);
11
+
12
+ function log(msg: string) {
13
+ console.log(`[surfagent] ${msg}`);
14
+ }
15
+
16
+ function checkCDP(): Promise<boolean> {
17
+ return new Promise((resolve) => {
18
+ const req = http.get(`http://localhost:${CDP_PORT}/json/version`, (res) => {
19
+ resolve(res.statusCode === 200);
20
+ });
21
+ req.on('error', () => resolve(false));
22
+ req.setTimeout(1000, () => { req.destroy(); resolve(false); });
23
+ });
24
+ }
25
+
26
+ function detectOS(): 'mac' | 'linux' | 'windows' {
27
+ const platform = process.platform;
28
+ if (platform === 'darwin') return 'mac';
29
+ if (platform === 'win32') return 'windows';
30
+ return 'linux';
31
+ }
32
+
33
+ function getChromePath(): string | null {
34
+ const os = detectOS();
35
+ const paths: Record<string, string[]> = {
36
+ mac: [
37
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
38
+ '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
39
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
40
+ ],
41
+ linux: [
42
+ '/usr/bin/google-chrome',
43
+ '/usr/bin/google-chrome-stable',
44
+ '/usr/bin/chromium-browser',
45
+ '/usr/bin/chromium',
46
+ '/snap/bin/chromium',
47
+ ],
48
+ windows: [
49
+ 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
50
+ 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
51
+ `${process.env.LOCALAPPDATA}\\Google\\Chrome\\Application\\chrome.exe`,
52
+ ],
53
+ };
54
+
55
+ for (const p of paths[os] || []) {
56
+ try {
57
+ execSync(`test -f "${p}"`, { stdio: 'ignore' });
58
+ return p;
59
+ } catch {
60
+ continue;
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+
66
+ function startChrome(chromePath: string) {
67
+ const userDataDir = process.env.CHROME_USER_DATA_DIR || '/tmp/surfagent-chrome';
68
+
69
+ // Copy cookies from default Chrome profile if available and dir is fresh
70
+ const os = detectOS();
71
+ try {
72
+ execSync(`mkdir -p "${userDataDir}/Default"`, { stdio: 'ignore' });
73
+
74
+ if (os === 'mac') {
75
+ const defaultProfile = `${process.env.HOME}/Library/Application Support/Google/Chrome/Default`;
76
+ execSync(`cp "${defaultProfile}/Cookies" "${userDataDir}/Default/" 2>/dev/null || true`, { stdio: 'ignore' });
77
+ } else if (os === 'linux') {
78
+ const defaultProfile = `${process.env.HOME}/.config/google-chrome/Default`;
79
+ execSync(`cp "${defaultProfile}/Cookies" "${userDataDir}/Default/" 2>/dev/null || true`, { stdio: 'ignore' });
80
+ }
81
+ } catch {}
82
+
83
+ const args = [
84
+ `--user-data-dir=${userDataDir}`,
85
+ `--remote-debugging-port=${CDP_PORT}`,
86
+ '--disable-save-password-bubble',
87
+ '--disable-popup-blocking',
88
+ '--disable-notifications',
89
+ '--disable-infobars',
90
+ '--disable-translate',
91
+ '--disable-features=PasswordManager,AutofillSaveCardBubble,TranslateUI',
92
+ '--password-store=basic',
93
+ ];
94
+
95
+ const chrome = spawn(chromePath, args, {
96
+ detached: true,
97
+ stdio: 'ignore',
98
+ });
99
+
100
+ chrome.unref();
101
+ log(`Chrome started (pid ${chrome.pid}) on port ${CDP_PORT}`);
102
+ }
103
+
104
+ async function waitForCDP(maxWait = 10000): Promise<boolean> {
105
+ const start = Date.now();
106
+ while (Date.now() - start < maxWait) {
107
+ if (await checkCDP()) return true;
108
+ await new Promise(r => setTimeout(r, 500));
109
+ }
110
+ return false;
111
+ }
112
+
113
+ async function main() {
114
+ const command = process.argv[2];
115
+
116
+ if (command === 'help' || command === '--help' || command === '-h') {
117
+ console.log(`
118
+ surfagent — Browser Recon API for AI agents
119
+
120
+ Usage:
121
+ surfagent start Start Chrome + API server
122
+ surfagent api Start API only (Chrome must be running)
123
+ surfagent chrome Start Chrome debug session only
124
+ surfagent health Check if everything is running
125
+ surfagent help Show this message
126
+
127
+ Environment variables:
128
+ CDP_PORT Chrome debug port (default: 9222)
129
+ API_PORT API server port (default: 3456)
130
+ CHROME_USER_DATA_DIR Chrome profile directory (default: /tmp/surfagent-chrome)
131
+
132
+ After starting, your AI agent can call http://localhost:3456
133
+ Full API docs: https://github.com/AllAboutAI-YT/webpilot#readme
134
+ `);
135
+ return;
136
+ }
137
+
138
+ if (command === 'health') {
139
+ const cdp = await checkCDP();
140
+ console.log(`Chrome CDP (port ${CDP_PORT}): ${cdp ? 'connected' : 'not running'}`);
141
+ if (cdp) {
142
+ try {
143
+ const res = await fetch(`http://localhost:${API_PORT}/health`);
144
+ const data = await res.json();
145
+ console.log(`API (port ${API_PORT}): ${data.status} — ${data.tabCount} tabs`);
146
+ } catch {
147
+ console.log(`API (port ${API_PORT}): not running`);
148
+ }
149
+ }
150
+ return;
151
+ }
152
+
153
+ if (command === 'chrome') {
154
+ const cdpRunning = await checkCDP();
155
+ if (cdpRunning) {
156
+ log(`Chrome already running on port ${CDP_PORT}`);
157
+ return;
158
+ }
159
+
160
+ const chromePath = getChromePath();
161
+ if (!chromePath) {
162
+ console.error('[surfagent] Chrome not found. Install Google Chrome and try again.');
163
+ process.exit(1);
164
+ }
165
+
166
+ startChrome(chromePath);
167
+ const connected = await waitForCDP();
168
+ if (!connected) {
169
+ console.error('[surfagent] Chrome started but CDP not responding. Check port ' + CDP_PORT);
170
+ process.exit(1);
171
+ }
172
+ log('Chrome ready');
173
+ return;
174
+ }
175
+
176
+ if (command === 'api') {
177
+ const cdpRunning = await checkCDP();
178
+ if (!cdpRunning) {
179
+ console.error(`[surfagent] Chrome not running on port ${CDP_PORT}. Run: surfagent chrome`);
180
+ process.exit(1);
181
+ }
182
+ await import('./api/server.js');
183
+ return;
184
+ }
185
+
186
+ if (command === 'start' || !command) {
187
+ log('Starting...');
188
+
189
+ // 1. Check/start Chrome
190
+ let cdpRunning = await checkCDP();
191
+ if (cdpRunning) {
192
+ log(`Chrome already running on port ${CDP_PORT}`);
193
+ } else {
194
+ const chromePath = getChromePath();
195
+ if (!chromePath) {
196
+ console.error('[surfagent] Chrome not found. Install Google Chrome and try again.');
197
+ process.exit(1);
198
+ }
199
+ startChrome(chromePath);
200
+ cdpRunning = await waitForCDP();
201
+ if (!cdpRunning) {
202
+ console.error('[surfagent] Chrome failed to start. Try running it manually with --remote-debugging-port=9222');
203
+ process.exit(1);
204
+ }
205
+ log('Chrome ready');
206
+ }
207
+
208
+ // 2. Start API
209
+ await import('./api/server.js');
210
+ return;
211
+ }
212
+
213
+ console.error(`Unknown command: ${command}. Run: surfagent help`);
214
+ process.exit(1);
215
+ }
216
+
217
+ main().catch((err) => {
218
+ console.error('[surfagent]', err.message);
219
+ process.exit(1);
220
+ });
@@ -1,33 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Start Chrome with remote debugging enabled
4
- # Uses a separate profile with copied auth data (required for Chrome 136+)
5
-
6
- PORT=${1:-9222}
7
- MAIN_PROFILE="$HOME/Library/Application Support/Google/Chrome/Default"
8
- DEBUG_PROFILE="/tmp/chrome-cdp"
9
-
10
- echo "Setting up Chrome debug profile..."
11
-
12
- # Create debug profile directory
13
- mkdir -p "$DEBUG_PROFILE/Default"
14
-
15
- # Copy auth data from main profile (preserves your logins)
16
- cp "$MAIN_PROFILE/Cookies" "$DEBUG_PROFILE/Default/" 2>/dev/null
17
- cp "$MAIN_PROFILE/Login Data" "$DEBUG_PROFILE/Default/" 2>/dev/null
18
- cp "$MAIN_PROFILE/Login Data For Account" "$DEBUG_PROFILE/Default/" 2>/dev/null
19
-
20
- echo "Starting Chrome with remote debugging on port $PORT..."
21
- echo "Note: This uses a separate profile with your login cookies copied over."
22
- echo ""
23
-
24
- /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
25
- --user-data-dir="$DEBUG_PROFILE" \
26
- --remote-debugging-port=$PORT \
27
- --disable-save-password-bubble \
28
- --disable-popup-blocking \
29
- --disable-notifications \
30
- --disable-infobars \
31
- --disable-translate \
32
- --disable-features=PasswordManager,AutofillSaveCardBubble,TranslateUI \
33
- --password-store=basic