chrome-tools 1.0.4 → 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 +79 -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,12 +7,13 @@
|
|
|
7
7
|
* Supports subcommands and shortcut flags for quick access to all data types.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { readFileSync } from "node:fs";
|
|
10
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
11
12
|
import { Command } from "commander";
|
|
12
13
|
import chalk from "chalk";
|
|
13
14
|
import Table from "cli-table3";
|
|
14
15
|
|
|
15
|
-
import { discoverProfiles, getProfileMetadata, getProfileStates } from "../src/core/chrome.js";
|
|
16
|
+
import { discoverProfiles, getProfileMetadata, getProfileStates, getDefaultChromeDir } from "../src/core/chrome.js";
|
|
16
17
|
import { getPasswords } from "../src/modules/passwords.js";
|
|
17
18
|
import { getBookmarks } from "../src/modules/bookmarks.js";
|
|
18
19
|
import { getHistory, getSearchTerms } from "../src/modules/history.js";
|
|
@@ -23,6 +24,39 @@ import { getExtensions } from "../src/modules/extensions.js";
|
|
|
23
24
|
import { getSearchEngines } from "../src/modules/search-engines.js";
|
|
24
25
|
import { getTopSites } from "../src/modules/top-sites.js";
|
|
25
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
|
+
|
|
26
60
|
// ─── Output Helpers ──────────────────────────────────────────────────────────
|
|
27
61
|
|
|
28
62
|
function outputJSON(data) {
|
|
@@ -50,8 +84,8 @@ function printCount(label, count) {
|
|
|
50
84
|
|
|
51
85
|
function addCommonOptions(cmd) {
|
|
52
86
|
return cmd
|
|
53
|
-
.option("--
|
|
54
|
-
.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)
|
|
55
89
|
.option("--json", "Output as JSON");
|
|
56
90
|
}
|
|
57
91
|
|
|
@@ -79,25 +113,11 @@ program
|
|
|
79
113
|
.option("--passwords", "Shortcut: list saved passwords")
|
|
80
114
|
.option("--bookmarks", "Shortcut: list bookmarks")
|
|
81
115
|
.option("--profiles", "Shortcut: list profiles")
|
|
82
|
-
.option("--
|
|
83
|
-
.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)
|
|
84
118
|
.option("--json", "Output as JSON")
|
|
85
119
|
.option("--search <term>", "Filter results (for shortcut flags)")
|
|
86
|
-
.option("--limit <n>", "Limit results (for shortcut flags)")
|
|
87
|
-
.action((opts) => {
|
|
88
|
-
// Handle shortcut flags at the top level
|
|
89
|
-
if (opts.passwords) {
|
|
90
|
-
return handlePasswords(opts);
|
|
91
|
-
}
|
|
92
|
-
if (opts.bookmarks) {
|
|
93
|
-
return handleBookmarks(opts);
|
|
94
|
-
}
|
|
95
|
-
if (opts.profiles) {
|
|
96
|
-
return handleProfiles(opts);
|
|
97
|
-
}
|
|
98
|
-
// No shortcut flag — show help
|
|
99
|
-
program.help();
|
|
100
|
-
});
|
|
120
|
+
.option("--limit <n>", "Limit results (for shortcut flags)");
|
|
101
121
|
|
|
102
122
|
// ─── Profiles Command ───────────────────────────────────────────────────────
|
|
103
123
|
|
|
@@ -112,13 +132,13 @@ addCommonOptions(profilesCmd).action((opts, cmd) => {
|
|
|
112
132
|
profilesCmd
|
|
113
133
|
.command("states")
|
|
114
134
|
.description("Show detailed profile states with available data files")
|
|
115
|
-
.option("--
|
|
135
|
+
.option("--profile-path <path>", "Custom Chrome Profile Path", defaultProfilePath)
|
|
116
136
|
.option("--json", "Output as JSON")
|
|
117
137
|
.action((opts, cmd) => handleProfileStates(cmd.optsWithGlobals()));
|
|
118
138
|
|
|
119
139
|
function handleProfiles(opts) {
|
|
120
|
-
const profiles = discoverProfiles(opts.
|
|
121
|
-
const metadata = getProfileMetadata(opts.
|
|
140
|
+
const profiles = discoverProfiles(opts.profilePath);
|
|
141
|
+
const metadata = getProfileMetadata(opts.profilePath);
|
|
122
142
|
|
|
123
143
|
if (opts.json) {
|
|
124
144
|
const metaMap = new Map(metadata.map((m) => [m.directory, m]));
|
|
@@ -154,7 +174,7 @@ function handleProfiles(opts) {
|
|
|
154
174
|
}
|
|
155
175
|
|
|
156
176
|
function handleProfileStates(opts) {
|
|
157
|
-
const states = getProfileStates(opts.
|
|
177
|
+
const states = getProfileStates(opts.profilePath);
|
|
158
178
|
|
|
159
179
|
if (opts.json) {
|
|
160
180
|
return outputJSON(states);
|
|
@@ -193,11 +213,11 @@ function handleProfileStates(opts) {
|
|
|
193
213
|
// ─── Passwords Command ──────────────────────────────────────────────────────
|
|
194
214
|
|
|
195
215
|
const passwordsCmd = program.command("passwords").description("List saved passwords");
|
|
196
|
-
addCommonOptions(
|
|
216
|
+
addSearchOption(addCommonOptions(passwordsCmd)).action((opts, cmd) => handlePasswords(cmd.optsWithGlobals()));
|
|
197
217
|
|
|
198
218
|
function handlePasswords(opts) {
|
|
199
219
|
const results = getPasswords({
|
|
200
|
-
chromeDir: opts.
|
|
220
|
+
chromeDir: opts.profilePath,
|
|
201
221
|
profile: opts.profile,
|
|
202
222
|
search: opts.search,
|
|
203
223
|
});
|
|
@@ -233,13 +253,13 @@ function handlePasswords(opts) {
|
|
|
233
253
|
// ─── Bookmarks Command ──────────────────────────────────────────────────────
|
|
234
254
|
|
|
235
255
|
const bookmarksCmd = program.command("bookmarks").description("List bookmarks");
|
|
236
|
-
addCommonOptions(
|
|
256
|
+
addSearchOption(addCommonOptions(bookmarksCmd))
|
|
237
257
|
.option("--folder <name>", "Filter by folder name")
|
|
238
258
|
.action((opts, cmd) => handleBookmarks(cmd.optsWithGlobals()));
|
|
239
259
|
|
|
240
260
|
function handleBookmarks(opts) {
|
|
241
261
|
const results = getBookmarks({
|
|
242
|
-
chromeDir: opts.
|
|
262
|
+
chromeDir: opts.profilePath,
|
|
243
263
|
profile: opts.profile,
|
|
244
264
|
folder: opts.folder,
|
|
245
265
|
search: opts.search,
|
|
@@ -268,10 +288,10 @@ function handleBookmarks(opts) {
|
|
|
268
288
|
// ─── History Command ─────────────────────────────────────────────────────────
|
|
269
289
|
|
|
270
290
|
const historyCmd = program.command("history").description("List browsing history");
|
|
271
|
-
|
|
291
|
+
addSearchOption(addLimitOption(addCommonOptions(historyCmd))).action((opts, cmd) => {
|
|
272
292
|
const mergedOpts = cmd.optsWithGlobals();
|
|
273
293
|
const results = getHistory({
|
|
274
|
-
chromeDir: mergedOpts.
|
|
294
|
+
chromeDir: mergedOpts.profilePath,
|
|
275
295
|
profile: mergedOpts.profile,
|
|
276
296
|
search: mergedOpts.search,
|
|
277
297
|
limit: parseInt(mergedOpts.limit, 10) || 100,
|
|
@@ -300,10 +320,10 @@ addCommonOptions(addSearchOption(addLimitOption(historyCmd))).action((opts, cmd)
|
|
|
300
320
|
// ─── Search Terms Command ────────────────────────────────────────────────────
|
|
301
321
|
|
|
302
322
|
const searchTermsCmd = program.command("search-terms").description("List search terms from history");
|
|
303
|
-
addCommonOptions(
|
|
323
|
+
addLimitOption(addCommonOptions(searchTermsCmd)).action((opts, cmd) => {
|
|
304
324
|
const mergedOpts = cmd.optsWithGlobals();
|
|
305
325
|
const results = getSearchTerms({
|
|
306
|
-
chromeDir: mergedOpts.
|
|
326
|
+
chromeDir: mergedOpts.profilePath,
|
|
307
327
|
profile: mergedOpts.profile,
|
|
308
328
|
limit: parseInt(mergedOpts.limit, 10) || 100,
|
|
309
329
|
});
|
|
@@ -326,14 +346,14 @@ addCommonOptions(addLimitOption(searchTermsCmd)).action((opts, cmd) => {
|
|
|
326
346
|
// ─── Cookies Command ─────────────────────────────────────────────────────────
|
|
327
347
|
|
|
328
348
|
const cookiesCmd = program.command("cookies").description("List cookies (encrypted values decrypted)");
|
|
329
|
-
addCommonOptions(
|
|
349
|
+
addLimitOption(addCommonOptions(cookiesCmd))
|
|
330
350
|
.option("--domain <domain>", "Filter by domain")
|
|
331
351
|
.option("--url <url>", "Filter by URL with path")
|
|
332
352
|
.option("--no-decrypt", "Skip decryption of encrypted values")
|
|
333
353
|
.action((opts, cmd) => {
|
|
334
354
|
const mergedOpts = cmd.optsWithGlobals();
|
|
335
355
|
const results = getCookies({
|
|
336
|
-
chromeDir: mergedOpts.
|
|
356
|
+
chromeDir: mergedOpts.profilePath,
|
|
337
357
|
profile: mergedOpts.profile,
|
|
338
358
|
domain: mergedOpts.domain,
|
|
339
359
|
url: mergedOpts.url,
|
|
@@ -365,10 +385,10 @@ addCommonOptions(addLimitOption(cookiesCmd))
|
|
|
365
385
|
// ─── Autofill Command ────────────────────────────────────────────────────────
|
|
366
386
|
|
|
367
387
|
const autofillCmd = program.command("autofill").description("List autofill entries");
|
|
368
|
-
|
|
388
|
+
addSearchOption(addLimitOption(addCommonOptions(autofillCmd))).action((opts, cmd) => {
|
|
369
389
|
const mergedOpts = cmd.optsWithGlobals();
|
|
370
390
|
const results = getAutofillEntries({
|
|
371
|
-
chromeDir: mergedOpts.
|
|
391
|
+
chromeDir: mergedOpts.profilePath,
|
|
372
392
|
profile: mergedOpts.profile,
|
|
373
393
|
search: mergedOpts.search,
|
|
374
394
|
limit: parseInt(mergedOpts.limit, 10) || 100,
|
|
@@ -400,7 +420,7 @@ const creditCardsCmd = program.command("credit-cards").description("List saved c
|
|
|
400
420
|
addCommonOptions(creditCardsCmd).action((opts, cmd) => {
|
|
401
421
|
const mergedOpts = cmd.optsWithGlobals();
|
|
402
422
|
const results = getCreditCards({
|
|
403
|
-
chromeDir: mergedOpts.
|
|
423
|
+
chromeDir: mergedOpts.profilePath,
|
|
404
424
|
profile: mergedOpts.profile,
|
|
405
425
|
});
|
|
406
426
|
|
|
@@ -430,7 +450,7 @@ const addressesCmd = program.command("addresses").description("List saved addres
|
|
|
430
450
|
addCommonOptions(addressesCmd).action((opts, cmd) => {
|
|
431
451
|
const mergedOpts = cmd.optsWithGlobals();
|
|
432
452
|
const results = getAddresses({
|
|
433
|
-
chromeDir: mergedOpts.
|
|
453
|
+
chromeDir: mergedOpts.profilePath,
|
|
434
454
|
profile: mergedOpts.profile,
|
|
435
455
|
});
|
|
436
456
|
|
|
@@ -458,10 +478,10 @@ addCommonOptions(addressesCmd).action((opts, cmd) => {
|
|
|
458
478
|
// ─── Downloads Command ───────────────────────────────────────────────────────
|
|
459
479
|
|
|
460
480
|
const downloadsCmd = program.command("downloads").description("List download history");
|
|
461
|
-
|
|
481
|
+
addSearchOption(addLimitOption(addCommonOptions(downloadsCmd))).action((opts, cmd) => {
|
|
462
482
|
const mergedOpts = cmd.optsWithGlobals();
|
|
463
483
|
const results = getDownloads({
|
|
464
|
-
chromeDir: mergedOpts.
|
|
484
|
+
chromeDir: mergedOpts.profilePath,
|
|
465
485
|
profile: mergedOpts.profile,
|
|
466
486
|
search: mergedOpts.search,
|
|
467
487
|
limit: parseInt(mergedOpts.limit, 10) || 100,
|
|
@@ -493,10 +513,10 @@ addCommonOptions(addSearchOption(addLimitOption(downloadsCmd))).action((opts, cm
|
|
|
493
513
|
// ─── Extensions Command ─────────────────────────────────────────────────────
|
|
494
514
|
|
|
495
515
|
const extensionsCmd = program.command("extensions").description("List installed extensions");
|
|
496
|
-
addCommonOptions(
|
|
516
|
+
addSearchOption(addCommonOptions(extensionsCmd)).action((opts, cmd) => {
|
|
497
517
|
const mergedOpts = cmd.optsWithGlobals();
|
|
498
518
|
const results = getExtensions({
|
|
499
|
-
chromeDir: mergedOpts.
|
|
519
|
+
chromeDir: mergedOpts.profilePath,
|
|
500
520
|
profile: mergedOpts.profile,
|
|
501
521
|
search: mergedOpts.search,
|
|
502
522
|
});
|
|
@@ -528,7 +548,7 @@ const searchEnginesCmd = program.command("search-engines").description("List con
|
|
|
528
548
|
addCommonOptions(searchEnginesCmd).action((opts, cmd) => {
|
|
529
549
|
const mergedOpts = cmd.optsWithGlobals();
|
|
530
550
|
const results = getSearchEngines({
|
|
531
|
-
chromeDir: mergedOpts.
|
|
551
|
+
chromeDir: mergedOpts.profilePath,
|
|
532
552
|
profile: mergedOpts.profile,
|
|
533
553
|
});
|
|
534
554
|
|
|
@@ -558,7 +578,7 @@ const topSitesCmd = program.command("top-sites").description("List top sites");
|
|
|
558
578
|
addCommonOptions(topSitesCmd).action((opts, cmd) => {
|
|
559
579
|
const mergedOpts = cmd.optsWithGlobals();
|
|
560
580
|
const results = getTopSites({
|
|
561
|
-
chromeDir: mergedOpts.
|
|
581
|
+
chromeDir: mergedOpts.profilePath,
|
|
562
582
|
profile: mergedOpts.profile,
|
|
563
583
|
});
|
|
564
584
|
|
|
@@ -593,3 +613,17 @@ function formatBytes(bytes) {
|
|
|
593
613
|
// ─── Run ─────────────────────────────────────────────────────────────────────
|
|
594
614
|
|
|
595
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) {
|