chrome-tools 1.0.3 → 1.0.5
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 +24 -23
- package/bin/cli.js +82 -45
- package/package.json +1 -1
- package/src/core/chrome.js +4 -3
package/README.md
CHANGED
|
@@ -80,8 +80,8 @@ npx chrome-tools passwords
|
|
|
80
80
|
# Filter credentials using a search term (matches URL or username)
|
|
81
81
|
npx chrome-tools passwords --search "gmail"
|
|
82
82
|
|
|
83
|
-
# Target a specific profile directory only
|
|
84
|
-
npx chrome-tools
|
|
83
|
+
# Target a specific profile directory only (placed before the subcommand)
|
|
84
|
+
npx chrome-tools --profile "Profile 1" passwords
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
#### Bookmarks
|
|
@@ -149,20 +149,20 @@ npx chrome-tools top-sites
|
|
|
149
149
|
|
|
150
150
|
### Global Options
|
|
151
151
|
|
|
152
|
-
These options apply globally to all subcommands and
|
|
152
|
+
These options apply globally to all subcommands and should be placed before the command (e.g. `npx chrome-tools --profile-path <path> --profile <name> cookies --url <url>`):
|
|
153
153
|
|
|
154
|
-
- `--
|
|
155
|
-
- `--profile <name>`:
|
|
154
|
+
- `--profile-path <path>`: Specify a custom Chrome User Data/profile folder (e.g., a backed-up profile from another machine). Defaults to the `PROFILE_PATH` env/`.env` variable, or falls back to the standard macOS Chrome User Data location.
|
|
155
|
+
- `--profile <name>`: Target a specific profile directory (e.g., `Default`, `Profile 1`). Defaults to the `PROFILE_NAME` env/`.env` variable.
|
|
156
156
|
- `--json`: Output strictly in JSON format (ideal for programmatic pipes or exporting to files).
|
|
157
157
|
- `--limit <number>`: Restrict the output results count (for history, autofill, cookies, etc.).
|
|
158
158
|
|
|
159
159
|
#### Custom Directory & JSON Examples
|
|
160
160
|
```bash
|
|
161
161
|
# Export bookmarks from a backed-up Chrome folder directly to a JSON file
|
|
162
|
-
npx chrome-tools
|
|
162
|
+
npx chrome-tools --profile-path "/path/to/backup/Chrome" bookmarks --json > bookmarks.json
|
|
163
163
|
|
|
164
164
|
# Retrieve all history from a specific profile in JSON format
|
|
165
|
-
npx chrome-tools
|
|
165
|
+
npx chrome-tools --profile-path "/path/to/backup/Chrome" --profile "Profile 2" history --json --limit 10
|
|
166
166
|
```
|
|
167
167
|
|
|
168
168
|
---
|
|
@@ -187,7 +187,7 @@ console.log(profiles);
|
|
|
187
187
|
|
|
188
188
|
// 2. Fetch bookmarks programmatically
|
|
189
189
|
const githubBookmarks = getBookmarks({
|
|
190
|
-
|
|
190
|
+
profilePath: "/path/to/chrome/User Data",
|
|
191
191
|
search: "github"
|
|
192
192
|
});
|
|
193
193
|
|
|
@@ -214,27 +214,28 @@ for (const cred of credentials) {
|
|
|
214
214
|
### Available API Modules & Signatures
|
|
215
215
|
|
|
216
216
|
All core functions accept an options object with the following fields:
|
|
217
|
-
- `
|
|
217
|
+
- `profilePath` *(string)*: Custom Chrome User Data/profile directory (alias: `chromeDir`).
|
|
218
|
+
- `chromeDir` *(string)*: Alias for `profilePath`.
|
|
218
219
|
- `profile` *(string)*: Specific profile subdirectory name (e.g., `"Default"`).
|
|
219
220
|
- `search` *(string)*: Case-insensitive filter term.
|
|
220
221
|
- `limit` *(number)*: Maximum returned rows count.
|
|
221
222
|
|
|
222
223
|
| Function | Module Path | Returns |
|
|
223
224
|
| --- | --- | --- |
|
|
224
|
-
| `discoverProfiles(
|
|
225
|
-
| `getProfileStates(
|
|
226
|
-
| `getPasswords({chromeDir, profile, search})` | `chrome-tools/passwords` | `Array<Credentials>` |
|
|
227
|
-
| `getBookmarks({chromeDir, profile, folder, search})` | `chrome-tools/bookmarks` | `Array<Bookmark>` |
|
|
228
|
-
| `getHistory({chromeDir, profile, search, limit})` | `chrome-tools/history` | `Array<HistoryEntry>` |
|
|
229
|
-
| `getSearchTerms({chromeDir, profile, limit})` | `chrome-tools/history` | `Array<SearchTerm>` |
|
|
230
|
-
| `getCookies({chromeDir, profile, domain, url, decrypt, limit})` | `chrome-tools/cookies` | `Array<Cookie>` |
|
|
231
|
-
| `getAutofillEntries({chromeDir, profile, search, limit})` | `chrome-tools/autofill` | `Array<AutofillEntry>` |
|
|
232
|
-
| `getCreditCards({chromeDir, profile})` | `chrome-tools/autofill` | `Array<CreditCard>` |
|
|
233
|
-
| `getAddresses({chromeDir, profile})` | `chrome-tools/autofill` | `Array<Address>` |
|
|
234
|
-
| `getDownloads({chromeDir, profile, search, limit})` | `chrome-tools/downloads` | `Array<Download>` |
|
|
235
|
-
| `getExtensions({chromeDir, profile, search})` | `chrome-tools/extensions` | `Array<Extension>` |
|
|
236
|
-
| `getSearchEngines({chromeDir, profile})` | `chrome-tools/search-engines` | `Array<SearchEngine>` |
|
|
237
|
-
| `getTopSites({chromeDir, profile})` | `chrome-tools/top-sites` | `Array<TopSite>` |
|
|
225
|
+
| `discoverProfiles(profilePath)` | `chrome-tools` | `Array<{name, path}>` |
|
|
226
|
+
| `getProfileStates(profilePath)` | `chrome-tools` | `Array<ProfileState>` |
|
|
227
|
+
| `getPasswords({profilePath, chromeDir, profile, search})` | `chrome-tools/passwords` | `Array<Credentials>` |
|
|
228
|
+
| `getBookmarks({profilePath, chromeDir, profile, folder, search})` | `chrome-tools/bookmarks` | `Array<Bookmark>` |
|
|
229
|
+
| `getHistory({profilePath, chromeDir, profile, search, limit})` | `chrome-tools/history` | `Array<HistoryEntry>` |
|
|
230
|
+
| `getSearchTerms({profilePath, chromeDir, profile, limit})` | `chrome-tools/history` | `Array<SearchTerm>` |
|
|
231
|
+
| `getCookies({profilePath, chromeDir, profile, domain, url, decrypt, limit})` | `chrome-tools/cookies` | `Array<Cookie>` |
|
|
232
|
+
| `getAutofillEntries({profilePath, chromeDir, profile, search, limit})` | `chrome-tools/autofill` | `Array<AutofillEntry>` |
|
|
233
|
+
| `getCreditCards({profilePath, chromeDir, profile})` | `chrome-tools/autofill` | `Array<CreditCard>` |
|
|
234
|
+
| `getAddresses({profilePath, chromeDir, profile})` | `chrome-tools/autofill` | `Array<Address>` |
|
|
235
|
+
| `getDownloads({profilePath, chromeDir, profile, search, limit})` | `chrome-tools/downloads` | `Array<Download>` |
|
|
236
|
+
| `getExtensions({profilePath, chromeDir, profile, search})` | `chrome-tools/extensions` | `Array<Extension>` |
|
|
237
|
+
| `getSearchEngines({profilePath, chromeDir, profile})` | `chrome-tools/search-engines` | `Array<SearchEngine>` |
|
|
238
|
+
| `getTopSites({profilePath, chromeDir, profile})` | `chrome-tools/top-sites` | `Array<TopSite>` |
|
|
238
239
|
|
|
239
240
|
---
|
|
240
241
|
|
package/bin/cli.js
CHANGED
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
* Supports subcommands and shortcut flags for quick access to all data types.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
10
12
|
import { Command } from "commander";
|
|
11
13
|
import chalk from "chalk";
|
|
12
14
|
import Table from "cli-table3";
|
|
13
15
|
|
|
14
|
-
import { discoverProfiles, getProfileMetadata, getProfileStates } from "../src/core/chrome.js";
|
|
16
|
+
import { discoverProfiles, getProfileMetadata, getProfileStates, getDefaultChromeDir } from "../src/core/chrome.js";
|
|
15
17
|
import { getPasswords } from "../src/modules/passwords.js";
|
|
16
18
|
import { getBookmarks } from "../src/modules/bookmarks.js";
|
|
17
19
|
import { getHistory, getSearchTerms } from "../src/modules/history.js";
|
|
@@ -22,6 +24,39 @@ import { getExtensions } from "../src/modules/extensions.js";
|
|
|
22
24
|
import { getSearchEngines } from "../src/modules/search-engines.js";
|
|
23
25
|
import { getTopSites } from "../src/modules/top-sites.js";
|
|
24
26
|
|
|
27
|
+
// ─── Environment Loading ─────────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
function loadEnv() {
|
|
30
|
+
const env = { ...process.env };
|
|
31
|
+
const envPath = join(process.cwd(), ".env");
|
|
32
|
+
if (existsSync(envPath)) {
|
|
33
|
+
try {
|
|
34
|
+
const content = readFileSync(envPath, "utf8");
|
|
35
|
+
for (const line of content.split(/\r?\n/)) {
|
|
36
|
+
const trimmed = line.trim();
|
|
37
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
38
|
+
const index = trimmed.indexOf("=");
|
|
39
|
+
if (index !== -1) {
|
|
40
|
+
const key = trimmed.substring(0, index).trim();
|
|
41
|
+
let val = trimmed.substring(index + 1).trim();
|
|
42
|
+
// Remove wrapping quotes
|
|
43
|
+
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
|
|
44
|
+
val = val.slice(1, -1);
|
|
45
|
+
}
|
|
46
|
+
env[key] = val;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
// Ignore
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return env;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const env = loadEnv();
|
|
57
|
+
const defaultProfilePath = env.PROFILE_PATH || getDefaultChromeDir();
|
|
58
|
+
const defaultProfileName = env.PROFILE_NAME || undefined;
|
|
59
|
+
|
|
25
60
|
// ─── Output Helpers ──────────────────────────────────────────────────────────
|
|
26
61
|
|
|
27
62
|
function outputJSON(data) {
|
|
@@ -49,8 +84,8 @@ function printCount(label, count) {
|
|
|
49
84
|
|
|
50
85
|
function addCommonOptions(cmd) {
|
|
51
86
|
return cmd
|
|
52
|
-
.option("--
|
|
53
|
-
.option("--profile <name>", "Target a specific profile")
|
|
87
|
+
.option("--profile-path <path>", "Custom Chrome Profile Path", defaultProfilePath)
|
|
88
|
+
.option("--profile <name>", "Target a specific profile", defaultProfileName)
|
|
54
89
|
.option("--json", "Output as JSON");
|
|
55
90
|
}
|
|
56
91
|
|
|
@@ -66,35 +101,23 @@ function addLimitOption(cmd, defaultLimit = 100) {
|
|
|
66
101
|
|
|
67
102
|
const program = new Command();
|
|
68
103
|
|
|
104
|
+
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
105
|
+
|
|
69
106
|
program
|
|
70
107
|
.name("chrome-tools")
|
|
71
108
|
.description(
|
|
72
109
|
chalk.bold.cyan("Chrome Data Toolkit") +
|
|
73
110
|
chalk.dim(" — Extract passwords, bookmarks, history, cookies, and more from Chrome on macOS")
|
|
74
111
|
)
|
|
75
|
-
.version(
|
|
112
|
+
.version(pkg.version)
|
|
76
113
|
.option("--passwords", "Shortcut: list saved passwords")
|
|
77
114
|
.option("--bookmarks", "Shortcut: list bookmarks")
|
|
78
115
|
.option("--profiles", "Shortcut: list profiles")
|
|
79
|
-
.option("--
|
|
80
|
-
.option("--profile <name>", "Target a specific profile")
|
|
116
|
+
.option("--profile-path <path>", "Custom Chrome Profile Path", defaultProfilePath)
|
|
117
|
+
.option("--profile <name>", "Target a specific profile", defaultProfileName)
|
|
81
118
|
.option("--json", "Output as JSON")
|
|
82
119
|
.option("--search <term>", "Filter results (for shortcut flags)")
|
|
83
|
-
.option("--limit <n>", "Limit results (for shortcut flags)")
|
|
84
|
-
.action((opts) => {
|
|
85
|
-
// Handle shortcut flags at the top level
|
|
86
|
-
if (opts.passwords) {
|
|
87
|
-
return handlePasswords(opts);
|
|
88
|
-
}
|
|
89
|
-
if (opts.bookmarks) {
|
|
90
|
-
return handleBookmarks(opts);
|
|
91
|
-
}
|
|
92
|
-
if (opts.profiles) {
|
|
93
|
-
return handleProfiles(opts);
|
|
94
|
-
}
|
|
95
|
-
// No shortcut flag — show help
|
|
96
|
-
program.help();
|
|
97
|
-
});
|
|
120
|
+
.option("--limit <n>", "Limit results (for shortcut flags)");
|
|
98
121
|
|
|
99
122
|
// ─── Profiles Command ───────────────────────────────────────────────────────
|
|
100
123
|
|
|
@@ -109,13 +132,13 @@ addCommonOptions(profilesCmd).action((opts, cmd) => {
|
|
|
109
132
|
profilesCmd
|
|
110
133
|
.command("states")
|
|
111
134
|
.description("Show detailed profile states with available data files")
|
|
112
|
-
.option("--
|
|
135
|
+
.option("--profile-path <path>", "Custom Chrome Profile Path", defaultProfilePath)
|
|
113
136
|
.option("--json", "Output as JSON")
|
|
114
137
|
.action((opts, cmd) => handleProfileStates(cmd.optsWithGlobals()));
|
|
115
138
|
|
|
116
139
|
function handleProfiles(opts) {
|
|
117
|
-
const profiles = discoverProfiles(opts.
|
|
118
|
-
const metadata = getProfileMetadata(opts.
|
|
140
|
+
const profiles = discoverProfiles(opts.profilePath);
|
|
141
|
+
const metadata = getProfileMetadata(opts.profilePath);
|
|
119
142
|
|
|
120
143
|
if (opts.json) {
|
|
121
144
|
const metaMap = new Map(metadata.map((m) => [m.directory, m]));
|
|
@@ -151,7 +174,7 @@ function handleProfiles(opts) {
|
|
|
151
174
|
}
|
|
152
175
|
|
|
153
176
|
function handleProfileStates(opts) {
|
|
154
|
-
const states = getProfileStates(opts.
|
|
177
|
+
const states = getProfileStates(opts.profilePath);
|
|
155
178
|
|
|
156
179
|
if (opts.json) {
|
|
157
180
|
return outputJSON(states);
|
|
@@ -190,11 +213,11 @@ function handleProfileStates(opts) {
|
|
|
190
213
|
// ─── Passwords Command ──────────────────────────────────────────────────────
|
|
191
214
|
|
|
192
215
|
const passwordsCmd = program.command("passwords").description("List saved passwords");
|
|
193
|
-
addCommonOptions(
|
|
216
|
+
addSearchOption(addCommonOptions(passwordsCmd)).action((opts, cmd) => handlePasswords(cmd.optsWithGlobals()));
|
|
194
217
|
|
|
195
218
|
function handlePasswords(opts) {
|
|
196
219
|
const results = getPasswords({
|
|
197
|
-
chromeDir: opts.
|
|
220
|
+
chromeDir: opts.profilePath,
|
|
198
221
|
profile: opts.profile,
|
|
199
222
|
search: opts.search,
|
|
200
223
|
});
|
|
@@ -230,13 +253,13 @@ function handlePasswords(opts) {
|
|
|
230
253
|
// ─── Bookmarks Command ──────────────────────────────────────────────────────
|
|
231
254
|
|
|
232
255
|
const bookmarksCmd = program.command("bookmarks").description("List bookmarks");
|
|
233
|
-
addCommonOptions(
|
|
256
|
+
addSearchOption(addCommonOptions(bookmarksCmd))
|
|
234
257
|
.option("--folder <name>", "Filter by folder name")
|
|
235
258
|
.action((opts, cmd) => handleBookmarks(cmd.optsWithGlobals()));
|
|
236
259
|
|
|
237
260
|
function handleBookmarks(opts) {
|
|
238
261
|
const results = getBookmarks({
|
|
239
|
-
chromeDir: opts.
|
|
262
|
+
chromeDir: opts.profilePath,
|
|
240
263
|
profile: opts.profile,
|
|
241
264
|
folder: opts.folder,
|
|
242
265
|
search: opts.search,
|
|
@@ -265,10 +288,10 @@ function handleBookmarks(opts) {
|
|
|
265
288
|
// ─── History Command ─────────────────────────────────────────────────────────
|
|
266
289
|
|
|
267
290
|
const historyCmd = program.command("history").description("List browsing history");
|
|
268
|
-
|
|
291
|
+
addSearchOption(addLimitOption(addCommonOptions(historyCmd))).action((opts, cmd) => {
|
|
269
292
|
const mergedOpts = cmd.optsWithGlobals();
|
|
270
293
|
const results = getHistory({
|
|
271
|
-
chromeDir: mergedOpts.
|
|
294
|
+
chromeDir: mergedOpts.profilePath,
|
|
272
295
|
profile: mergedOpts.profile,
|
|
273
296
|
search: mergedOpts.search,
|
|
274
297
|
limit: parseInt(mergedOpts.limit, 10) || 100,
|
|
@@ -297,10 +320,10 @@ addCommonOptions(addSearchOption(addLimitOption(historyCmd))).action((opts, cmd)
|
|
|
297
320
|
// ─── Search Terms Command ────────────────────────────────────────────────────
|
|
298
321
|
|
|
299
322
|
const searchTermsCmd = program.command("search-terms").description("List search terms from history");
|
|
300
|
-
addCommonOptions(
|
|
323
|
+
addLimitOption(addCommonOptions(searchTermsCmd)).action((opts, cmd) => {
|
|
301
324
|
const mergedOpts = cmd.optsWithGlobals();
|
|
302
325
|
const results = getSearchTerms({
|
|
303
|
-
chromeDir: mergedOpts.
|
|
326
|
+
chromeDir: mergedOpts.profilePath,
|
|
304
327
|
profile: mergedOpts.profile,
|
|
305
328
|
limit: parseInt(mergedOpts.limit, 10) || 100,
|
|
306
329
|
});
|
|
@@ -323,14 +346,14 @@ addCommonOptions(addLimitOption(searchTermsCmd)).action((opts, cmd) => {
|
|
|
323
346
|
// ─── Cookies Command ─────────────────────────────────────────────────────────
|
|
324
347
|
|
|
325
348
|
const cookiesCmd = program.command("cookies").description("List cookies (encrypted values decrypted)");
|
|
326
|
-
addCommonOptions(
|
|
349
|
+
addLimitOption(addCommonOptions(cookiesCmd))
|
|
327
350
|
.option("--domain <domain>", "Filter by domain")
|
|
328
351
|
.option("--url <url>", "Filter by URL with path")
|
|
329
352
|
.option("--no-decrypt", "Skip decryption of encrypted values")
|
|
330
353
|
.action((opts, cmd) => {
|
|
331
354
|
const mergedOpts = cmd.optsWithGlobals();
|
|
332
355
|
const results = getCookies({
|
|
333
|
-
chromeDir: mergedOpts.
|
|
356
|
+
chromeDir: mergedOpts.profilePath,
|
|
334
357
|
profile: mergedOpts.profile,
|
|
335
358
|
domain: mergedOpts.domain,
|
|
336
359
|
url: mergedOpts.url,
|
|
@@ -362,10 +385,10 @@ addCommonOptions(addLimitOption(cookiesCmd))
|
|
|
362
385
|
// ─── Autofill Command ────────────────────────────────────────────────────────
|
|
363
386
|
|
|
364
387
|
const autofillCmd = program.command("autofill").description("List autofill entries");
|
|
365
|
-
|
|
388
|
+
addSearchOption(addLimitOption(addCommonOptions(autofillCmd))).action((opts, cmd) => {
|
|
366
389
|
const mergedOpts = cmd.optsWithGlobals();
|
|
367
390
|
const results = getAutofillEntries({
|
|
368
|
-
chromeDir: mergedOpts.
|
|
391
|
+
chromeDir: mergedOpts.profilePath,
|
|
369
392
|
profile: mergedOpts.profile,
|
|
370
393
|
search: mergedOpts.search,
|
|
371
394
|
limit: parseInt(mergedOpts.limit, 10) || 100,
|
|
@@ -397,7 +420,7 @@ const creditCardsCmd = program.command("credit-cards").description("List saved c
|
|
|
397
420
|
addCommonOptions(creditCardsCmd).action((opts, cmd) => {
|
|
398
421
|
const mergedOpts = cmd.optsWithGlobals();
|
|
399
422
|
const results = getCreditCards({
|
|
400
|
-
chromeDir: mergedOpts.
|
|
423
|
+
chromeDir: mergedOpts.profilePath,
|
|
401
424
|
profile: mergedOpts.profile,
|
|
402
425
|
});
|
|
403
426
|
|
|
@@ -427,7 +450,7 @@ const addressesCmd = program.command("addresses").description("List saved addres
|
|
|
427
450
|
addCommonOptions(addressesCmd).action((opts, cmd) => {
|
|
428
451
|
const mergedOpts = cmd.optsWithGlobals();
|
|
429
452
|
const results = getAddresses({
|
|
430
|
-
chromeDir: mergedOpts.
|
|
453
|
+
chromeDir: mergedOpts.profilePath,
|
|
431
454
|
profile: mergedOpts.profile,
|
|
432
455
|
});
|
|
433
456
|
|
|
@@ -455,10 +478,10 @@ addCommonOptions(addressesCmd).action((opts, cmd) => {
|
|
|
455
478
|
// ─── Downloads Command ───────────────────────────────────────────────────────
|
|
456
479
|
|
|
457
480
|
const downloadsCmd = program.command("downloads").description("List download history");
|
|
458
|
-
|
|
481
|
+
addSearchOption(addLimitOption(addCommonOptions(downloadsCmd))).action((opts, cmd) => {
|
|
459
482
|
const mergedOpts = cmd.optsWithGlobals();
|
|
460
483
|
const results = getDownloads({
|
|
461
|
-
chromeDir: mergedOpts.
|
|
484
|
+
chromeDir: mergedOpts.profilePath,
|
|
462
485
|
profile: mergedOpts.profile,
|
|
463
486
|
search: mergedOpts.search,
|
|
464
487
|
limit: parseInt(mergedOpts.limit, 10) || 100,
|
|
@@ -490,10 +513,10 @@ addCommonOptions(addSearchOption(addLimitOption(downloadsCmd))).action((opts, cm
|
|
|
490
513
|
// ─── Extensions Command ─────────────────────────────────────────────────────
|
|
491
514
|
|
|
492
515
|
const extensionsCmd = program.command("extensions").description("List installed extensions");
|
|
493
|
-
addCommonOptions(
|
|
516
|
+
addSearchOption(addCommonOptions(extensionsCmd)).action((opts, cmd) => {
|
|
494
517
|
const mergedOpts = cmd.optsWithGlobals();
|
|
495
518
|
const results = getExtensions({
|
|
496
|
-
chromeDir: mergedOpts.
|
|
519
|
+
chromeDir: mergedOpts.profilePath,
|
|
497
520
|
profile: mergedOpts.profile,
|
|
498
521
|
search: mergedOpts.search,
|
|
499
522
|
});
|
|
@@ -525,7 +548,7 @@ const searchEnginesCmd = program.command("search-engines").description("List con
|
|
|
525
548
|
addCommonOptions(searchEnginesCmd).action((opts, cmd) => {
|
|
526
549
|
const mergedOpts = cmd.optsWithGlobals();
|
|
527
550
|
const results = getSearchEngines({
|
|
528
|
-
chromeDir: mergedOpts.
|
|
551
|
+
chromeDir: mergedOpts.profilePath,
|
|
529
552
|
profile: mergedOpts.profile,
|
|
530
553
|
});
|
|
531
554
|
|
|
@@ -555,7 +578,7 @@ const topSitesCmd = program.command("top-sites").description("List top sites");
|
|
|
555
578
|
addCommonOptions(topSitesCmd).action((opts, cmd) => {
|
|
556
579
|
const mergedOpts = cmd.optsWithGlobals();
|
|
557
580
|
const results = getTopSites({
|
|
558
|
-
chromeDir: mergedOpts.
|
|
581
|
+
chromeDir: mergedOpts.profilePath,
|
|
559
582
|
profile: mergedOpts.profile,
|
|
560
583
|
});
|
|
561
584
|
|
|
@@ -590,3 +613,17 @@ function formatBytes(bytes) {
|
|
|
590
613
|
// ─── Run ─────────────────────────────────────────────────────────────────────
|
|
591
614
|
|
|
592
615
|
program.parse();
|
|
616
|
+
|
|
617
|
+
const rootOpts = program.opts();
|
|
618
|
+
const hasSubcommand = program.args.length > 0;
|
|
619
|
+
if (!hasSubcommand) {
|
|
620
|
+
if (rootOpts.passwords) {
|
|
621
|
+
handlePasswords(rootOpts);
|
|
622
|
+
} else if (rootOpts.bookmarks) {
|
|
623
|
+
handleBookmarks(rootOpts);
|
|
624
|
+
} else if (rootOpts.profiles) {
|
|
625
|
+
handleProfiles(rootOpts);
|
|
626
|
+
} else {
|
|
627
|
+
program.help();
|
|
628
|
+
}
|
|
629
|
+
}
|
package/package.json
CHANGED
package/src/core/chrome.js
CHANGED
|
@@ -158,12 +158,13 @@ export function resolveProfilePath(chromeDir, profileName) {
|
|
|
158
158
|
* Otherwise returns all discovered profiles.
|
|
159
159
|
*
|
|
160
160
|
* @param {Object} options
|
|
161
|
-
* @param {string} [options.
|
|
161
|
+
* @param {string} [options.profilePath] - Custom Chrome User Data/profile directory.
|
|
162
|
+
* @param {string} [options.chromeDir] - Chrome User Data path (alias for profilePath).
|
|
162
163
|
* @param {string} [options.profile] - Specific profile name to target.
|
|
163
164
|
* @returns {Array<{name: string, path: string}>}
|
|
164
165
|
*/
|
|
165
|
-
export function resolveTargetProfiles({ chromeDir, profile } = {}) {
|
|
166
|
-
const dir = chromeDir || getDefaultChromeDir();
|
|
166
|
+
export function resolveTargetProfiles({ profilePath, chromeDir, profile } = {}) {
|
|
167
|
+
const dir = profilePath || chromeDir || getDefaultChromeDir();
|
|
167
168
|
const allProfiles = discoverProfiles(dir);
|
|
168
169
|
|
|
169
170
|
if (profile) {
|