@pablovitasso/szkrabok 1.0.10 → 1.0.13
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 +7 -4
- package/package.json +6 -8
- package/packages/runtime/config.js +30 -33
- package/packages/runtime/index.js +1 -1
- package/packages/runtime/launch.js +17 -1
- package/packages/runtime/package.json +5 -1
- package/scripts/release-publish.js +6 -7
- package/scripts/release-reminder.js +2 -3
- package/src/cli.js +30 -0
- package/src/tools/templates/szkrabok.config.local.toml.example +1 -2
- package/scripts/detect_browsers.sh +0 -147
package/README.md
CHANGED
|
@@ -28,9 +28,10 @@ MCP server supplementing [microsoft/playwright-mcp](https://github.com/microsoft
|
|
|
28
28
|
|
|
29
29
|
| Use Case | Command |
|
|
30
30
|
| --- | --- |
|
|
31
|
-
| **
|
|
32
|
-
| **Claude Code** | `claude mcp add szkrabok -- npx -y @pablovitasso/szkrabok` |
|
|
31
|
+
| **Claude Code — global (all projects)** | `claude mcp add --scope user szkrabok -- npx -y @pablovitasso/szkrabok` |
|
|
32
|
+
| **Claude Code — this project only** | `claude mcp add szkrabok -- npx -y @pablovitasso/szkrabok` |
|
|
33
33
|
| **Claude Desktop** | See config snippet below |
|
|
34
|
+
| **Scaffold a new project** | `npx @pablovitasso/szkrabok init` |
|
|
34
35
|
| **Development (from source)** | `npm ci && claude mcp add szkrabok node /path/to/szkrabok/src/index.js` |
|
|
35
36
|
|
|
36
37
|
Claude Desktop — add to `claude_desktop_config.json`:
|
|
@@ -45,8 +46,7 @@ Claude Desktop — add to `claude_desktop_config.json`:
|
|
|
45
46
|
}
|
|
46
47
|
```
|
|
47
48
|
|
|
48
|
-
> **Browser not
|
|
49
|
-
> Set `CI=true` or `SZKRABOK_SKIP_BROWSER_INSTALL=1` to suppress the auto-install in CI / Docker.
|
|
49
|
+
> **Browser not found?** Run `szkrabok detect-browser` to find installed browsers, or `szkrabok install-browser` to install Playwright's Chromium. Requires **Node.js ≥ 20**.
|
|
50
50
|
|
|
51
51
|
**2. Configure**
|
|
52
52
|
|
|
@@ -91,6 +91,9 @@ bebok session inspect <id> # Dump cookie/localStorage counts
|
|
|
91
91
|
bebok session delete <id> # Delete a session
|
|
92
92
|
bebok session cleanup --days 30 # Delete sessions unused for N days
|
|
93
93
|
bebok endpoint <sessionName> # Print CDP + WS endpoints
|
|
94
|
+
|
|
95
|
+
szkrabok detect-browser # List usable Chrome/Chromium installations
|
|
96
|
+
szkrabok install-browser # Install Playwright's Chromium
|
|
94
97
|
```
|
|
95
98
|
|
|
96
99
|
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pablovitasso/szkrabok",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "Production-grade MCP browser automation layer with persistent sessions and stealth capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"README.md"
|
|
19
19
|
],
|
|
20
20
|
"bin": {
|
|
21
|
-
"szkrabok": "
|
|
22
|
-
"bebok": "
|
|
21
|
+
"szkrabok": "src/index.js",
|
|
22
|
+
"bebok": "src/cli.js"
|
|
23
23
|
},
|
|
24
24
|
"engines": {
|
|
25
|
-
"node": ">=
|
|
25
|
+
"node": ">=20.0.0"
|
|
26
26
|
},
|
|
27
27
|
"workspaces": [
|
|
28
28
|
"packages/runtime"
|
|
@@ -37,10 +37,8 @@
|
|
|
37
37
|
"format:check": "prettier --check \"{src,tests}/**/*.{js,json,md}\" \"*.{js,json,md}\"",
|
|
38
38
|
"codegen:mcp": "node packages/runtime/mcp-client/codegen/generate-mcp-tools.mjs",
|
|
39
39
|
"prepack": "git describe --exact-match --tags HEAD 2>/dev/null || (echo 'ERROR: HEAD is not tagged. Run npm run release:patch or release:minor first.' && exit 1)",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"release:patch": "npm version patch --workspaces --include-workspace-root --ignore-scripts && npm run pack && node scripts/release-reminder.js",
|
|
43
|
-
"release:minor": "npm version minor --workspaces --include-workspace-root --ignore-scripts && npm run pack && node scripts/release-reminder.js",
|
|
40
|
+
"release:patch": "npm version patch --workspaces --include-workspace-root --ignore-scripts && node scripts/release-reminder.js",
|
|
41
|
+
"release:minor": "npm version minor --workspaces --include-workspace-root --ignore-scripts && node scripts/release-reminder.js",
|
|
44
42
|
"release:publish": "node scripts/release-publish.js",
|
|
45
43
|
"test": "npm run test:self && npm run test:auto",
|
|
46
44
|
"test:node": "node --test tests/node/*.test.js",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { homedir } from 'os';
|
|
2
1
|
import { join, resolve, dirname } from 'path';
|
|
3
|
-
import {
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
4
3
|
import { fileURLToPath } from 'url';
|
|
5
4
|
import { parse } from 'smol-toml';
|
|
6
5
|
|
|
@@ -134,40 +133,38 @@ export const TIMEZONE = defaults.timezone || 'America/New_York';
|
|
|
134
133
|
|
|
135
134
|
// ── Chromium path resolution ────────────────────────────────────────────────
|
|
136
135
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
.filter(d => d.startsWith('chromium-'))
|
|
147
|
-
.sort()
|
|
148
|
-
.reverse();
|
|
149
|
-
|
|
150
|
-
for (const dir of dirs) {
|
|
151
|
-
const paths = [
|
|
152
|
-
join(playwrightCache, dir, 'chrome-linux', 'chrome'),
|
|
153
|
-
join(playwrightCache, dir, 'chrome-linux64', 'chrome'),
|
|
154
|
-
];
|
|
155
|
-
|
|
156
|
-
for (const path of paths) {
|
|
157
|
-
if (existsSync(path)) return path;
|
|
158
|
-
}
|
|
136
|
+
// resolveBrowserPath — pure, injectable. Exported for testing.
|
|
137
|
+
// finders: array of async () => string|null, tried in order.
|
|
138
|
+
export const resolveBrowserPath = async (finders) => {
|
|
139
|
+
for (const finder of finders) {
|
|
140
|
+
try {
|
|
141
|
+
const path = await finder();
|
|
142
|
+
if (path) return path;
|
|
143
|
+
} catch {
|
|
144
|
+
// finder unavailable — try next
|
|
159
145
|
}
|
|
160
146
|
}
|
|
147
|
+
return null;
|
|
148
|
+
};
|
|
161
149
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
];
|
|
167
|
-
|
|
168
|
-
for (const path of systemChromiums) {
|
|
169
|
-
if (existsSync(path)) return path;
|
|
150
|
+
export const findChromiumPath = async () => {
|
|
151
|
+
// 1. User-configured path (highest priority)
|
|
152
|
+
if (tomlDefault.executablePath) {
|
|
153
|
+
return tomlDefault.executablePath;
|
|
170
154
|
}
|
|
171
155
|
|
|
172
|
-
return
|
|
156
|
+
return resolveBrowserPath([
|
|
157
|
+
// 2. System Chrome/Chromium/Brave/Edge via chrome-launcher
|
|
158
|
+
async () => {
|
|
159
|
+
const { Launcher } = await import('chrome-launcher');
|
|
160
|
+
const installs = await Launcher.getInstallations();
|
|
161
|
+
return installs[0] ?? null;
|
|
162
|
+
},
|
|
163
|
+
// 3. Playwright bundled browser
|
|
164
|
+
async () => {
|
|
165
|
+
const { chromium } = await import('playwright');
|
|
166
|
+
const pwPath = chromium.executablePath();
|
|
167
|
+
return pwPath && existsSync(pwPath) ? pwPath : null;
|
|
168
|
+
},
|
|
169
|
+
]);
|
|
173
170
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @szkrabok/runtime — public API
|
|
2
2
|
// Do NOT expose: pool internals, storage internals, stealth utilities
|
|
3
3
|
|
|
4
|
-
export { launch, connect } from './launch.js';
|
|
4
|
+
export { launch, connect, checkBrowser } from './launch.js';
|
|
5
5
|
export { closeSession, getSession, listSessions as listRuntimeSessions, listStoredSessions, updateSessionMeta, deleteStoredSession, updateSessionPage, closeAllSessions } from './sessions.js';
|
|
6
6
|
export { resolvePreset, PRESETS } from './config.js';
|
|
7
7
|
|
|
@@ -30,7 +30,7 @@ const cdpPortForId = id => {
|
|
|
30
30
|
const _launchPersistentContext = async (userDataDir, options = {}) => {
|
|
31
31
|
const presetConfig = options.presetConfig ?? {};
|
|
32
32
|
const pw = options.stealth ? enhanceWithStealth(chromium, presetConfig) : chromium;
|
|
33
|
-
const executablePath = findChromiumPath();
|
|
33
|
+
const executablePath = await findChromiumPath();
|
|
34
34
|
|
|
35
35
|
if (executablePath) {
|
|
36
36
|
log('Using existing Chromium for persistent context', { path: executablePath });
|
|
@@ -90,9 +90,25 @@ const _launchPersistentContext = async (userDataDir, options = {}) => {
|
|
|
90
90
|
* @param {boolean} [options.reuse] Return existing if profile already open (default: true)
|
|
91
91
|
* @returns {Promise<{ browser: import('playwright').Browser, context: import('playwright').BrowserContext, cdpEndpoint: string, close(): Promise<void> }>}
|
|
92
92
|
*/
|
|
93
|
+
export const checkBrowser = async () => {
|
|
94
|
+
const found = await findChromiumPath();
|
|
95
|
+
if (!found) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
'Chromium browser not found.\n\n' +
|
|
98
|
+
'Run:\n' +
|
|
99
|
+
' npx playwright install chromium\n\n' +
|
|
100
|
+
'Or:\n' +
|
|
101
|
+
' szkrabok install-browser\n'
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return found;
|
|
105
|
+
};
|
|
106
|
+
|
|
93
107
|
export const launch = async (options = {}) => {
|
|
94
108
|
const { profile = 'default', preset: presetName, headless, stealth, userAgent, viewport, locale, timezone, reuse = true } = options;
|
|
95
109
|
|
|
110
|
+
await checkBrowser();
|
|
111
|
+
|
|
96
112
|
// Idempotency: return existing handle when reuse=true and profile is open
|
|
97
113
|
if (reuse && pool.has(profile)) {
|
|
98
114
|
log(`Reusing existing session: ${profile}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@szkrabok/runtime",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "szkrabok — browser bootstrap, stealth, session pool, MCP client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"postinstall": "node scripts/patch-playwright.js"
|
|
16
16
|
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=20.0.0"
|
|
19
|
+
},
|
|
17
20
|
"dependencies": {
|
|
18
21
|
"@modelcontextprotocol/sdk": ">=1.0.0",
|
|
22
|
+
"chrome-launcher": "*",
|
|
19
23
|
"playwright": "*",
|
|
20
24
|
"playwright-core": "*",
|
|
21
25
|
"playwright-extra": "*",
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
1
|
import { execSync } from 'node:child_process';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { resolve, dirname } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
|
|
6
6
|
const pkg = JSON.parse(readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf8'));
|
|
7
7
|
const v = pkg.version;
|
|
8
|
-
const tarball = `dist/szkrabok-runtime-${v}.tgz`;
|
|
9
8
|
|
|
10
9
|
try {
|
|
11
|
-
execSync(
|
|
10
|
+
execSync('npm whoami', { stdio: 'pipe' });
|
|
12
11
|
} catch {
|
|
13
|
-
console.error('ERROR:
|
|
12
|
+
console.error('ERROR: not logged in to npm. Run: npm login');
|
|
14
13
|
process.exit(1);
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
console.log(`
|
|
18
|
-
execSync(
|
|
19
|
-
console.log(`\nDone.
|
|
16
|
+
console.log(`Publishing @pablovitasso/szkrabok@${v} to npm...`);
|
|
17
|
+
execSync('npm publish --access public', { stdio: 'inherit' });
|
|
18
|
+
console.log(`\nDone. https://www.npmjs.com/package/@pablovitasso/szkrabok`);
|
|
@@ -6,9 +6,8 @@ const pkg = JSON.parse(readFileSync(resolve(dirname(fileURLToPath(import.meta.ur
|
|
|
6
6
|
const v = pkg.version;
|
|
7
7
|
|
|
8
8
|
console.log(`
|
|
9
|
-
|
|
9
|
+
Version bumped to ${v}.
|
|
10
10
|
|
|
11
11
|
Next steps:
|
|
12
|
-
|
|
13
|
-
2. Update RUNTIME_RELEASES in src/tools/scaffold.js (add '${v}' entry, bump CURRENT_RUNTIME_VERSION)
|
|
12
|
+
npm run release:publish
|
|
14
13
|
`);
|
package/src/cli.js
CHANGED
|
@@ -163,4 +163,34 @@ program
|
|
|
163
163
|
}
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
+
/* ---------- detect-browser command ---------- */
|
|
167
|
+
|
|
168
|
+
program
|
|
169
|
+
.command('detect-browser')
|
|
170
|
+
.description('Detect usable Chrome/Chromium browsers')
|
|
171
|
+
.action(async () => {
|
|
172
|
+
const { findChromiumPath } = await import('#runtime');
|
|
173
|
+
const path = await findChromiumPath();
|
|
174
|
+
if (!path) {
|
|
175
|
+
console.log('No usable Chrome/Chromium browser found.\n');
|
|
176
|
+
console.log(' szkrabok install-browser');
|
|
177
|
+
console.log(' https://www.google.com/chrome/\n');
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
console.log(path);
|
|
181
|
+
console.log('\nRecommended configuration:\n\n[default]');
|
|
182
|
+
console.log(`executablePath = "${path}"`);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
/* ---------- install-browser command ---------- */
|
|
186
|
+
|
|
187
|
+
program
|
|
188
|
+
.command('install-browser')
|
|
189
|
+
.description('Install Chromium browser via Playwright')
|
|
190
|
+
.action(async () => {
|
|
191
|
+
const { spawn } = await import('node:child_process');
|
|
192
|
+
const proc = spawn('npx', ['playwright', 'install', 'chromium'], { stdio: 'inherit' });
|
|
193
|
+
proc.on('close', code => process.exit(code ?? 0));
|
|
194
|
+
});
|
|
195
|
+
|
|
166
196
|
program.parse();
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
# Machine-specific overrides. Copy to szkrabok.config.local.toml and edit.
|
|
3
3
|
# This file is gitignored — never commit credentials or paths here.
|
|
4
4
|
#
|
|
5
|
-
# Run `
|
|
6
|
-
# to find your Chrome/Chromium binary path.
|
|
5
|
+
# Run `szkrabok detect-browser` to find Chrome/Chromium binary paths.
|
|
7
6
|
|
|
8
7
|
[default]
|
|
9
8
|
# executablePath = "/path/to/chrome"
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# detect_browsers.sh — find Chrome/Chromium binaries and echo szkrabok.config.toml lines
|
|
3
|
-
#
|
|
4
|
-
# Usage:
|
|
5
|
-
# bash scripts/detect_browsers.sh
|
|
6
|
-
#
|
|
7
|
-
# Output:
|
|
8
|
-
# For each detected browser: its version + the TOML executablePath line to use.
|
|
9
|
-
# If nothing useful is found: installation suggestions.
|
|
10
|
-
#
|
|
11
|
-
# Copy the executablePath line you want into szkrabok.config.toml [default] section.
|
|
12
|
-
# Google Chrome stable is best for stealth (native brands). Ungoogled-chromium is a
|
|
13
|
-
# good second choice. The Playwright bundled binary (Chrome for Testing) should be
|
|
14
|
-
# avoided in production — it brands itself as automation tooling.
|
|
15
|
-
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
|
|
18
|
-
FOUND=()
|
|
19
|
-
|
|
20
|
-
# ── helpers ───────────────────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
get_version() {
|
|
23
|
-
# Run binary with --version, strip leading "Chromium ", "Google Chrome " etc.
|
|
24
|
-
timeout 5 "$1" --version 2>/dev/null | head -1 | sed 's/^[^0-9]*//' || true
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
check_binary() {
|
|
28
|
-
local label="$1" path="$2"
|
|
29
|
-
if [[ -x "$path" ]]; then
|
|
30
|
-
local ver
|
|
31
|
-
ver="$(get_version "$path")"
|
|
32
|
-
if [[ -n "$ver" ]]; then
|
|
33
|
-
echo " FOUND $label — $ver"
|
|
34
|
-
echo " executablePath = \"$path\""
|
|
35
|
-
echo ""
|
|
36
|
-
FOUND+=("$label")
|
|
37
|
-
fi
|
|
38
|
-
fi
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
check_flatpak() {
|
|
42
|
-
local label="$1" app_id="$2"
|
|
43
|
-
if command -v flatpak >/dev/null 2>&1 && flatpak info "$app_id" >/dev/null 2>&1; then
|
|
44
|
-
local ver
|
|
45
|
-
ver="$(timeout 5 flatpak run "$app_id" --version 2>/dev/null | head -1 | sed 's/^[^0-9]*//' || true)"
|
|
46
|
-
if [[ -n "$ver" ]]; then
|
|
47
|
-
# Write a small wrapper path check — flatpak run is the executable path
|
|
48
|
-
local wrapper
|
|
49
|
-
wrapper="$(command -v flatpak)"
|
|
50
|
-
echo " FOUND $label — $ver"
|
|
51
|
-
echo " # flatpak binary — use a wrapper script or the flatpak run command:"
|
|
52
|
-
echo " executablePath = \"$HOME/.local/bin/$(echo "$app_id" | tr '.' '-' | tr '[:upper:]' '[:lower:]')\""
|
|
53
|
-
echo " # (create that wrapper: echo '#!/bin/sh' > the path, then:"
|
|
54
|
-
echo " # echo 'exec flatpak run $app_id \"\$@\"' >> the path, chmod +x)"
|
|
55
|
-
echo ""
|
|
56
|
-
FOUND+=("$label")
|
|
57
|
-
fi
|
|
58
|
-
fi
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
check_snap() {
|
|
62
|
-
local label="$1" snap_name="$2" snap_bin="$3"
|
|
63
|
-
if [[ -x "$snap_bin" ]]; then
|
|
64
|
-
local ver
|
|
65
|
-
ver="$(get_version "$snap_bin")"
|
|
66
|
-
if [[ -n "$ver" ]]; then
|
|
67
|
-
echo " FOUND $label — $ver"
|
|
68
|
-
echo " executablePath = \"$snap_bin\""
|
|
69
|
-
echo ""
|
|
70
|
-
FOUND+=("$label")
|
|
71
|
-
fi
|
|
72
|
-
fi
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
# ── scan ──────────────────────────────────────────────────────────────────────
|
|
76
|
-
|
|
77
|
-
echo ""
|
|
78
|
-
echo "=== szkrabok browser detection ==="
|
|
79
|
-
echo ""
|
|
80
|
-
echo "Scanning for usable Chrome/Chromium binaries..."
|
|
81
|
-
echo ""
|
|
82
|
-
|
|
83
|
-
# Google Chrome stable (best for stealth — native brands)
|
|
84
|
-
check_binary "Google Chrome stable" "/usr/bin/google-chrome"
|
|
85
|
-
check_binary "Google Chrome stable" "/usr/bin/google-chrome-stable"
|
|
86
|
-
check_binary "Google Chrome stable" "/opt/google/chrome/chrome"
|
|
87
|
-
check_binary "Google Chrome stable" "/opt/google/chrome/google-chrome"
|
|
88
|
-
|
|
89
|
-
# Chromium (distro package)
|
|
90
|
-
check_binary "Chromium (distro)" "/usr/bin/chromium"
|
|
91
|
-
check_binary "Chromium (distro)" "/usr/bin/chromium-browser"
|
|
92
|
-
|
|
93
|
-
# Ungoogled-chromium — common wrapper locations
|
|
94
|
-
check_binary "Ungoogled-chromium" "$HOME/.local/bin/ungoogled-chromium"
|
|
95
|
-
check_binary "Ungoogled-chromium" "/usr/bin/ungoogled-chromium"
|
|
96
|
-
|
|
97
|
-
# Ungoogled-chromium via flatpak — only if no wrapper binary was found above
|
|
98
|
-
if [[ ! -x "$HOME/.local/bin/ungoogled-chromium" && ! -x "/usr/bin/ungoogled-chromium" ]]; then
|
|
99
|
-
check_flatpak "Ungoogled-chromium (flatpak)" "io.github.ungoogled_software.ungoogled_chromium"
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
# Chromium via snap
|
|
103
|
-
check_snap "Chromium (snap)" "chromium" "/snap/bin/chromium"
|
|
104
|
-
|
|
105
|
-
# Brave
|
|
106
|
-
check_binary "Brave" "/usr/bin/brave-browser"
|
|
107
|
-
check_binary "Brave" "/usr/bin/brave-browser-stable"
|
|
108
|
-
check_binary "Brave" "/opt/brave.com/brave/brave"
|
|
109
|
-
|
|
110
|
-
# Microsoft Edge (Chromium-based)
|
|
111
|
-
check_binary "Microsoft Edge" "/usr/bin/microsoft-edge"
|
|
112
|
-
check_binary "Microsoft Edge" "/usr/bin/microsoft-edge-stable"
|
|
113
|
-
check_binary "Microsoft Edge" "/opt/microsoft/msedge/msedge"
|
|
114
|
-
|
|
115
|
-
# ── results ───────────────────────────────────────────────────────────────────
|
|
116
|
-
|
|
117
|
-
if [[ ${#FOUND[@]} -eq 0 ]]; then
|
|
118
|
-
echo " NONE FOUND — no usable Chrome/Chromium binary detected."
|
|
119
|
-
echo ""
|
|
120
|
-
echo " szkrabok will fall back to the Playwright bundled 'Chrome for Testing'."
|
|
121
|
-
echo " This works but is detectable as automation tooling (brands itself as"
|
|
122
|
-
echo " 'Chrome for Testing' in navigator.userAgentData)."
|
|
123
|
-
echo ""
|
|
124
|
-
echo " Recommended installations:"
|
|
125
|
-
echo ""
|
|
126
|
-
echo " 1. Google Chrome stable (best stealth — native brands):"
|
|
127
|
-
echo " https://www.google.com/chrome/"
|
|
128
|
-
echo " wget -qO- https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -"
|
|
129
|
-
echo " sudo sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" > /etc/apt/sources.list.d/google-chrome.list'"
|
|
130
|
-
echo " sudo apt-get update && sudo apt-get install google-chrome-stable"
|
|
131
|
-
echo ""
|
|
132
|
-
echo " 2. Ungoogled-chromium via flatpak (no Google services, good stealth):"
|
|
133
|
-
echo " flatpak install flathub io.github.ungoogled_software.ungoogled_chromium"
|
|
134
|
-
echo " # then create a wrapper: ~/.local/bin/ungoogled-chromium"
|
|
135
|
-
echo " # with: exec flatpak run io.github.ungoogled_software.ungoogled_chromium \"\$@\""
|
|
136
|
-
echo ""
|
|
137
|
-
else
|
|
138
|
-
echo " Copy one executablePath line above into szkrabok.config.toml [default]."
|
|
139
|
-
echo ""
|
|
140
|
-
echo " Stealth ranking (best first):"
|
|
141
|
-
echo " 1. Google Chrome stable — native 'Google Chrome' brands, most trusted"
|
|
142
|
-
echo " 2. Ungoogled-chromium — no Google services; needs greasy brands patch"
|
|
143
|
-
echo " 3. Chromium (distro) — same as ungoogled; needs greasy brands patch"
|
|
144
|
-
echo " 4. Chrome for Testing — avoid in production (automation-branded)"
|
|
145
|
-
fi
|
|
146
|
-
|
|
147
|
-
echo ""
|