rechrome 1.46.0 → 1.47.0
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 +8 -1
- package/package.json +1 -1
- package/rechrome.js +56 -13
- package/rechrome.ts +56 -13
package/README.md
CHANGED
|
@@ -56,6 +56,9 @@ rech tab-list
|
|
|
56
56
|
rech eval "() => document.title"
|
|
57
57
|
rech --profile work@example.com open https://example.com # another registered profile
|
|
58
58
|
rech --isolate open https://accounts.example.com # throwaway session, e.g. for a login flow
|
|
59
|
+
rech --isolate=login open https://accounts.example.com # named isolated session: reused by later
|
|
60
|
+
rech --isolate=login fill-secret e12 --from-env PASSWORD # --isolate=login commands (same tabs)
|
|
61
|
+
rech session close login # until you close it (rech session ls lists it)
|
|
59
62
|
```
|
|
60
63
|
|
|
61
64
|
Any [playwright-cli](https://github.com/snomiao/playwright-cli) command works after `rech`. When a
|
|
@@ -545,7 +548,11 @@ Each client gets its own browser session, keyed by the **git worktree root path*
|
|
|
545
548
|
roll up to their parent), or the current directory outside git. So two worktrees of one repo
|
|
546
549
|
get separate sessions, and `git checkout` keeps you in the same one. `RECH_IDENTITY=branch`
|
|
547
550
|
restores the older `<remote>/tree/<branch>` keying and `RECH_IDENTITY=cwd` keys on the exact
|
|
548
|
-
directory. Pass `-s=<name>` for a named sub-session,
|
|
551
|
+
directory. Pass `-s=<name>` for a named sub-session, `--isolate` for a throwaway one (a new session per
|
|
552
|
+
command), or `--isolate=<name>` for a named isolated session (`-s=iso_<name>`) that later
|
|
553
|
+
`--isolate=<name>` commands from the same worktree reuse until `rech session close <name>`.
|
|
554
|
+
An isolated session is its own tab group in the same Chrome profile: it shares the profile's
|
|
555
|
+
cookies, so profile-scoped listeners still refuse `eval`, `run-code` and other arbitrary code in it.
|
|
549
556
|
A share device's sessions are additionally keyed by its share and device, so they never meet
|
|
550
557
|
another device's or a listener link's; `rech session ls` lists the ones this link drove.
|
|
551
558
|
|
package/package.json
CHANGED
package/rechrome.js
CHANGED
|
@@ -2059,7 +2059,7 @@ export function withDefaultScheme(target: string): string {
|
|
|
2059
2059
|
// `open --profile <dir>`, a user-data-dir path) and must pass through untouched. Throws on a
|
|
2060
2060
|
// missing value; accepts multiple occurrences (last one wins).
|
|
2061
2061
|
/**
|
|
2062
|
-
* `rech [--profile X] [--isolate] pw <args>` forwards <args> to playwright-cli verbatim, so
|
|
2062
|
+
* `rech [--profile X] [--isolate[=<name>]] pw <args>` forwards <args> to playwright-cli verbatim, so
|
|
2063
2063
|
* `rech pw --version` or `rech pw status` reach playwright instead of rech. `--` works the
|
|
2064
2064
|
* same after a rech flag (`rech --profile X -- status`); a bare leading `--` cannot, because
|
|
2065
2065
|
* Bun consumes the `--` right after the script path. The separator counts only when
|
|
@@ -2071,12 +2071,32 @@ export function rechSeparatorIndex(args: string[]): number {
|
|
|
2071
2071
|
const a = args[i];
|
|
2072
2072
|
if (a === "--" || a === "pw" || a === "playwright") return i;
|
|
2073
2073
|
if (a === "--profile") { i++; continue; }
|
|
2074
|
-
if (a.startsWith("--profile=") || a === "--isolate" || a === "--isolated") continue;
|
|
2074
|
+
if (a.startsWith("--profile=") || a === "--isolate" || a === "--isolated" || /^--isolated?=/.test(a)) continue;
|
|
2075
2075
|
return -1;
|
|
2076
2076
|
}
|
|
2077
2077
|
return -1;
|
|
2078
2078
|
}
|
|
2079
2079
|
|
|
2080
|
+
/** Prefix of a named isolated session (`--isolate=<name>` -> `-s=iso_<name>`); `_` keeps it out of the iso-<hex> reaper. */
|
|
2081
|
+
export const NAMED_ISO_PREFIX = "iso_";
|
|
2082
|
+
|
|
2083
|
+
/**
|
|
2084
|
+
* Turn rech's `--isolate` / `--isolate=<name>` into a session flag. Bare `--isolate` is a
|
|
2085
|
+
* throwaway `-s=iso-<random>` (reaped when idle); `--isolate=<name>` is the persistent
|
|
2086
|
+
* `-s=iso_<name>`, reused by later commands with the same name until `rech session close <name>`.
|
|
2087
|
+
*/
|
|
2088
|
+
export function applyIsolateArg(args: string[]): string[] {
|
|
2089
|
+
const idx = args.findIndex(a => a === "--isolate" || a === "--isolated" || /^--isolated?=/.test(a));
|
|
2090
|
+
if (idx === -1) return args;
|
|
2091
|
+
const flag = args[idx];
|
|
2092
|
+
const rest = args.filter((_, i) => i !== idx);
|
|
2093
|
+
if (!flag.includes("=")) return [...rest, `-s=iso-${randomBytes(8).toString("hex")}`];
|
|
2094
|
+
const name = flag.slice(flag.indexOf("=") + 1);
|
|
2095
|
+
if (!/^[a-zA-Z0-9_-]{1,60}$/.test(name)) throw new Error(`--isolate=<name> takes 1-60 letters, digits, '-' or '_' (got "${name}")`);
|
|
2096
|
+
if (rest.some(a => a.startsWith("-s="))) throw new Error("Pass --isolate=<name> or -s=<session>, not both.");
|
|
2097
|
+
return [...rest, `-s=${NAMED_ISO_PREFIX}${name}`];
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2080
2100
|
/** rechrome's own version, from the package.json shipped next to this file. */
|
|
2081
2101
|
export function rechromeVersion(): string {
|
|
2082
2102
|
try { return JSON.parse(readFileSync(join(import.meta.dir, "package.json"), "utf8")).version ?? "unknown"; }
|
|
@@ -4585,22 +4605,40 @@ async function bridgeCommand(): Promise<void> {
|
|
|
4585
4605
|
|
|
4586
4606
|
// ---- sessions (client view) -----------------------------------------------------------------
|
|
4587
4607
|
|
|
4608
|
+
type SessionRow = { session: string; profile?: string; client?: string; owner?: string; lastUsed: number; live: boolean };
|
|
4609
|
+
|
|
4610
|
+
async function fetchSessions(url: string): Promise<{ res: Response; body: { sessions?: SessionRow[]; stderr?: string } | null }> {
|
|
4611
|
+
const res = await fetch(serviceUrl(url, "sessions"), { headers: { Authorization: `Bearer ${parseUrl(url).key}` }, signal: AbortSignal.timeout(10_000) });
|
|
4612
|
+
return { res, body: await res.json().catch(() => null) as { sessions?: SessionRow[]; stderr?: string } | null };
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4615
|
+
/** `name` as given, unless only the named isolated session `iso_<name>` exists. */
|
|
4616
|
+
export function pickSessionName(name: string, known: string[]): string {
|
|
4617
|
+
if (name.startsWith(NAMED_ISO_PREFIX) || known.includes(name)) return name;
|
|
4618
|
+
return known.includes(NAMED_ISO_PREFIX + name) ? NAMED_ISO_PREFIX + name : name;
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4621
|
+
async function resolveSessionName(url: string, name: string): Promise<string> {
|
|
4622
|
+
const known = await fetchSessions(url).then(({ body }) => (body?.sessions ?? []).map(s => s.session)).catch(() => [] as string[]);
|
|
4623
|
+
return pickSessionName(name, known);
|
|
4624
|
+
}
|
|
4625
|
+
|
|
4588
4626
|
async function sessionCommand(action: string, name?: string): Promise<void> {
|
|
4589
4627
|
const raw = process.env[ENV_KEY];
|
|
4590
4628
|
if (!raw) throw new Error(notConnectedMessage());
|
|
4591
4629
|
const url = await transportUrl(raw);
|
|
4592
4630
|
if (action === "close") {
|
|
4593
4631
|
if (!name) throw new Error("Which session? rech session close <name> (see rech session ls)");
|
|
4594
|
-
|
|
4632
|
+
// A named isolated session closes by its --isolate name too (`login` for iso_login).
|
|
4633
|
+
return run(url, ["close", `-s=${await resolveSessionName(url, name)}`]);
|
|
4595
4634
|
}
|
|
4596
|
-
const res
|
|
4597
|
-
const body = await res.json().catch(() => null) as { sessions?: { session: string; profile?: string; client?: string; owner?: string; lastUsed: number; live: boolean }[]; stderr?: string } | null;
|
|
4635
|
+
const { res, body } = await fetchSessions(url);
|
|
4598
4636
|
if (!res.ok || !body?.sessions) throw new Error(body?.stderr?.trim() || `The host does not list sessions (HTTP ${res.status}); it may run an older rech.`);
|
|
4599
4637
|
if (!body.sessions.length) { console.log("No sessions yet (since the host's daemon started)."); return; }
|
|
4600
4638
|
const rows = [["SESSION", "PROFILE", "CLIENT", "LAST USED", "STATE"]];
|
|
4601
4639
|
for (const s of body.sessions) rows.push([s.session, s.profile ?? "-", s.client ?? "-", fmtDate(s.lastUsed), s.live ? "open" : "closed"]);
|
|
4602
4640
|
printTable(rows);
|
|
4603
|
-
console.log(`\nUse one: rech -s=<session> open https://example.com · close it: rech session close <session>`);
|
|
4641
|
+
console.log(`\nUse one: rech -s=<session> open https://example.com (an ${NAMED_ISO_PREFIX}<name> session: rech --isolate=<name> …) · close it: rech session close <session>`);
|
|
4604
4642
|
}
|
|
4605
4643
|
|
|
4606
4644
|
async function signalServe(opts: { host?: string; port?: number }): Promise<void> {
|
|
@@ -4731,10 +4769,12 @@ const HELP_USAGE = `rechrome (rech) — drive your real, logged-in Chrome from s
|
|
|
4731
4769
|
Usage: rech <command> [options] · rech <browser-command> [args]`;
|
|
4732
4770
|
|
|
4733
4771
|
const HELP_EPILOGUE = `Browser commands (sent to this project's Chrome session):
|
|
4734
|
-
rech [--profile <p>] [--isolate] <browser-command> [args]
|
|
4772
|
+
rech [--profile <p>] [--isolate[=<name>]] <browser-command> [args]
|
|
4735
4773
|
open, goto, click, fill, screenshot, eval, tab-list… (\`rech pw --help\` lists all)
|
|
4736
4774
|
--profile <p> as another registered profile (email, name or folder); put it first
|
|
4737
|
-
--isolate in a throwaway session
|
|
4775
|
+
--isolate in a throwaway session (a new one per command)
|
|
4776
|
+
--isolate=<n> in the named isolated session <n>: made on first use, reused by later
|
|
4777
|
+
commands (same tabs, same page) until \`rech session close <n>\`
|
|
4738
4778
|
rech fill-secret <ref> --from-env VAR | --totp-from-env VAR [--env-file f] [--allow-domain '*.example.com']
|
|
4739
4779
|
type a password / TOTP code without it reaching argv, logs or output
|
|
4740
4780
|
rech read-secret <ref> --allow-domain <host> | <vault command>
|
|
@@ -4894,7 +4934,7 @@ export function rechCli(argv: string[], handlers: RechHandlers) {
|
|
|
4894
4934
|
.command("remove <name>", "Remove a listener", y => y.positional("name", { type: "string", demandOption: true }),
|
|
4895
4935
|
a => handlers.removeListener(a.name))
|
|
4896
4936
|
.demandCommand(1).strict())
|
|
4897
|
-
.command(["session [action] [name]", "sessions [action] [name]"], "This link's browser sessions on the host: ls (default) | close <name>", y => y
|
|
4937
|
+
.command(["session [action] [name]", "sessions [action] [name]"], "This link's browser sessions on the host: ls (default) | close <name> (also an --isolate=<name> session)", y => y
|
|
4898
4938
|
.positional("action", { type: "string", choices: ["ls", "list", "close"], default: "ls" })
|
|
4899
4939
|
.positional("name", { type: "string", describe: "With close: the session (as `rech session ls` shows it)" }),
|
|
4900
4940
|
a => handlers.session(a.action === "list" ? "ls" : a.action!, a.name))
|
|
@@ -5041,10 +5081,13 @@ if (import.meta.main) {
|
|
|
5041
5081
|
// flows (OAuth/login) that must not share tabs with the worktree's default session. The `iso-`
|
|
5042
5082
|
// marker lets the daemon reap these throwaway sessions on an idle TTL (see serve.js), so an
|
|
5043
5083
|
// OAuth drive can't leak an orphaned browser context.
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5084
|
+
// --isolate=<name>: a named isolated session (-s=iso_<name>), kept across commands until
|
|
5085
|
+
// `rech session close <name>`, for multi-step flows (email, password, TOTP).
|
|
5086
|
+
try { args = applyIsolateArg(args); }
|
|
5087
|
+
catch (err) {
|
|
5088
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
5089
|
+
envWatcher?.close();
|
|
5090
|
+
process.exit(1);
|
|
5048
5091
|
}
|
|
5049
5092
|
args = [...forwarded, ...args];
|
|
5050
5093
|
await run(url, args, overrideEnv, { verbatim: separator !== -1 });
|
package/rechrome.ts
CHANGED
|
@@ -2059,7 +2059,7 @@ export function withDefaultScheme(target: string): string {
|
|
|
2059
2059
|
// `open --profile <dir>`, a user-data-dir path) and must pass through untouched. Throws on a
|
|
2060
2060
|
// missing value; accepts multiple occurrences (last one wins).
|
|
2061
2061
|
/**
|
|
2062
|
-
* `rech [--profile X] [--isolate] pw <args>` forwards <args> to playwright-cli verbatim, so
|
|
2062
|
+
* `rech [--profile X] [--isolate[=<name>]] pw <args>` forwards <args> to playwright-cli verbatim, so
|
|
2063
2063
|
* `rech pw --version` or `rech pw status` reach playwright instead of rech. `--` works the
|
|
2064
2064
|
* same after a rech flag (`rech --profile X -- status`); a bare leading `--` cannot, because
|
|
2065
2065
|
* Bun consumes the `--` right after the script path. The separator counts only when
|
|
@@ -2071,12 +2071,32 @@ export function rechSeparatorIndex(args: string[]): number {
|
|
|
2071
2071
|
const a = args[i];
|
|
2072
2072
|
if (a === "--" || a === "pw" || a === "playwright") return i;
|
|
2073
2073
|
if (a === "--profile") { i++; continue; }
|
|
2074
|
-
if (a.startsWith("--profile=") || a === "--isolate" || a === "--isolated") continue;
|
|
2074
|
+
if (a.startsWith("--profile=") || a === "--isolate" || a === "--isolated" || /^--isolated?=/.test(a)) continue;
|
|
2075
2075
|
return -1;
|
|
2076
2076
|
}
|
|
2077
2077
|
return -1;
|
|
2078
2078
|
}
|
|
2079
2079
|
|
|
2080
|
+
/** Prefix of a named isolated session (`--isolate=<name>` -> `-s=iso_<name>`); `_` keeps it out of the iso-<hex> reaper. */
|
|
2081
|
+
export const NAMED_ISO_PREFIX = "iso_";
|
|
2082
|
+
|
|
2083
|
+
/**
|
|
2084
|
+
* Turn rech's `--isolate` / `--isolate=<name>` into a session flag. Bare `--isolate` is a
|
|
2085
|
+
* throwaway `-s=iso-<random>` (reaped when idle); `--isolate=<name>` is the persistent
|
|
2086
|
+
* `-s=iso_<name>`, reused by later commands with the same name until `rech session close <name>`.
|
|
2087
|
+
*/
|
|
2088
|
+
export function applyIsolateArg(args: string[]): string[] {
|
|
2089
|
+
const idx = args.findIndex(a => a === "--isolate" || a === "--isolated" || /^--isolated?=/.test(a));
|
|
2090
|
+
if (idx === -1) return args;
|
|
2091
|
+
const flag = args[idx];
|
|
2092
|
+
const rest = args.filter((_, i) => i !== idx);
|
|
2093
|
+
if (!flag.includes("=")) return [...rest, `-s=iso-${randomBytes(8).toString("hex")}`];
|
|
2094
|
+
const name = flag.slice(flag.indexOf("=") + 1);
|
|
2095
|
+
if (!/^[a-zA-Z0-9_-]{1,60}$/.test(name)) throw new Error(`--isolate=<name> takes 1-60 letters, digits, '-' or '_' (got "${name}")`);
|
|
2096
|
+
if (rest.some(a => a.startsWith("-s="))) throw new Error("Pass --isolate=<name> or -s=<session>, not both.");
|
|
2097
|
+
return [...rest, `-s=${NAMED_ISO_PREFIX}${name}`];
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2080
2100
|
/** rechrome's own version, from the package.json shipped next to this file. */
|
|
2081
2101
|
export function rechromeVersion(): string {
|
|
2082
2102
|
try { return JSON.parse(readFileSync(join(import.meta.dir, "package.json"), "utf8")).version ?? "unknown"; }
|
|
@@ -4585,22 +4605,40 @@ async function bridgeCommand(): Promise<void> {
|
|
|
4585
4605
|
|
|
4586
4606
|
// ---- sessions (client view) -----------------------------------------------------------------
|
|
4587
4607
|
|
|
4608
|
+
type SessionRow = { session: string; profile?: string; client?: string; owner?: string; lastUsed: number; live: boolean };
|
|
4609
|
+
|
|
4610
|
+
async function fetchSessions(url: string): Promise<{ res: Response; body: { sessions?: SessionRow[]; stderr?: string } | null }> {
|
|
4611
|
+
const res = await fetch(serviceUrl(url, "sessions"), { headers: { Authorization: `Bearer ${parseUrl(url).key}` }, signal: AbortSignal.timeout(10_000) });
|
|
4612
|
+
return { res, body: await res.json().catch(() => null) as { sessions?: SessionRow[]; stderr?: string } | null };
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4615
|
+
/** `name` as given, unless only the named isolated session `iso_<name>` exists. */
|
|
4616
|
+
export function pickSessionName(name: string, known: string[]): string {
|
|
4617
|
+
if (name.startsWith(NAMED_ISO_PREFIX) || known.includes(name)) return name;
|
|
4618
|
+
return known.includes(NAMED_ISO_PREFIX + name) ? NAMED_ISO_PREFIX + name : name;
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4621
|
+
async function resolveSessionName(url: string, name: string): Promise<string> {
|
|
4622
|
+
const known = await fetchSessions(url).then(({ body }) => (body?.sessions ?? []).map(s => s.session)).catch(() => [] as string[]);
|
|
4623
|
+
return pickSessionName(name, known);
|
|
4624
|
+
}
|
|
4625
|
+
|
|
4588
4626
|
async function sessionCommand(action: string, name?: string): Promise<void> {
|
|
4589
4627
|
const raw = process.env[ENV_KEY];
|
|
4590
4628
|
if (!raw) throw new Error(notConnectedMessage());
|
|
4591
4629
|
const url = await transportUrl(raw);
|
|
4592
4630
|
if (action === "close") {
|
|
4593
4631
|
if (!name) throw new Error("Which session? rech session close <name> (see rech session ls)");
|
|
4594
|
-
|
|
4632
|
+
// A named isolated session closes by its --isolate name too (`login` for iso_login).
|
|
4633
|
+
return run(url, ["close", `-s=${await resolveSessionName(url, name)}`]);
|
|
4595
4634
|
}
|
|
4596
|
-
const res
|
|
4597
|
-
const body = await res.json().catch(() => null) as { sessions?: { session: string; profile?: string; client?: string; owner?: string; lastUsed: number; live: boolean }[]; stderr?: string } | null;
|
|
4635
|
+
const { res, body } = await fetchSessions(url);
|
|
4598
4636
|
if (!res.ok || !body?.sessions) throw new Error(body?.stderr?.trim() || `The host does not list sessions (HTTP ${res.status}); it may run an older rech.`);
|
|
4599
4637
|
if (!body.sessions.length) { console.log("No sessions yet (since the host's daemon started)."); return; }
|
|
4600
4638
|
const rows = [["SESSION", "PROFILE", "CLIENT", "LAST USED", "STATE"]];
|
|
4601
4639
|
for (const s of body.sessions) rows.push([s.session, s.profile ?? "-", s.client ?? "-", fmtDate(s.lastUsed), s.live ? "open" : "closed"]);
|
|
4602
4640
|
printTable(rows);
|
|
4603
|
-
console.log(`\nUse one: rech -s=<session> open https://example.com · close it: rech session close <session>`);
|
|
4641
|
+
console.log(`\nUse one: rech -s=<session> open https://example.com (an ${NAMED_ISO_PREFIX}<name> session: rech --isolate=<name> …) · close it: rech session close <session>`);
|
|
4604
4642
|
}
|
|
4605
4643
|
|
|
4606
4644
|
async function signalServe(opts: { host?: string; port?: number }): Promise<void> {
|
|
@@ -4731,10 +4769,12 @@ const HELP_USAGE = `rechrome (rech) — drive your real, logged-in Chrome from s
|
|
|
4731
4769
|
Usage: rech <command> [options] · rech <browser-command> [args]`;
|
|
4732
4770
|
|
|
4733
4771
|
const HELP_EPILOGUE = `Browser commands (sent to this project's Chrome session):
|
|
4734
|
-
rech [--profile <p>] [--isolate] <browser-command> [args]
|
|
4772
|
+
rech [--profile <p>] [--isolate[=<name>]] <browser-command> [args]
|
|
4735
4773
|
open, goto, click, fill, screenshot, eval, tab-list… (\`rech pw --help\` lists all)
|
|
4736
4774
|
--profile <p> as another registered profile (email, name or folder); put it first
|
|
4737
|
-
--isolate in a throwaway session
|
|
4775
|
+
--isolate in a throwaway session (a new one per command)
|
|
4776
|
+
--isolate=<n> in the named isolated session <n>: made on first use, reused by later
|
|
4777
|
+
commands (same tabs, same page) until \`rech session close <n>\`
|
|
4738
4778
|
rech fill-secret <ref> --from-env VAR | --totp-from-env VAR [--env-file f] [--allow-domain '*.example.com']
|
|
4739
4779
|
type a password / TOTP code without it reaching argv, logs or output
|
|
4740
4780
|
rech read-secret <ref> --allow-domain <host> | <vault command>
|
|
@@ -4894,7 +4934,7 @@ export function rechCli(argv: string[], handlers: RechHandlers) {
|
|
|
4894
4934
|
.command("remove <name>", "Remove a listener", y => y.positional("name", { type: "string", demandOption: true }),
|
|
4895
4935
|
a => handlers.removeListener(a.name))
|
|
4896
4936
|
.demandCommand(1).strict())
|
|
4897
|
-
.command(["session [action] [name]", "sessions [action] [name]"], "This link's browser sessions on the host: ls (default) | close <name>", y => y
|
|
4937
|
+
.command(["session [action] [name]", "sessions [action] [name]"], "This link's browser sessions on the host: ls (default) | close <name> (also an --isolate=<name> session)", y => y
|
|
4898
4938
|
.positional("action", { type: "string", choices: ["ls", "list", "close"], default: "ls" })
|
|
4899
4939
|
.positional("name", { type: "string", describe: "With close: the session (as `rech session ls` shows it)" }),
|
|
4900
4940
|
a => handlers.session(a.action === "list" ? "ls" : a.action!, a.name))
|
|
@@ -5041,10 +5081,13 @@ if (import.meta.main) {
|
|
|
5041
5081
|
// flows (OAuth/login) that must not share tabs with the worktree's default session. The `iso-`
|
|
5042
5082
|
// marker lets the daemon reap these throwaway sessions on an idle TTL (see serve.ts), so an
|
|
5043
5083
|
// OAuth drive can't leak an orphaned browser context.
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5084
|
+
// --isolate=<name>: a named isolated session (-s=iso_<name>), kept across commands until
|
|
5085
|
+
// `rech session close <name>`, for multi-step flows (email, password, TOTP).
|
|
5086
|
+
try { args = applyIsolateArg(args); }
|
|
5087
|
+
catch (err) {
|
|
5088
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
5089
|
+
envWatcher?.close();
|
|
5090
|
+
process.exit(1);
|
|
5048
5091
|
}
|
|
5049
5092
|
args = [...forwarded, ...args];
|
|
5050
5093
|
await run(url, args, overrideEnv, { verbatim: separator !== -1 });
|