node-modules-hunter 1.3.0 → 1.4.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.
Files changed (3) hide show
  1. package/README.md +9 -3
  2. package/dist/cli.js +1219 -1018
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -176,35 +176,35 @@ var en = {
176
176
  "render.stats.directDeps": "Direct deps : {count} declared across the scanned projects",
177
177
  "render.stats.waste": "Waste (dedupable) : {size} ({percent}% of package sizes)",
178
178
  "render.stats.noLicenses": "no package manifests found \u2014 nothing to license",
179
- "render.stats.copyleftProd": " \u26A0 copyleft di production dependencies",
180
- "render.stats.copyleftOther": " (copyleft, bukan prod-dep)",
179
+ "render.stats.copyleftProd": " \u26A0 copyleft in production dependencies",
180
+ "render.stats.copyleftOther": " (copyleft, not a prod dependency)",
181
181
  "render.stats.experimental": "(experimental)",
182
182
  "render.stats.grade": "grade",
183
183
  "render.stats.wasteLabel": "waste",
184
184
  "render.stats.dupLabel": "dup factor",
185
185
  "render.stats.deadLabel": "dead",
186
- "render.stats.deadNotAudited": "(tidak diaudit \u2014 tambahkan --dead untuk daftar)",
186
+ "render.stats.deadNotAudited": "(not audited \u2014 add --dead for the list)",
187
187
  "render.stats.sizeLabel": "size",
188
- "render.stats.co2Storage": "estimasi kasar, bukan audit karbon \u2014 simpan setahun",
189
- "render.stats.co2Transfer": "kalau men-download ulang semuanya sekali",
190
- "render.stats.deprecatedNone": "tidak ada paket deprecated \u2600\uFE0F",
188
+ "render.stats.co2Storage": "rough estimate, not a carbon audit \u2014 one year of storage",
189
+ "render.stats.co2Transfer": "plus re-downloading everything once",
190
+ "render.stats.deprecatedNone": "no deprecated packages \u2600\uFE0F",
191
191
  "render.stats.deprecatedCount": "{count} instance deprecated:",
192
- "render.stats.moreDeprecations": "\u2026dan {n} lainnya",
192
+ "render.stats.moreDeprecations": "\u2026and {n} more",
193
193
  "render.stats.lockfileGrade": "(lockfile-grade)",
194
- "render.stats.graphSuffix": "lockfile-grade \u2014 sisanya manifest-grade",
194
+ "render.stats.graphSuffix": "lockfile-grade \u2014 the rest is manifest-grade",
195
195
  "render.stats.graphRoot": "root direct : {declared} declared \u2192 {nodes} tree nodes via {edges} edges",
196
- "render.stats.graphNoDepth": "tidak ada kedalaman yang bisa dilacak dari root \u2014 bisa jadi lockfile ini v1/pecah",
196
+ "render.stats.graphNoDepth": "nothing traceable in depth from the root \u2014 this lockfile may be v1/broken",
197
197
  "render.stats.graphUnreachable": "+ {n} node(s) unreachable from the root (optional/peer pruning)",
198
198
  "render.stats.noLockfile": "no usable lockfile \u2014 manifest-grade",
199
- "render.stats.reinstallNaive": "(naif)",
200
- "render.stats.reinstallLine": "pasang ulang semuanya sekali : ~{duration}",
199
+ "render.stats.reinstallNaive": "(naive)",
200
+ "render.stats.reinstallLine": "reinstall everything once : ~{duration}",
201
201
  "render.stats.copies": "\xD7{n} copies",
202
202
  "render.stats.oneCopy": "\xD71 copy",
203
- "render.stats.dedupSaving": " \u2190 dedup bisa hemat {size}",
203
+ "render.stats.dedupSaving": " \u2190 dedup could save {size}",
204
204
  "render.stats.longTail": "\u2026 plus {names} more package name(s) \xB7 {instances} instances \xB7 {size}",
205
- "render.stats.bisaHemat": " bisa hemat",
205
+ "render.stats.bisaHemat": " could save",
206
206
  "render.stats.declaredRange": "{project} declared {range} ({field})",
207
- "render.stats.transitive": "transitive (tidak dideklarasi di manifest)",
207
+ "render.stats.transitive": "transitive (not declared in a manifest)",
208
208
  "render.global.title": "\u{1F310} nmh stats \u2014 global installation analysis",
209
209
  "render.global.readonly": "(\u26A0\uFE0F global mode \u2014 read-only; needs access to the PM prefixes \u2014 sudo is never auto-applied)",
210
210
  "render.global.pmDetected": "PM detected : {pms}{skipped}",
@@ -238,8 +238,8 @@ var en = {
238
238
  "render.why.title": "\u{1F50D} why '{pkg}' \u2014 {count} instance(s)",
239
239
  "render.why.linked": "linked",
240
240
  "render.why.declares": " project : {project} declares {range} ({field})",
241
- "render.why.noName": "(manifest tanpa nama)",
242
- "render.why.transitive": " project : transitive \u2014 tidak dideklarasi di manifest manapun",
241
+ "render.why.noName": "(unnamed manifest)",
242
+ "render.why.transitive": " project : transitive \u2014 not declared in any manifest",
243
243
  "render.why.requiredBy": " required by : {count} package(s)",
244
244
  "render.why.moreRequirers": " \u2026 plus {n} more requirer(s)",
245
245
  "render.why.rootOnly": " required by : no package in the lockfile graph depends on it (root-only copy?)",
@@ -251,7 +251,7 @@ var en = {
251
251
  // ── utils: format / update-check / version ─────────────────────────────
252
252
  "format.now": "now",
253
253
  "format.ago": "{n} ago",
254
- "update.note": "update tersedia: {current} \u2192 {latest} \u2014 npm i -g node-modules-hunter (cek 24 jam sekali, opt-in via --update-check)",
254
+ "update.note": "update available: {current} \u2192 {latest} \u2014 npm i -g node-modules-hunter (checked every 24 h, opt-in via --update-check)",
255
255
  "version.tagline": "hunt node_modules \u2014 scan \xB7 measure \xB7 clean safely",
256
256
  "version.yes": "yes",
257
257
  "version.no": "no",
@@ -302,6 +302,7 @@ var en = {
302
302
  "wizard.menu.map": "\u{1F5FA}\uFE0F Map dependencies \u2014 project \u2192 PM \u2192 declared deps",
303
303
  "wizard.menu.stats": "\u{1F4CA} Detailed report \u2014 the full stats read-out",
304
304
  "wizard.menu.settings": "\u2699\uFE0F Settings & integration (read-only view)",
305
+ "wizard.menu.update": "\u{1F501} Update nmh (checks the registry, asks first)",
305
306
  "wizard.menu.quit": "\u23F9 Exit nmh",
306
307
  "wizard.outro.bye": "bye \u{1F44B} \u2014 nothing deleted",
307
308
  "wizard.search.message": "Search installed packages \u2014 which pattern?",
@@ -335,9 +336,9 @@ var en = {
335
336
  "update.info.installed": "installed {value}",
336
337
  "update.info.latest": "latest {value}",
337
338
  "update.info.update": "update {value}",
338
- "update.info.available": "tersedia \u2014 jalankan `nmh update`",
339
- "update.info.availableNonGlobal": " (atau: npm i -g node-modules-hunter)",
340
- "update.info.none": "tidak ada \u2014 ini versi terbaru",
339
+ "update.info.available": "available \u2014 run `nmh update`",
340
+ "update.info.availableNonGlobal": " (or: npm i -g node-modules-hunter)",
341
+ "update.info.none": "none \u2014 this is the latest version",
341
342
  "update.info.summary": "summary {value}",
342
343
  "update.info.tarball": "tarball {value}",
343
344
  "update.info.sizeSuffix": " ({size}{files} files)",
@@ -345,17 +346,22 @@ var en = {
345
346
  "update.info.license": "license {value}",
346
347
  "update.info.published": "published {value}",
347
348
  "update.err.noRegistry": "cannot read the latest version \u2014 is the registry reachable? (npm view node-modules-hunter version)",
348
- "update.check.available": "\u2191 update tersedia: {current} \u2192 {latest} \u2014 jalankan `nmh update` untuk menginstall",
349
- "update.check.latest": "\u2713 nmh {current} sudah versi terbaru (registry: {latest})",
350
- "update.latestNoInstall": "\u2713 nmh {current} sudah versi terbaru (registry: {latest}) \u2014 tak ada yang diinstall",
351
- "update.manual.title": "nmh {current} terpasang di luar npm global \u2014 update manual:",
352
- "update.manual.command": " npm i -g node-modules-hunter (atau: pnpm add -g / bunx / brew upgrade node-modules-hunter)",
353
- "update.err.needsAnswer": "update butuh jawaban eksplisit \u2014 -y untuk menginstall, -n untuk menolak (--check/--info untuk lihat saja)",
349
+ "update.check.available": "\u2191 update available: {current} \u2192 {latest} \u2014 run `nmh update` to install",
350
+ "update.check.latest": "\u2713 nmh {current} is already the latest version (registry: {latest})",
351
+ "update.latestNoInstall": "\u2713 nmh {current} is already the latest version (registry: {latest}) \u2014 nothing installed",
352
+ "update.manual.title": "nmh {current} is installed outside npm global \u2014 update manually:",
353
+ "update.manual.command": " npm i -g node-modules-hunter (or: pnpm add -g / bunx / brew upgrade node-modules-hunter)",
354
+ "update.err.needsAnswer": "update needs an explicit answer \u2014 -y to install, -n to decline (--check/--info just look)",
354
355
  "update.confirm": "Update nmh {current} \u2192 {latest} via npm install -g?",
355
- "update.declined": "\u2715 tetap nmh {current} \u2014 update ke {latest} tidak diinstall",
356
- "update.err.failed": "\u26A0 update gagal: {detail}",
357
- "update.err.manualHint": " coba manual: npm install -g node-modules-hunter@{latest}",
358
- "update.done": "\u2713 terupdate {current} \u2192 {latest} (npm install -g node-modules-hunter)",
356
+ "update.declined": "\u2715 staying on nmh {current} \u2014 the {latest} update was not installed",
357
+ "update.err.failed": "\u26A0 update failed: {detail}",
358
+ "update.err.manualHint": " try manually: npm install -g node-modules-hunter@{latest}",
359
+ "update.done": "\u2713 updated {current} \u2192 {latest} (npm install -g node-modules-hunter)",
360
+ "update.info.tags": "dist-tags {tags}",
361
+ "update.check.onTag": "(dist-tag: {tag})",
362
+ "update.confirm.downgrade": 'Downgrade nmh {current} \u2192 {target} from dist-tag "{tag}"?',
363
+ "update.err.tagUnknown": 'dist-tag "{tag}" not found \u2014 available: {tags}',
364
+ "update.err.invalidTag": 'invalid dist-tag "{value}" \u2014 use letters, digits, dot, hyphen, underscore',
359
365
  // ── commands/global.ts ──────────────────────────────────────────────────
360
366
  "global.spin.probe": "probing global prefixes\u2026",
361
367
  "global.spin.progress": "global {pm} \u2014 {done}/{total} packages",
@@ -371,7 +377,7 @@ var en = {
371
377
  "why.warn.none": "no instance of '{pkg}' in the scanned node_modules \u2014 nmh why <pkg> [dirs]",
372
378
  "treemap.warn.none": "no node_modules found \u2014 nothing to draw here \u{1F643}",
373
379
  "treemap.err.write": "\u{1F6D1} could not write the treemap file \u2192 {path} \u2014 {detail}",
374
- "treemap.done": "\u{1F5FA}\uFE0F treemap \u2192 {path} \u2014 buka di browser, hover cell buat detail",
380
+ "treemap.done": "\u{1F5FA}\uFE0F treemap \u2192 {path} \u2014 open it in a browser, hover a cell for details",
375
381
  // ── verbose diagnostics & utils ─────────────────────────────────────────
376
382
  "verbose.deleteLogUnavailable": "delete log unavailable: {detail}",
377
383
  "verbose.configUsing": "config: using {file}",
@@ -396,11 +402,11 @@ var en = {
396
402
  "verbose.npmViewFailed": "npm view failed (rc {code}): {stderr}",
397
403
  // ── commands/stats.ts ───────────────────────────────────────────────────
398
404
  "stats.spin.progress": "analyzing {done}/{total} node_modules\u2026",
399
- "stats.hint.noDeclared": "copies resolusinya ikut parent masing-masing \u2014 tidak ada knob langsung di project level",
405
+ "stats.hint.noDeclared": "copies resolve through their own parents \u2014 no direct knob at the project level",
400
406
  "stats.hint.tail": " (declared {range})",
401
- "stats.hint.pnpm": "range declared identik \u2014 pnpm virtual store melipat copy hoisted; cukup satu versi di workspace root{tail}",
402
- "stats.hint.sameRange": "range declared identik \u2014 jalankan install ulang / npm dedupe \xB7 yarn dedupe melipat copy hoisted{tail}",
403
- "stats.hint.diffRanges": "range declared beda ({ranges}) \u2014 samakan dulu di package.json, lalu install ulang",
407
+ "stats.hint.pnpm": "identical declared ranges \u2014 the pnpm virtual store folds hoisted copies; one version at the workspace root is enough{tail}",
408
+ "stats.hint.sameRange": "identical declared ranges \u2014 rerun install / npm dedupe \xB7 yarn dedupe folds hoisted copies{tail}",
409
+ "stats.hint.diffRanges": "declared ranges differ ({ranges}) \u2014 align them in package.json first, then reinstall",
404
410
  "stats.err.noBaseline": "no baseline named '{name}' \u2014 {detail}",
405
411
  "stats.err.baselinesSaved": "saved: {list}",
406
412
  "stats.err.saveFirst": "save one first with nmh stats --save-baseline <name>",
@@ -411,7 +417,7 @@ var en = {
411
417
  "stats.err.saveFailed": "could not save baseline '{name}': {detail}",
412
418
  // ── core/treemap.ts (HTML artifact) ────────────────────────────────────
413
419
  "treemap.link": " \u27F6link",
414
- "treemap.html.header": "nmh treemap \u2014 {entries} \u2014 {count} node_modules \u2014 hover buat detail disk, generated {at}",
420
+ "treemap.html.header": "nmh treemap \u2014 {entries} \u2014 {count} node_modules \u2014 hover a cell for disk details, generated {at}",
415
421
  "treemap.html.aria": "treemap ukuran node_modules",
416
422
  // ── help manual ─────────────────────────────────────────────────────────
417
423
  "help.tagline": "hunt bloated node_modules folders: scan, measure, clean safely (npm/pnpm/yarn/bun)",
@@ -421,9 +427,9 @@ var en = {
421
427
  "help.statsSub.title": "Stats subcommands",
422
428
  "help.options.title": "Options \u2014 {group}",
423
429
  "help.examples.title": "Examples",
424
- "help.cmd.bare": "interactive wizard: arrow menu (delete all / pick / search / map / report / settings)",
430
+ "help.cmd.bare": "interactive wizard: arrow menu (delete all / pick / search / map / report / update / settings)",
425
431
  "help.cmd.paths": "shortcut: scan given path(s); one-liner actions via flags (--delete, --search, \u2026)",
426
- "help.cmd.wizard": "v1.2: the wizard on explicit targets (--dir=./a,./b skips the auto-climb); -- <view> opens a view first",
432
+ "help.cmd.wizard": "v1.2: the wizard on explicit targets (--dir=./a,./b skips the auto-climb); -- <view> opens a view first; the menu now includes \u{1F501} Update nmh (v1.4)",
427
433
  "help.cmd.scan": "full scan across targets (default: cwd)",
428
434
  "help.cmd.clean": "scan + delete everything safe (trash by default)",
429
435
  "help.cmd.search": "find installed packages by name (+ versions & sizes) \u2014 read-only",
@@ -433,7 +439,7 @@ var en = {
433
439
  "help.cmd.treemap": "single-file interactive HTML treemap \u2192 nmh-treemap.html",
434
440
  "help.cmd.global": "global installs across npm/pnpm/yarn/bun \u2014 read-only",
435
441
  "help.cmd.config": "manage .nmhrc from the CLI: info \xB7 set \xB7 add \xB7 remove \xB7 unset",
436
- "help.cmd.update": "v1.2: shows the facts and asks before installing \u2014 --check / --info compare only; -y installs, -n declines, --force skips the ask",
442
+ "help.cmd.update": "v1.4: shows the facts and asks before installing \u2014 --check [tag] / --info compare only; --tag reads a dist-tag (downgrades confirm with NO as default); -y installs, -n declines, --force skips the ask",
437
443
  "help.cmd.version": "banner: tool version, node+abi, OS/arch/kernel, tty (alias: -v / --version)",
438
444
  "help.cmd.help": "this help (alias: -h / --help)",
439
445
  "help.statsSub.byType": "breakdown per dependency field (dep/dev/optional/peer/transitive)",
@@ -463,6 +469,8 @@ var en = {
463
469
  "help.flag.saveReport": "also write the printed report to a file (.json/.md/.txt; --report <file> aliases it)",
464
470
  "help.flag.wizard": "v1.2: open the wizard explicitly \u2014 same as bare `nmh`, but a pipe refuses with directions instead of a scan",
465
471
  "help.flag.updateFamily": "v1.2: read-only views vs consented install \u2014 see `nmh update` row above",
472
+ "help.flag.tag": "read a specific npm dist-tag \u2014 nmh update --tag beta; --check <tag> compares against it (v1.4)",
473
+ "help.flag.updateTag": "persisted update dist-tag (updateTag in .nmhrc) \u2014 what `nmh update` / `--check` read by default (v1.4)",
466
474
  "help.flag.updateCheck": "peek npm for a newer release (non-blocking, 24 h cache; also settable in .nmhrc)",
467
475
  "help.flag.stale": "keep only projects idle >= <days>; ladder = git commit \u2192 manifest \u2192 folder mtime; no evidence = dropped",
468
476
  "help.flag.fastSize": "measure with one `du -sk` per entry (KiB granularity) instead of walking every file",
@@ -474,6 +482,7 @@ var en = {
474
482
  "help.flag.verbose": "debug chatter on stderr",
475
483
  "help.flag.noColor": "disable ANSI colors (auto: colors only on a real TTY or with --color / FORCE_COLOR)",
476
484
  "help.flag.color": "force ANSI colors even on a piped run (wins over a config color:false)",
485
+ "help.flag.language": "UI language: en | id | zh | ru | es \u2014 also via .nmhrc `language` and NMH_LANG; unknown values fall back to en silently",
477
486
  "help.flag.recursive": "also look INSIDE found node_modules (nested audit; totals stay top-level only)",
478
487
  "help.flag.pm": "filter by detected PM: npm|pnpm|yarn|bun|vp \u2014 no value lists what was detected",
479
488
  "help.flag.exclude": "exclude paths from results (comma list of globs, e.g. **/e2e/**)",
@@ -549,6 +558,9 @@ var en = {
549
558
  "cli.err.rootRefusal": "refusing a delete op over the filesystem root \u2014 point --dir at the project directory you want cleaned",
550
559
  "cli.err.checkOnlyUpdate": "--check only works with the update command \u2014 nmh update --check",
551
560
  "cli.err.infoOnlyUpdate": "--info only works with the update command \u2014 nmh update --info",
561
+ "cli.err.tagNeedsValue": "--tag needs a dist-tag name \u2014 nmh update --tag beta (bare --check reads --tag / .nmhrc / latest)",
562
+ "cli.err.invalidTag": 'invalid dist-tag "{value}" \u2014 use letters, digits, dot, hyphen, underscore',
563
+ "cli.err.tagOnlyUpdate": "--tag only works with the update command \u2014 nmh update --tag beta",
552
564
  "cli.err.updateArgs": "update takes no arguments \u2014 plain `nmh update` (add --json for the payload)",
553
565
  "cli.err.checkInfoExclusive": "--check and --info are two different read-only views \u2014 pick one (nmh update --check | --info)",
554
566
  "cli.err.routerOrphan": "the `--` router belongs to the wizard \u2014 nmh wizard -- stats|map|search|why|treemap \u2026",
@@ -595,6 +607,7 @@ var en = {
595
607
  "config.err.notBoolean": "invalid config: {file}: {key} must be true or false (got {value})",
596
608
  "config.err.invalidLanguage": "invalid config: {file}: language must be one of en | id | zh | ru | es (got {value})",
597
609
  "config.err.invalidLogDir": "invalid config: {file}: logDir must be a non-empty string",
610
+ "config.err.invalidUpdateTag": "invalid config: {file}: updateTag must be a dist-tag name \u2014 letters, digits, dot, hyphen, underscore (got {value})",
598
611
  "config.err.unreadable": "config unreadable: {file} ({code})",
599
612
  "config.err.notFound": "config file not found: {file}",
600
613
  "config.warn.unknownKey": '{file}: unknown config key "{key}" \u2014 ignored',
@@ -602,6 +615,7 @@ var en = {
602
615
  "config.err.invalidDepthValue": "invalid --depth value: {value} (expected a non-negative integer)",
603
616
  "config.err.invalidModeValue": "invalid --default-mode: {value} (expected hard | soft | trash)",
604
617
  "config.err.invalidLanguageValue": "invalid --language value: {value} (expected en | id | zh | ru | es)",
618
+ "config.err.invalidUpdateTagValue": "invalid --update-tag value: {value} (letters, digits, dot, hyphen, underscore)",
605
619
  "config.err.boolNeedsValue": "{label} needs true or false \u2014 e.g. nmh config set --animate=false",
606
620
  "config.err.setListNeedsValue": "config set --{flag} needs the list value \u2014 e.g. --{flag}=.npm,.nvm",
607
621
  "config.err.addListNeedsValue": "config add --{flag} needs items to append \u2014 e.g. --{flag}=.cache,self",
@@ -802,6 +816,7 @@ var id = {
802
816
  "wizard.menu.map": "\u{1F5FA}\uFE0F Petakan dependensi \u2014 proyek \u2192 PM \u2192 dep terdeklarasi",
803
817
  "wizard.menu.stats": "\u{1F4CA} Laporan detail \u2014 read-out stats lengkap",
804
818
  "wizard.menu.settings": "\u2699\uFE0F Setelan & integrasi (tampilan read-only)",
819
+ "wizard.menu.update": "\u{1F501} Update nmh (cek registry, tanya dulu)",
805
820
  "wizard.menu.quit": "\u23F9 Keluar dari nmh",
806
821
  "wizard.outro.bye": "sampai jumpa \u{1F44B} \u2014 tidak ada yang dihapus",
807
822
  "wizard.search.message": "Cari paket terinstall \u2014 pattern apa?",
@@ -856,6 +871,11 @@ var id = {
856
871
  "update.err.failed": "\u26A0 update gagal: {detail}",
857
872
  "update.err.manualHint": " coba manual: npm install -g node-modules-hunter@{latest}",
858
873
  "update.done": "\u2713 terupdate {current} \u2192 {latest} (npm install -g node-modules-hunter)",
874
+ "update.info.tags": "dist-tags {tags}",
875
+ "update.check.onTag": "(dist-tag: {tag})",
876
+ "update.confirm.downgrade": 'Turunkan nmh {current} \u2192 {target} dari dist-tag "{tag}"?',
877
+ "update.err.tagUnknown": 'dist-tag "{tag}" tidak ditemukan \u2014 yang tersedia: {tags}',
878
+ "update.err.invalidTag": 'dist-tag "{value}" tidak valid \u2014 pakai huruf, digit, titik, tanda hubung, garis bawah',
859
879
  // ── commands/global.ts ──────────────────────────────────────────────────
860
880
  "global.spin.probe": "memeriksa prefix global\u2026",
861
881
  "global.spin.progress": "global {pm} \u2014 {done}/{total} paket",
@@ -921,9 +941,9 @@ var id = {
921
941
  "help.statsSub.title": "Subperintah stats",
922
942
  "help.options.title": "Opsi \u2014 {group}",
923
943
  "help.examples.title": "Contoh",
924
- "help.cmd.bare": "wizard interaktif: menu panah (hapus semua / pilih / search / map / report / setelan)",
944
+ "help.cmd.bare": "wizard interaktif: menu panah (hapus semua / pilih / search / map / report / update / setelan)",
925
945
  "help.cmd.paths": "jalan pintas: scan path yang diberikan; aksi satu-baris via flag (--delete, --search, \u2026)",
926
- "help.cmd.wizard": "v1.2: wizard pada target eksplisit (--dir=./a,./b melewati auto-climb); -- <view> membuka view dulu",
946
+ "help.cmd.wizard": "v1.2: wizard pada target eksplisit (--dir=./a,./b melewati auto-climb); -- <view> membuka view dulu; menu kini punya \u{1F501} Update nmh (v1.4)",
927
947
  "help.cmd.scan": "scan penuh di seluruh target (bawaan: cwd)",
928
948
  "help.cmd.clean": "scan + hapus semua yang aman (trash secara bawaan)",
929
949
  "help.cmd.search": "cari paket terinstall berdasarkan nama (+ versi & ukuran) \u2014 read-only",
@@ -933,7 +953,7 @@ var id = {
933
953
  "help.cmd.treemap": "treemap HTML interaktif satu-file \u2192 nmh-treemap.html",
934
954
  "help.cmd.global": "instalasi global lintas npm/pnpm/yarn/bun \u2014 read-only",
935
955
  "help.cmd.config": "kelola .nmhrc dari CLI: info \xB7 set \xB7 add \xB7 remove \xB7 unset",
936
- "help.cmd.update": "v1.2: menampilkan fakta dan bertanya sebelum menginstall \u2014 --check / --info hanya membandingkan; -y menginstall, -n menolak, --force melewati tanya",
956
+ "help.cmd.update": "v1.4: menampilkan fakta dan bertanya sebelum menginstall \u2014 --check [tag] / --info hanya membandingkan; --tag membaca dist-tag (downgrade konfirmasinya default TIDAK); -y menginstall, -n menolak, --force melewati tanya",
937
957
  "help.cmd.version": "banner: versi tool, node+abi, OS/arch/kernel, tty (alias: -v / --version)",
938
958
  "help.cmd.help": "bantuan ini (alias: -h / --help)",
939
959
  "help.statsSub.byType": "rincian per field dependensi (dep/dev/optional/peer/transitive)",
@@ -963,6 +983,8 @@ var id = {
963
983
  "help.flag.saveReport": "tuliskan juga laporan yang tercetak ke file (.json/.md/.txt; --report <file> aliasnya)",
964
984
  "help.flag.wizard": "v1.2: buka wizard secara eksplisit \u2014 sama dengan `nmh` polos, tapi pipe menolak dengan arah alih-alih scan",
965
985
  "help.flag.updateFamily": "v1.2: view read-only vs install yang disetujui \u2014 lihat baris `nmh update` di atas",
986
+ "help.flag.tag": "baca dist-tag npm tertentu \u2014 nmh update --tag beta; --check <tag> membandingkan dengannya (v1.4)",
987
+ "help.flag.updateTag": "dist-tag update yang tersimpan (updateTag di .nmhrc) \u2014 yang dibaca `nmh update` / `--check` secara default (v1.4)",
966
988
  "help.flag.updateCheck": "intip npm untuk rilis lebih baru (non-blocking, cache 24 jam; juga bisa di .nmhrc)",
967
989
  "help.flag.stale": "hanya proyek idle >= <hari>; tangga = git commit \u2192 manifest \u2192 mtime folder; tanpa bukti = dibuang",
968
990
  "help.flag.fastSize": "ukur dengan satu `du -sk` per entry (granularitas KiB) alih-alih jalan di tiap file",
@@ -974,6 +996,7 @@ var id = {
974
996
  "help.flag.verbose": "obrolan debug di stderr",
975
997
  "help.flag.noColor": "matikan warna ANSI (auto: warna hanya di TTY sungguhan atau dengan --color / FORCE_COLOR)",
976
998
  "help.flag.color": "paksa warna ANSI meski dijalankan di pipe (menang atas config color:false)",
999
+ "help.flag.language": "bahasa UI: en | id | zh | ru | es \u2014 juga lewat .nmhrc `language` dan NMH_LANG; nilai tak dikenal diam-diam jatuh ke en",
977
1000
  "help.flag.recursive": "lihat juga DI DALAM node_modules yang ditemukan (audit nested; total tetap top-level saja)",
978
1001
  "help.flag.pm": "filter berdasarkan PM terdeteksi: npm|pnpm|yarn|bun|vp \u2014 tanpa nilai mendaftar yang terdeteksi",
979
1002
  "help.flag.exclude": "kecualikan path dari hasil (daftar glob dipisah koma, mis. **/e2e/**)",
@@ -1049,6 +1072,9 @@ var id = {
1049
1072
  "cli.err.rootRefusal": "menolak delete op di atas root filesystem \u2014 arahkan --dir ke direktori proyek yang ingin dibersihkan",
1050
1073
  "cli.err.checkOnlyUpdate": "--check hanya untuk perintah update \u2014 nmh update --check",
1051
1074
  "cli.err.infoOnlyUpdate": "--info hanya untuk perintah update \u2014 nmh update --info",
1075
+ "cli.err.tagNeedsValue": "--tag butuh nama dist-tag \u2014 nmh update --tag beta (--check tanpa nilai membaca --tag / .nmhrc / latest)",
1076
+ "cli.err.invalidTag": 'dist-tag "{value}" tidak valid \u2014 pakai huruf, digit, titik, tanda hubung, garis bawah',
1077
+ "cli.err.tagOnlyUpdate": "--tag hanya untuk perintah update \u2014 nmh update --tag beta",
1052
1078
  "cli.err.updateArgs": "update tidak menerima argumen \u2014 `nmh update` polos (tambah --json untuk payload)",
1053
1079
  "cli.err.checkInfoExclusive": "--check dan --info adalah dua view read-only berbeda \u2014 pilih satu (nmh update --check | --info)",
1054
1080
  "cli.err.routerOrphan": "router `--` milik wizard \u2014 nmh wizard -- stats|map|search|why|treemap \u2026",
@@ -1095,6 +1121,7 @@ var id = {
1095
1121
  "config.err.notBoolean": "config tidak valid: {file}: {key} harus true atau false (dapat {value})",
1096
1122
  "config.err.invalidLanguage": "config tidak valid: {file}: language harus salah satu dari en | id | zh | ru | es (dapat {value})",
1097
1123
  "config.err.invalidLogDir": "config tidak valid: {file}: logDir harus string tak-kosong",
1124
+ "config.err.invalidUpdateTag": "config tidak valid: {file}: updateTag harus nama dist-tag \u2014 huruf, digit, titik, tanda hubung, garis bawah (dapat {value})",
1098
1125
  "config.err.unreadable": "config tidak bisa dibaca: {file} ({code})",
1099
1126
  "config.err.notFound": "file config tidak ditemukan: {file}",
1100
1127
  "config.warn.unknownKey": '{file}: kunci config tidak dikenal "{key}" \u2014 diabaikan',
@@ -1102,6 +1129,7 @@ var id = {
1102
1129
  "config.err.invalidDepthValue": "nilai --depth tidak valid: {value} (harus bilangan bulat non-negatif)",
1103
1130
  "config.err.invalidModeValue": "nilai --default-mode tidak valid: {value} (harus hard | soft | trash)",
1104
1131
  "config.err.invalidLanguageValue": "nilai --language tidak valid: {value} (harus en | id | zh | ru | es)",
1132
+ "config.err.invalidUpdateTagValue": "nilai --update-tag tidak valid: {value} (huruf, digit, titik, tanda hubung, garis bawah)",
1105
1133
  "config.err.boolNeedsValue": "{label} butuh true atau false \u2014 mis. nmh config set --animate=false",
1106
1134
  "config.err.setListNeedsValue": "config set --{flag} butuh nilai daftarnya \u2014 mis. --{flag}=.npm,.nvm",
1107
1135
  "config.err.addListNeedsValue": "config add --{flag} butuh item untuk ditambahkan \u2014 mis. --{flag}=.cache,self",
@@ -1122,1000 +1150,1028 @@ var id_default = id;
1122
1150
  // src/i18n/locales/zh.ts
1123
1151
  var zh = {
1124
1152
  // ── banner ──────────────────────────────────────────────────────────────
1125
- "banner.tagline": "scan \xB7 measure \xB7 clean \u2014 safety rails on",
1126
- "banner.compact": "read-only scan",
1127
- "banner.updateLine": "\u2191 {version} available \u2014 run `nmh update`",
1153
+ "banner.tagline": "\u626B\u63CF \xB7 \u5EA6\u91CF \xB7 \u6E05\u7406 \u2014 \u5B89\u5168\u62A4\u680F\u5DF2\u5F00\u542F",
1154
+ "banner.compact": "\u53EA\u8BFB\u626B\u63CF",
1155
+ "banner.updateLine": "\u2191 {version} \u53EF\u7528 \u2014 \u8BF7\u8FD0\u884C `nmh update`",
1128
1156
  // ── generic ─────────────────────────────────────────────────────────────
1129
- "common.path": "Path",
1130
- "common.size": "Size",
1131
- "common.share": "Share",
1132
- "common.packages": "Pkgs",
1157
+ "common.path": "\u8DEF\u5F84",
1158
+ "common.size": "\u5927\u5C0F",
1159
+ "common.share": "\u5360\u6BD4",
1160
+ "common.packages": "\u5305\u6570",
1133
1161
  "common.pm": "PM",
1134
- "common.modified": "Modified",
1135
- "common.idle": "Idle",
1162
+ "common.modified": "\u4FEE\u6539\u65F6\u95F4",
1163
+ "common.idle": "\u95F2\u7F6E",
1136
1164
  // ── core/render.ts ──────────────────────────────────────────────────────
1137
- "render.scan.nested": " nested ",
1138
- "render.scan.nestedNote": " (+{n} nested, not counted)",
1139
- "render.scan.total": "\u{1F4BE} Total: {size} across {folders} folder(s), {packages} packages",
1140
- "render.warn.permission": "\u26A0 {n} directory(ies) unreadable (permission denied) \u2014 exit code 4",
1141
- "render.plan.hardLabel": "DELETE (permanent)",
1142
- "render.plan.trashLabel": "TRASH (restorable)",
1143
- "render.plan.dryRun": "[DRY RUN] Would {label} {count} folder(s) ({size}):",
1144
- "render.plan.more": " \u2026 plus {n} more",
1145
- "render.plan.rerun": "Run again without --dry-run to execute.",
1146
- "render.delete.verbHard": "Deleted",
1147
- "render.delete.verbTrash": "Trashed",
1148
- "render.delete.deleted": "\u2705 {verb}: {size} from {count} folder(s)",
1149
- "render.delete.failed": "\u26A0 {count} folder(s) failed \u2014 rerun with --verbose for details",
1150
- "render.search.header": "\u{1F50D} '{pattern}' \u2192 {count} package(s) in {dirs} node_modules",
1151
- "render.search.pathMatch": " (path match)",
1152
- "render.map.head.project": "Project",
1153
- "render.map.head.topPkgs": "TopPkgs",
1154
- "render.map.head.declared": "Declared",
1155
- "render.map.noPkgs": " (no top-level packages)",
1156
- "render.map.noManifest": " (no manifest with declared dependencies)",
1157
- "render.map.noDeclared": " (no declared dependencies)",
1158
- "render.map.declaredBy": "\u{1F517} '{pkg}' is declared by {count} project(s):",
1159
- "render.section.overview": "OVERVIEW",
1160
- "render.section.byType": "BY TYPE",
1161
- "render.section.licenses": "LICENSES",
1162
- "render.section.score": "BLOAT SCORE",
1163
- "render.section.co2": "CO2 ESTIMATE",
1164
- "render.section.deprecated": "DEPRECATED",
1165
- "render.section.graph": "GRAPH",
1166
- "render.section.reinstall": "REINSTALL",
1167
- "render.section.top": "TOP {n} SIZE",
1168
- "render.section.longTail": "LONG TAIL",
1169
- "render.section.dedup": "DEDUP SUGGESTION",
1170
- "render.section.baseline": "BASELINE COMPARE",
1171
- "render.section.audit": "DEPS AUDIT",
1165
+ "render.scan.nested": " \u5D4C\u5957 ",
1166
+ "render.scan.nestedNote": " (\u53E6\u6709 {n} \u4E2A\u5D4C\u5957\uFF0C\u672A\u8BA1\u5165)",
1167
+ "render.scan.total": "\u{1F4BE} \u603B\u8BA1\uFF1A{size}\uFF0C{folders} \u4E2A\u6587\u4EF6\u5939\uFF0C{packages} \u4E2A\u5305",
1168
+ "render.warn.permission": "\u26A0 {n} \u4E2A\u76EE\u5F55\u65E0\u6CD5\u8BFB\u53D6\uFF08\u6743\u9650\u4E0D\u8DB3\uFF09\u2014 \u9000\u51FA\u7801 4",
1169
+ "render.plan.hardLabel": "\u5220\u9664\uFF08\u6C38\u4E45\uFF09",
1170
+ "render.plan.trashLabel": "\u79FB\u5165\u56DE\u6536\u7AD9\uFF08\u53EF\u6062\u590D\uFF09",
1171
+ "render.plan.dryRun": "[\u6F14\u7EC3] \u5C06{label} {count} \u4E2A\u6587\u4EF6\u5939\uFF08{size}\uFF09\uFF1A",
1172
+ "render.plan.more": " \u2026 \u53E6\u6709 {n} \u9879",
1173
+ "render.plan.rerun": "\u53BB\u6389 --dry-run \u91CD\u65B0\u8FD0\u884C\u5373\u53EF\u6267\u884C\u3002",
1174
+ "render.delete.verbHard": "\u5DF2\u5220\u9664",
1175
+ "render.delete.verbTrash": "\u5DF2\u79FB\u5165\u56DE\u6536\u7AD9",
1176
+ "render.delete.deleted": "\u2705 {verb}\uFF1A{count} \u4E2A\u6587\u4EF6\u5939\uFF0C\u5171 {size}",
1177
+ "render.delete.failed": "\u26A0 {count} \u4E2A\u6587\u4EF6\u5939\u5931\u8D25 \u2014 \u52A0 --verbose \u91CD\u8DD1\u67E5\u770B\u8BE6\u60C5",
1178
+ "render.search.header": "\u{1F50D} '{pattern}' \u2192 \u5728 {dirs} \u4E2A node_modules \u4E2D\u627E\u5230 {count} \u4E2A\u5305",
1179
+ "render.search.pathMatch": " \uFF08\u8DEF\u5F84\u5339\u914D\uFF09",
1180
+ "render.map.head.project": "\u9879\u76EE",
1181
+ "render.map.head.topPkgs": "\u4E3B\u8981\u5305",
1182
+ "render.map.head.declared": "\u58F0\u660E\u4F9D\u8D56",
1183
+ "render.map.noPkgs": " \uFF08\u6CA1\u6709\u9876\u5C42\u5305\uFF09",
1184
+ "render.map.noManifest": " \uFF08\u6CA1\u6709\u542B\u58F0\u660E\u4F9D\u8D56\u7684 manifest\uFF09",
1185
+ "render.map.noDeclared": " \uFF08\u6CA1\u6709\u58F0\u660E\u4F9D\u8D56\uFF09",
1186
+ "render.map.declaredBy": "\u{1F517} '{pkg}' \u88AB {count} \u4E2A\u9879\u76EE\u58F0\u660E\uFF1A",
1187
+ "render.section.overview": "\u603B\u89C8",
1188
+ "render.section.byType": "\u6309\u7C7B\u578B",
1189
+ "render.section.licenses": "\u8BB8\u53EF\u8BC1",
1190
+ "render.section.score": "\u81C3\u80BF\u8BC4\u5206",
1191
+ "render.section.co2": "CO2 \u4F30\u7B97",
1192
+ "render.section.deprecated": "\u5DF2\u5F03\u7528",
1193
+ "render.section.graph": "\u4F9D\u8D56\u56FE",
1194
+ "render.section.reinstall": "\u91CD\u88C5\u4F30\u7B97",
1195
+ "render.section.top": "\u524D {n} \u5927\u5C0F",
1196
+ "render.section.longTail": "\u957F\u5C3E",
1197
+ "render.section.dedup": "\u53BB\u91CD\u5EFA\u8BAE",
1198
+ "render.section.baseline": "\u57FA\u7EBF\u5BF9\u6BD4",
1199
+ "render.section.audit": "\u4F9D\u8D56\u5BA1\u8BA1",
1172
1200
  "render.stats.title": "\u{1F4CA} nmh stats \u2014 {badges}",
1173
- "render.stats.dedupPotential": " \xB7 dedup potential detected",
1174
- "render.stats.totalSize": "Total size : {size} across {count} node_modules",
1175
- "render.stats.packages": "Packages : {instances} instances / {unique} unique (dup {dup}\xD7)",
1176
- "render.stats.directDeps": "Direct deps : {count} declared across the scanned projects",
1177
- "render.stats.waste": "Waste (dedupable) : {size} ({percent}% of package sizes)",
1178
- "render.stats.noLicenses": "no package manifests found \u2014 nothing to license",
1179
- "render.stats.copyleftProd": " \u26A0 copyleft di production dependencies",
1180
- "render.stats.copyleftOther": " (copyleft, bukan prod-dep)",
1181
- "render.stats.experimental": "(experimental)",
1182
- "render.stats.grade": "grade",
1183
- "render.stats.wasteLabel": "waste",
1184
- "render.stats.dupLabel": "dup factor",
1185
- "render.stats.deadLabel": "dead",
1186
- "render.stats.deadNotAudited": "(tidak diaudit \u2014 tambahkan --dead untuk daftar)",
1187
- "render.stats.sizeLabel": "size",
1188
- "render.stats.co2Storage": "estimasi kasar, bukan audit karbon \u2014 simpan setahun",
1189
- "render.stats.co2Transfer": "kalau men-download ulang semuanya sekali",
1190
- "render.stats.deprecatedNone": "tidak ada paket deprecated \u2600\uFE0F",
1191
- "render.stats.deprecatedCount": "{count} instance deprecated:",
1192
- "render.stats.moreDeprecations": "\u2026dan {n} lainnya",
1193
- "render.stats.lockfileGrade": "(lockfile-grade)",
1194
- "render.stats.graphSuffix": "lockfile-grade \u2014 sisanya manifest-grade",
1195
- "render.stats.graphRoot": "root direct : {declared} declared \u2192 {nodes} tree nodes via {edges} edges",
1196
- "render.stats.graphNoDepth": "tidak ada kedalaman yang bisa dilacak dari root \u2014 bisa jadi lockfile ini v1/pecah",
1197
- "render.stats.graphUnreachable": "+ {n} node(s) unreachable from the root (optional/peer pruning)",
1198
- "render.stats.noLockfile": "no usable lockfile \u2014 manifest-grade",
1199
- "render.stats.reinstallNaive": "(naif)",
1200
- "render.stats.reinstallLine": "pasang ulang semuanya sekali : ~{duration}",
1201
- "render.stats.copies": "\xD7{n} copies",
1202
- "render.stats.oneCopy": "\xD71 copy",
1203
- "render.stats.dedupSaving": " \u2190 dedup bisa hemat {size}",
1204
- "render.stats.longTail": "\u2026 plus {names} more package name(s) \xB7 {instances} instances \xB7 {size}",
1205
- "render.stats.bisaHemat": " bisa hemat",
1206
- "render.stats.declaredRange": "{project} declared {range} ({field})",
1207
- "render.stats.transitive": "transitive (tidak dideklarasi di manifest)",
1208
- "render.global.title": "\u{1F310} nmh stats \u2014 global installation analysis",
1209
- "render.global.readonly": "(\u26A0\uFE0F global mode \u2014 read-only; needs access to the PM prefixes \u2014 sudo is never auto-applied)",
1210
- "render.global.pmDetected": "PM detected : {pms}{skipped}",
1211
- "render.global.total": "Total global : {count} packages \u2014 {size}",
1212
- "render.global.dead": "\u26A0 dead globals in {pm}: {count} (broken/missing bin symlink)",
1213
- "render.global.more": " \u2026 plus {n} more",
1214
- "render.global.crossDup": "\u26A0 Cross-PM duplicates : {count} package(s) (~{size} could be saved \u2014 uninstall one of them)",
1215
- "render.global.unreadable": "\u26A0 {count} unreadable location(s) \u2014 exit code 4",
1216
- "render.global.notFound": " (not found: {list})",
1217
- "render.global.multiPm": " \u2190 in more than one PM",
1218
- "render.global.head.package": "Package",
1219
- "render.global.head.version": "Version",
1220
- "render.baseline.saved": "Baseline : '{name}' saved {date}",
1221
- "render.baseline.totalSize": "Total size : {delta}{pct} \u2014 was {before}, now {after}",
1222
- "render.baseline.packages": "Packages : {delta}",
1223
- "render.baseline.headBefore": "Before",
1224
- "render.baseline.headNow": "Now",
1201
+ "render.stats.dedupPotential": " \xB7 \u68C0\u6D4B\u5230\u53BB\u91CD\u6F5C\u529B",
1202
+ "render.stats.totalSize": "\u603B\u5927\u5C0F : {size} \u2014 {count} \u4E2A node_modules",
1203
+ "render.stats.packages": "\u5305 : {instances} \u4E2A\u5B9E\u4F8B / {unique} \u4E2A\u552F\u4E00\uFF08\u91CD\u590D {dup}\xD7\uFF09",
1204
+ "render.stats.directDeps": "\u76F4\u63A5\u4F9D\u8D56 : \u626B\u63CF\u7684\u9879\u76EE\u5171\u58F0\u660E {count} \u4E2A",
1205
+ "render.stats.waste": "\u6D6A\u8D39\uFF08\u53EF\u53BB\u91CD\uFF09 : {size}\uFF08\u5360\u5305\u4F53\u79EF\u7684 {percent}%\uFF09",
1206
+ "render.stats.noLicenses": "\u672A\u627E\u5230\u5305 manifest \u2014 \u6CA1\u6709\u8BB8\u53EF\u8BC1\u53EF\u7EDF\u8BA1",
1207
+ "render.stats.copyleftProd": " \u26A0 \u751F\u4EA7\u4F9D\u8D56\u4E2D\u5B58\u5728 copyleft \u8BB8\u53EF\u8BC1",
1208
+ "render.stats.copyleftOther": " \uFF08copyleft\uFF0C\u975E\u751F\u4EA7\u4F9D\u8D56\uFF09",
1209
+ "render.stats.experimental": "\uFF08\u5B9E\u9A8C\u6027\uFF09",
1210
+ "render.stats.grade": "\u7B49\u7EA7",
1211
+ "render.stats.wasteLabel": "\u6D6A\u8D39",
1212
+ "render.stats.dupLabel": "\u91CD\u590D\u7387",
1213
+ "render.stats.deadLabel": "\u6B7B\u4EE3\u7801",
1214
+ "render.stats.deadNotAudited": "\uFF08\u672A\u5BA1\u8BA1 \u2014 \u52A0 --dead \u67E5\u770B\u5217\u8868\uFF09",
1215
+ "render.stats.sizeLabel": "\u5927\u5C0F",
1216
+ "render.stats.co2Storage": "\u7C97\u7565\u4F30\u7B97\uFF0C\u5E76\u975E\u78B3\u5BA1\u8BA1 \u2014 \u4E00\u5E74\u7684\u5B58\u50A8",
1217
+ "render.stats.co2Transfer": "\u76F8\u5F53\u4E8E\u628A\u6240\u6709\u5185\u5BB9\u91CD\u65B0\u4E0B\u8F7D\u4E00\u6B21",
1218
+ "render.stats.deprecatedNone": "\u6CA1\u6709\u5DF2\u5F03\u7528\u7684\u5305 \u2600\uFE0F",
1219
+ "render.stats.deprecatedCount": "{count} \u4E2A\u5DF2\u5F03\u7528\u7684\u5B9E\u4F8B\uFF1A",
1220
+ "render.stats.moreDeprecations": "\u2026\u53E6\u6709 {n} \u4E2A",
1221
+ "render.stats.lockfileGrade": "\uFF08lockfile \u7EA7\uFF09",
1222
+ "render.stats.graphSuffix": "lockfile \u7EA7 \u2014 \u5176\u4F59\u4E3A manifest \u7EA7",
1223
+ "render.stats.graphRoot": "\u6839\u76F4\u63A5\u4F9D\u8D56 : {declared} \u4E2A\u58F0\u660E \u2192 {nodes} \u4E2A\u6811\u8282\u70B9 / {edges} \u6761\u8FB9",
1224
+ "render.stats.graphNoDepth": "\u6CA1\u6709\u53EF\u4ECE\u6839\u8FFD\u8E2A\u7684\u6DF1\u5EA6 \u2014 \u8BE5 lockfile \u53EF\u80FD\u662F v1/\u5DF2\u635F\u574F",
1225
+ "render.stats.graphUnreachable": "+ {n} \u4E2A\u8282\u70B9\u4ECE\u6839\u4E0D\u53EF\u8FBE\uFF08optional/peer \u88AB\u526A\u679D\uFF09",
1226
+ "render.stats.noLockfile": "\u6CA1\u6709\u53EF\u7528\u7684 lockfile \u2014 manifest \u7EA7",
1227
+ "render.stats.reinstallNaive": "\uFF08\u7C97\u7565\uFF09",
1228
+ "render.stats.reinstallLine": "\u5168\u90E8\u91CD\u88C5\u4E00\u6B21 : \u7EA6 {duration}",
1229
+ "render.stats.copies": "\xD7{n} \u4EFD",
1230
+ "render.stats.oneCopy": "\xD71 \u4EFD",
1231
+ "render.stats.dedupSaving": " \u2190 \u53BB\u91CD\u53EF\u8282\u7701 {size}",
1232
+ "render.stats.longTail": "\u2026 \u53E6\u6709 {names} \u4E2A\u5305\u540D \xB7 {instances} \u4E2A\u5B9E\u4F8B \xB7 {size}",
1233
+ "render.stats.bisaHemat": " \u53EF\u8282\u7701",
1234
+ "render.stats.declaredRange": "{project} \u58F0\u660E\u4E86 {range}\uFF08{field}\uFF09",
1235
+ "render.stats.transitive": "\u4F20\u9012\u4F9D\u8D56\uFF08\u672A\u5728 manifest \u4E2D\u58F0\u660E\uFF09",
1236
+ "render.global.title": "\u{1F310} nmh stats \u2014 \u5168\u5C40\u5B89\u88C5\u5206\u6790",
1237
+ "render.global.readonly": "\uFF08\u26A0\uFE0F \u5168\u5C40\u6A21\u5F0F \u2014 \u53EA\u8BFB\uFF1B\u9700\u8981\u8BBF\u95EE\u5305\u7BA1\u7406\u5668\u524D\u7F00 \u2014 \u7EDD\u4E0D\u81EA\u52A8\u4F7F\u7528 sudo\uFF09",
1238
+ "render.global.pmDetected": "\u68C0\u6D4B\u5230 PM : {pms}{skipped}",
1239
+ "render.global.total": "\u5168\u5C40\u603B\u8BA1 : {count} \u4E2A\u5305 \u2014 {size}",
1240
+ "render.global.dead": "\u26A0 {pm} \u4E2D\u5931\u6548\u7684\u5168\u5C40\u5305\uFF1A{count} \u4E2A\uFF08bin \u7B26\u53F7\u94FE\u63A5\u635F\u574F/\u7F3A\u5931\uFF09",
1241
+ "render.global.more": " \u2026 \u53E6\u6709 {n} \u9879",
1242
+ "render.global.crossDup": "\u26A0 \u8DE8 PM \u91CD\u590D : {count} \u4E2A\u5305\uFF08\u7EA6\u53EF\u8282\u7701 {size} \u2014 \u5378\u8F7D\u5176\u4E2D\u4E00\u4E2A\u5373\u53EF\uFF09",
1243
+ "render.global.unreadable": "\u26A0 {count} \u4E2A\u4F4D\u7F6E\u65E0\u6CD5\u8BFB\u53D6 \u2014 \u9000\u51FA\u7801 4",
1244
+ "render.global.notFound": " \uFF08\u672A\u627E\u5230\uFF1A{list}\uFF09",
1245
+ "render.global.multiPm": " \u2190 \u5B58\u5728\u4E8E\u591A\u4E2A PM",
1246
+ "render.global.head.package": "\u5305",
1247
+ "render.global.head.version": "\u7248\u672C",
1248
+ "render.baseline.saved": "\u57FA\u7EBF \uFF1A'{name}' \u4FDD\u5B58\u4E8E {date}",
1249
+ "render.baseline.totalSize": "\u603B\u5927\u5C0F : {delta}{pct} \u2014 \u4E4B\u524D {before}\uFF0C\u73B0\u5728 {after}",
1250
+ "render.baseline.packages": "\u5305\u6570\u91CF : {delta}",
1251
+ "render.baseline.headBefore": "\u4E4B\u524D",
1252
+ "render.baseline.headNow": "\u73B0\u5728",
1225
1253
  "render.baseline.headDelta": "\u0394",
1226
- "render.baseline.new": "new",
1227
- "render.baseline.gone": "gone",
1228
- "render.baseline.moreChanged": "\u2026 plus {n} more changed path(s)",
1229
- "render.baseline.movers": "Package movers :",
1230
- "render.baseline.bloatGrowth": "\u{1F6A8} bloat growth detected \u2014 node_modules grew by more than 30% since the baseline",
1231
- "render.baselineHistory.title": "\u2696 nmh baselines \u2014 {count} saved",
1232
- "render.baselineHistory.saveHint": "save one with: nmh stats --save-baseline <name>",
1233
- "render.baselineHistory.head.name": "Name",
1234
- "render.baselineHistory.head.saved": "Saved",
1254
+ "render.baseline.new": "\u65B0\u589E",
1255
+ "render.baseline.gone": "\u6D88\u5931",
1256
+ "render.baseline.moreChanged": "\u2026 \u53E6\u6709 {n} \u4E2A\u53D8\u66F4\u8DEF\u5F84",
1257
+ "render.baseline.movers": "\u5305\u53D8\u52A8 :",
1258
+ "render.baseline.bloatGrowth": "\u{1F6A8} \u68C0\u6D4B\u5230\u81C3\u80BF\u589E\u957F \u2014 node_modules \u8F83\u57FA\u7EBF\u589E\u957F\u4E86 30% \u4EE5\u4E0A",
1259
+ "render.baselineHistory.title": "\u2696 nmh \u57FA\u7EBF \u2014 \u5DF2\u4FDD\u5B58 {count} \u6761",
1260
+ "render.baselineHistory.saveHint": "\u4FDD\u5B58\u57FA\u7EBF\uFF1Anmh stats --save-baseline <name>",
1261
+ "render.baselineHistory.head.name": "\u540D\u79F0",
1262
+ "render.baselineHistory.head.saved": "\u4FDD\u5B58\u65F6\u95F4",
1235
1263
  "render.baselineHistory.head.modules": "Node_modules",
1236
- "render.baselineHistory.head.where": "Where",
1237
- "render.baselineHistory.thisDir": " \xB7 this dir",
1238
- "render.why.title": "\u{1F50D} why '{pkg}' \u2014 {count} instance(s)",
1239
- "render.why.linked": "linked",
1240
- "render.why.declares": " project : {project} declares {range} ({field})",
1241
- "render.why.noName": "(manifest tanpa nama)",
1242
- "render.why.transitive": " project : transitive \u2014 tidak dideklarasi di manifest manapun",
1243
- "render.why.requiredBy": " required by : {count} package(s)",
1244
- "render.why.moreRequirers": " \u2026 plus {n} more requirer(s)",
1245
- "render.why.rootOnly": " required by : no package in the lockfile graph depends on it (root-only copy?)",
1246
- "render.why.orphan": " required by : no package manifest names it \u2014 orphan copy",
1247
- "render.audit.disclaimer": "\xB7 best-effort regex scan \u2014 {count} source file(s) (real graph: nmh stats --graph)",
1248
- "render.audit.clean": "\u2713 no phantom imports and no dead declarations detected",
1249
- "render.audit.phantom": "\u{1F9DF} phantom imports \u2014 imported in code, declared nowhere ({count})",
1250
- "render.audit.dead": "\u{1FAA6} dead declarations \u2014 installed + declared, never imported ({count})",
1264
+ "render.baselineHistory.head.where": "\u4F4D\u7F6E",
1265
+ "render.baselineHistory.thisDir": " \xB7 \u5F53\u524D\u76EE\u5F55",
1266
+ "render.why.title": "\u{1F50D} why '{pkg}' \u2014 {count} \u4E2A\u5B9E\u4F8B",
1267
+ "render.why.linked": "\u5DF2\u94FE\u63A5",
1268
+ "render.why.declares": " \u9879\u76EE : {project} \u58F0\u660E\u4E86 {range}\uFF08{field}\uFF09",
1269
+ "render.why.noName": "\uFF08\u65E0\u540D\u79F0\u7684 manifest\uFF09",
1270
+ "render.why.transitive": " \u9879\u76EE : \u4F20\u9012\u4F9D\u8D56 \u2014 \u672A\u5728\u4EFB\u4F55 manifest \u4E2D\u58F0\u660E",
1271
+ "render.why.requiredBy": " \u88AB\u4F9D\u8D56 : {count} \u4E2A\u5305",
1272
+ "render.why.moreRequirers": " \u2026 \u53E6\u6709 {n} \u4E2A\u4F9D\u8D56\u65B9",
1273
+ "render.why.rootOnly": " \u88AB\u4F9D\u8D56 : lockfile \u56FE\u4E2D\u6CA1\u6709\u4EFB\u4F55\u5305\u4F9D\u8D56\u5B83\uFF08\u4EC5\u6839\u76EE\u5F55\u7684\u526F\u672C\uFF1F\uFF09",
1274
+ "render.why.orphan": " \u88AB\u4F9D\u8D56 : \u6CA1\u6709 manifest \u63D0\u53CA\u5B83 \u2014 \u5B64\u513F\u526F\u672C",
1275
+ "render.audit.disclaimer": "\xB7 \u5C3D\u529B\u800C\u4E3A\u7684\u6B63\u5219\u626B\u63CF \u2014 {count} \u4E2A\u6E90\u6587\u4EF6\uFF08\u771F\u5B9E\u4F9D\u8D56\u56FE\uFF1Anmh stats --graph\uFF09",
1276
+ "render.audit.clean": "\u2713 \u672A\u53D1\u73B0\u5E7D\u7075\u5BFC\u5165\u548C\u6B7B\u58F0\u660E",
1277
+ "render.audit.phantom": "\u{1F9DF} \u5E7D\u7075\u5BFC\u5165 \u2014 \u4EE3\u7801\u4E2D\u5BFC\u5165\u4F46\u672A\u5728\u4EFB\u4F55\u5730\u65B9\u58F0\u660E\uFF08{count}\uFF09",
1278
+ "render.audit.dead": "\u{1FAA6} \u6B7B\u58F0\u660E \u2014 \u5DF2\u5B89\u88C5\u4E14\u5DF2\u58F0\u660E\u4F46\u4ECE\u672A\u5BFC\u5165\uFF08{count}\uFF09",
1251
1279
  // ── utils: format / update-check / version ─────────────────────────────
1252
- "format.now": "now",
1253
- "format.ago": "{n} ago",
1254
- "update.note": "update tersedia: {current} \u2192 {latest} \u2014 npm i -g node-modules-hunter (cek 24 jam sekali, opt-in via --update-check)",
1255
- "version.tagline": "hunt node_modules \u2014 scan \xB7 measure \xB7 clean safely",
1256
- "version.yes": "yes",
1257
- "version.no": "no",
1280
+ "format.now": "\u521A\u521A",
1281
+ "format.ago": "{n} \u524D",
1282
+ "update.note": "\u6709\u66F4\u65B0\u53EF\u7528\uFF1A{current} \u2192 {latest} \u2014 npm i -g node-modules-hunter\uFF08\u6BCF 24 \u5C0F\u65F6\u68C0\u67E5\u4E00\u6B21\uFF0C\u9700\u901A\u8FC7 --update-check \u5F00\u542F\uFF09",
1283
+ "version.tagline": "\u730E\u6355 node_modules \u2014 \u626B\u63CF \xB7 \u5EA6\u91CF \xB7 \u5B89\u5168\u6E05\u7406",
1284
+ "version.yes": "\u662F",
1285
+ "version.no": "\u5426",
1258
1286
  // ── commands/scan.ts ────────────────────────────────────────────────────
1259
- "scan.warn.noMatch": "no match for pattern: {pattern}",
1260
- "scan.warn.unresolvable": "cannot resolve real path (symlink loop?): {path}",
1261
- "scan.detectedPms": "detected PMs: {pms}",
1262
- "scan.spin.measuring": "measuring {done}/{total} folders \xB7 {size}",
1263
- "scan.warn.none": "no node_modules found \u2014 nothing to hunt here \u{1F643}",
1287
+ "scan.warn.noMatch": "\u6CA1\u6709\u5339\u914D\u8BE5\u6A21\u5F0F\u7684\u9879\uFF1A{pattern}",
1288
+ "scan.warn.unresolvable": "\u65E0\u6CD5\u89E3\u6790\u771F\u5B9E\u8DEF\u5F84\uFF08\u7B26\u53F7\u94FE\u63A5\u5FAA\u73AF\uFF1F\uFF09\uFF1A{path}",
1289
+ "scan.detectedPms": "\u68C0\u6D4B\u5230\u7684 PM\uFF1A{pms}",
1290
+ "scan.spin.measuring": "\u6B63\u5728\u6D4B\u91CF {done}/{total} \u4E2A\u6587\u4EF6\u5939 \xB7 {size}",
1291
+ "scan.warn.none": "\u672A\u627E\u5230 node_modules \u2014 \u8FD9\u91CC\u6CA1\u6709\u53EF\u730E\u7684 \u{1F643}",
1264
1292
  // ── commands/delete.ts + core/guards.ts ─────────────────────────────────
1265
- "delete.spin.progress": "\u{1F5D1} {done}/{total} folders\u2026",
1266
- "delete.note.trashFallback": "no OS trash backend (install gio or trash-cli) \u2014 fell back to the restorable nmh trash: {batch}",
1267
- "delete.note.trashBatch": "restorable nmh trash: {batch} (manifest: manifest.jsonl \u2014 restore by moving folders back)",
1268
- "delete.guard.unresolvable": "\u{1F6D1} {path} \u2014 refusing: cannot resolve real path (symlink loop?)",
1293
+ "delete.spin.progress": "\u{1F5D1} {done}/{total} \u4E2A\u6587\u4EF6\u5939\u2026",
1294
+ "delete.note.trashFallback": "\u6CA1\u6709\u7CFB\u7EDF\u56DE\u6536\u7AD9\u540E\u7AEF\uFF08\u8BF7\u5B89\u88C5 gio \u6216 trash-cli\uFF09\u2014 \u5DF2\u56DE\u9000\u5230\u53EF\u6062\u590D\u7684 nmh \u56DE\u6536\u7AD9\uFF1A{batch}",
1295
+ "delete.note.trashBatch": "\u53EF\u6062\u590D\u7684 nmh \u56DE\u6536\u7AD9\uFF1A{batch}\uFF08\u6E05\u5355\uFF1Amanifest.jsonl \u2014 \u628A\u6587\u4EF6\u5939\u79FB\u56DE\u53BB\u5373\u53EF\u6062\u590D\uFF09",
1296
+ "delete.guard.unresolvable": "\u{1F6D1} {path} \u2014 \u62D2\u7EDD\uFF1A\u65E0\u6CD5\u89E3\u6790\u771F\u5B9E\u8DEF\u5F84\uFF08\u7B26\u53F7\u94FE\u63A5\u5FAA\u73AF\uFF1F\uFF09",
1269
1297
  "delete.guard.blocked": "\u{1F6D1} {path} \u2014 {reason}",
1270
- "delete.guard.abort": "delete aborted \u2014 safety guard refused; nothing was deleted (exit 3)",
1271
- "delete.warn.unresolvableSkipped": "{n} unresolvable target(s) skipped",
1272
- "delete.warn.guardSkipped": "{n} target(s) skipped by safety guard \u2014 continuing with the safe ones",
1273
- "delete.warn.jsonNeedsYes": "--json deletes require an explicit --yes (or --force) \u2014 there is no interactive confirm inside --json; nothing was deleted",
1274
- "delete.warn.nonInteractive": "non-interactive shell \u2014 nothing deleted without --yes (tip: --dry-run previews first)",
1275
- "delete.cancelled": "cancelled \u2014 nothing deleted",
1276
- "delete.select.mode": "Deletion mode:",
1277
- "delete.select.trash": "trash \u2014 move to OS bin (safe, restorable) \xB7 recommended",
1278
- "delete.select.hard": "hard \u2014 delete permanently \xB7 no undo",
1279
- "delete.confirm.hard": "Delete {count} folder(s) \u2014 {size} \u2014 PERMANENTLY (no undo)?",
1280
- "delete.confirm.trash": "Move {count} folder(s) \u2014 {size} \u2014 to the OS trash?",
1281
- "render.plan.notExecuted": "[NOT EXECUTED] Would {label} {count} folder(s) ({size}):",
1282
- "guard.reason.notFound": "path does not exist",
1283
- "guard.reason.notDirectory": "not a directory",
1284
- "guard.reason.symlinkLoop": "cannot resolve real path (symlink loop?)",
1285
- "guard.reason.name": "refusing: folder is not named node_modules ({name})",
1286
- "guard.reason.root": "refusing: target is a filesystem root",
1287
- "guard.reason.home": "refusing: target is the user home directory",
1288
- "guard.reason.rootParent": "refusing: node_modules directly inside the filesystem root",
1289
- "guard.reason.homeParent": "refusing: node_modules directly inside the home directory",
1290
- "guard.reason.unsafe": "unsafe target",
1298
+ "delete.guard.abort": "\u5220\u9664\u5DF2\u4E2D\u6B62 \u2014 \u5B89\u5168\u62A4\u680F\u62D2\u7EDD\uFF1B\u672A\u5220\u9664\u4EFB\u4F55\u5185\u5BB9\uFF08\u9000\u51FA\u7801 3\uFF09",
1299
+ "delete.warn.unresolvableSkipped": "\u5DF2\u8DF3\u8FC7 {n} \u4E2A\u65E0\u6CD5\u89E3\u6790\u7684\u76EE\u6807",
1300
+ "delete.warn.guardSkipped": "\u5B89\u5168\u62A4\u680F\u8DF3\u8FC7\u4E86 {n} \u4E2A\u76EE\u6807 \u2014 \u7EE7\u7EED\u5904\u7406\u5B89\u5168\u7684\u76EE\u6807",
1301
+ "delete.warn.jsonNeedsYes": "--json \u5220\u9664\u9700\u8981\u663E\u5F0F\u7684 --yes\uFF08\u6216 --force\uFF09\u2014 --json \u5185\u6CA1\u6709\u4EA4\u4E92\u786E\u8BA4\uFF1B\u672A\u5220\u9664\u4EFB\u4F55\u5185\u5BB9",
1302
+ "delete.warn.nonInteractive": "\u975E\u4EA4\u4E92\u5F0F shell \u2014 \u6CA1\u6709 --yes \u4E0D\u4F1A\u5220\u9664\u4EFB\u4F55\u5185\u5BB9\uFF08\u63D0\u793A\uFF1A\u5148\u7528 --dry-run \u9884\u89C8\uFF09",
1303
+ "delete.cancelled": "\u5DF2\u53D6\u6D88 \u2014 \u672A\u5220\u9664\u4EFB\u4F55\u5185\u5BB9",
1304
+ "delete.select.mode": "\u5220\u9664\u65B9\u5F0F\uFF1A",
1305
+ "delete.select.trash": "\u56DE\u6536\u7AD9 \u2014 \u79FB\u5165\u7CFB\u7EDF\u56DE\u6536\u7AD9\uFF08\u5B89\u5168\uFF0C\u53EF\u6062\u590D\uFF09\xB7 \u63A8\u8350",
1306
+ "delete.select.hard": "\u5F7B\u5E95\u5220\u9664 \u2014 \u6C38\u4E45\u5220\u9664 \xB7 \u4E0D\u53EF\u64A4\u9500",
1307
+ "delete.confirm.hard": "\u6C38\u4E45\u5220\u9664\uFF08\u4E0D\u53EF\u64A4\u9500\uFF09{count} \u4E2A\u6587\u4EF6\u5939 \u2014 {size}\uFF1F",
1308
+ "delete.confirm.trash": "\u628A {count} \u4E2A\u6587\u4EF6\u5939 \u2014 {size} \u2014 \u79FB\u5165\u7CFB\u7EDF\u56DE\u6536\u7AD9\uFF1F",
1309
+ "render.plan.notExecuted": "[\u672A\u6267\u884C] \u5C06{label} {count} \u4E2A\u6587\u4EF6\u5939\uFF08{size}\uFF09\uFF1A",
1310
+ "guard.reason.notFound": "\u8DEF\u5F84\u4E0D\u5B58\u5728",
1311
+ "guard.reason.notDirectory": "\u4E0D\u662F\u76EE\u5F55",
1312
+ "guard.reason.symlinkLoop": "\u65E0\u6CD5\u89E3\u6790\u771F\u5B9E\u8DEF\u5F84\uFF08\u7B26\u53F7\u94FE\u63A5\u5FAA\u73AF\uFF1F\uFF09",
1313
+ "guard.reason.name": "\u62D2\u7EDD\uFF1A\u6587\u4EF6\u5939\u4E0D\u53EB node_modules\uFF08{name}\uFF09",
1314
+ "guard.reason.root": "\u62D2\u7EDD\uFF1A\u76EE\u6807\u662F\u6587\u4EF6\u7CFB\u7EDF\u6839\u76EE\u5F55",
1315
+ "guard.reason.home": "\u62D2\u7EDD\uFF1A\u76EE\u6807\u662F\u7528\u6237\u4E3B\u76EE\u5F55",
1316
+ "guard.reason.rootParent": "\u62D2\u7EDD\uFF1Anode_modules \u76F4\u63A5\u4F4D\u4E8E\u6587\u4EF6\u7CFB\u7EDF\u6839\u76EE\u5F55\u4E0B",
1317
+ "guard.reason.homeParent": "\u62D2\u7EDD\uFF1Anode_modules \u76F4\u63A5\u4F4D\u4E8E\u4E3B\u76EE\u5F55\u4E0B",
1318
+ "guard.reason.unsafe": "\u4E0D\u5B89\u5168\u7684\u76EE\u6807",
1291
1319
  // ── commands/wizard.ts ──────────────────────────────────────────────────
1292
- "wizard.warn.climbed": "no node_modules within 3 levels of cwd \u2014 scoped to the project root above: {root}",
1293
- "wizard.warn.noneHere": "no node_modules found in this folder",
1294
- "wizard.warn.scouted": "project ancestors were scouted too (\u22648 hops up) \u2014 no node_modules anywhere",
1295
- "wizard.warn.needsTty": "the interactive wizard needs a TTY \u2014 this was a plain read-only scan; every menu action exists as a command: see nmh --help",
1296
- "wizard.info.scopedUp": "cwd has no node_modules in 3 levels \u2014 scoped up to the project root {root}",
1297
- "wizard.outro.nothingFound": "nothing found \u{1F643}",
1298
- "wizard.menu.message": "{count} node_modules found in this tree \u2014 {size} \xB7 next move?",
1299
- "wizard.menu.deleteAll": "\u{1F5D1}\uFE0F Delete everything found (guards, mode & confirm included)",
1300
- "wizard.menu.pick": "\u2611\uFE0F Pick manually \u2014 checkboxes (space to select)",
1301
- "wizard.menu.search": "\u{1F50D} Search installed packages by pattern",
1302
- "wizard.menu.map": "\u{1F5FA}\uFE0F Map dependencies \u2014 project \u2192 PM \u2192 declared deps",
1303
- "wizard.menu.stats": "\u{1F4CA} Detailed report \u2014 the full stats read-out",
1304
- "wizard.menu.settings": "\u2699\uFE0F Settings & integration (read-only view)",
1305
- "wizard.menu.quit": "\u23F9 Exit nmh",
1306
- "wizard.outro.bye": "bye \u{1F44B} \u2014 nothing deleted",
1307
- "wizard.search.message": "Search installed packages \u2014 which pattern?",
1308
- "wizard.search.validate": "give a pattern \u2014 substring, glob, or /regex/",
1309
- "wizard.search.skipped": "search skipped \u2014 back to the menu",
1310
- "wizard.guard.blocked": "\u{1F6D1} {path} \u2014 {reason} (excluded from wizard)",
1311
- "wizard.outro.nothingSafe": "nothing safe to select \u2014 done",
1312
- "wizard.pick.message": "{count} node_modules \u2014 {size} found \xB7 space to select, enter to continue",
1313
- "wizard.outro.nothingSelected": "nothing selected \u2014 bye \u{1F44B}",
1314
- "wizard.outro.failures": "{icon} done with {n} failure(s) \u2014 freed {size}",
1315
- "wizard.outro.freed": "{icon} Freed: {size} from {count} folder(s)",
1316
- "wizard.mode.message": "How should these die?",
1317
- "wizard.mode.trash": "Move to OS trash \u2014 safe & restorable (recommended)",
1318
- "wizard.mode.hard": "Delete permanently \u2014 there is no undo",
1319
- "wizard.settings.title": "\u2699 settings & integration",
1320
- "wizard.settings.none": "(none)",
1320
+ "wizard.warn.climbed": "cwd \u7684 3 \u5C42\u5185\u6CA1\u6709 node_modules \u2014 \u5DF2\u6536\u7A84\u5230\u4E0A\u9762\u7684\u9879\u76EE\u6839\uFF1A{root}",
1321
+ "wizard.warn.noneHere": "\u6B64\u6587\u4EF6\u5939\u4E2D\u672A\u627E\u5230 node_modules",
1322
+ "wizard.warn.scouted": "\u4E0A\u5C42\u9879\u76EE\u76EE\u5F55\u4E5F\u4FA6\u5BDF\u8FC7\u4E86\uFF08\u5411\u4E0A \u22648 \u8DF3\uFF09\u2014 \u5230\u5904\u90FD\u6CA1\u6709 node_modules",
1323
+ "wizard.warn.needsTty": "\u4EA4\u4E92\u5F0F\u5411\u5BFC\u9700\u8981 TTY \u2014 \u521A\u624D\u53EA\u662F\u4E00\u6B21\u53EA\u8BFB\u626B\u63CF\uFF1B\u6BCF\u4E2A\u83DC\u5355\u64CD\u4F5C\u90FD\u6709\u5BF9\u5E94\u7684\u547D\u4EE4\uFF1A\u89C1 nmh --help",
1324
+ "wizard.info.scopedUp": "cwd \u7684 3 \u5C42\u5185\u6CA1\u6709 node_modules \u2014 \u5DF2\u6536\u7A84\u5230\u9879\u76EE\u6839 {root}",
1325
+ "wizard.outro.nothingFound": "\u4E00\u65E0\u6240\u83B7 \u{1F643}",
1326
+ "wizard.menu.message": "\u6B64\u76EE\u5F55\u6811\u4E2D\u53D1\u73B0 {count} \u4E2A node_modules \u2014 {size} \xB7 \u4E0B\u4E00\u6B65\uFF1F",
1327
+ "wizard.menu.deleteAll": "\u{1F5D1}\uFE0F \u5220\u9664\u5168\u90E8\u53D1\u73B0\u9879\uFF08\u542B\u62A4\u680F\u3001\u65B9\u5F0F\u4E0E\u786E\u8BA4\uFF09",
1328
+ "wizard.menu.pick": "\u2611\uFE0F \u624B\u52A8\u6311\u9009 \u2014 \u590D\u9009\u6846\uFF08\u7A7A\u683C\u9009\u4E2D\uFF09",
1329
+ "wizard.menu.search": "\u{1F50D} \u6309\u6A21\u5F0F\u641C\u7D22\u5DF2\u5B89\u88C5\u7684\u5305",
1330
+ "wizard.menu.map": "\u{1F5FA}\uFE0F \u6620\u5C04\u4F9D\u8D56 \u2014 \u9879\u76EE \u2192 PM \u2192 \u58F0\u660E\u7684\u4F9D\u8D56",
1331
+ "wizard.menu.stats": "\u{1F4CA} \u8BE6\u7EC6\u62A5\u544A \u2014 \u5B8C\u6574\u7684 stats \u8F93\u51FA",
1332
+ "wizard.menu.settings": "\u2699\uFE0F \u8BBE\u7F6E\u4E0E\u96C6\u6210\uFF08\u53EA\u8BFB\u89C6\u56FE\uFF09",
1333
+ "wizard.menu.update": "\u{1F501} \u66F4\u65B0 nmh\uFF08\u67E5\u8BE2 registry\uFF0C\u5148\u8BE2\u95EE\uFF09",
1334
+ "wizard.menu.quit": "\u23F9 \u9000\u51FA nmh",
1335
+ "wizard.outro.bye": "\u518D\u89C1 \u{1F44B} \u2014 \u672A\u5220\u9664\u4EFB\u4F55\u5185\u5BB9",
1336
+ "wizard.search.message": "\u641C\u7D22\u5DF2\u5B89\u88C5\u7684\u5305 \u2014 \u7528\u4EC0\u4E48\u6A21\u5F0F\uFF1F",
1337
+ "wizard.search.validate": "\u8BF7\u7ED9\u4E00\u4E2A\u6A21\u5F0F \u2014 \u5B50\u4E32\u3001glob \u6216 /regex/",
1338
+ "wizard.search.skipped": "\u5DF2\u8DF3\u8FC7\u641C\u7D22 \u2014 \u8FD4\u56DE\u83DC\u5355",
1339
+ "wizard.guard.blocked": "\u{1F6D1} {path} \u2014 {reason}\uFF08\u5DF2\u4ECE\u5411\u5BFC\u6392\u9664\uFF09",
1340
+ "wizard.outro.nothingSafe": "\u6CA1\u6709\u53EF\u5B89\u5168\u9009\u4E2D\u7684\u76EE\u6807 \u2014 \u5B8C\u6210",
1341
+ "wizard.pick.message": "\u627E\u5230 {count} \u4E2A node_modules \u2014 {size} \xB7 \u7A7A\u683C\u9009\u4E2D\uFF0C\u56DE\u8F66\u7EE7\u7EED",
1342
+ "wizard.outro.nothingSelected": "\u672A\u9009\u4E2D\u4EFB\u4F55\u9879 \u2014 \u518D\u89C1 \u{1F44B}",
1343
+ "wizard.outro.failures": "{icon} \u5B8C\u6210\uFF0C{n} \u4E2A\u5931\u8D25 \u2014 \u91CA\u653E\u4E86 {size}",
1344
+ "wizard.outro.freed": "{icon} \u5DF2\u91CA\u653E\uFF1A{count} \u4E2A\u6587\u4EF6\u5939\u4E2D\u7684 {size}",
1345
+ "wizard.mode.message": "\u8FD9\u4E9B\u8981\u600E\u4E48\u5904\u7F6E\uFF1F",
1346
+ "wizard.mode.trash": "\u79FB\u5165\u7CFB\u7EDF\u56DE\u6536\u7AD9 \u2014 \u5B89\u5168\u4E14\u53EF\u6062\u590D\uFF08\u63A8\u8350\uFF09",
1347
+ "wizard.mode.hard": "\u6C38\u4E45\u5220\u9664 \u2014 \u4E0D\u53EF\u64A4\u9500",
1348
+ "wizard.settings.title": "\u2699 \u8BBE\u7F6E\u4E0E\u96C6\u6210",
1349
+ "wizard.settings.none": "\uFF08\u65E0\uFF09",
1321
1350
  "wizard.settings.list": "{n}: {list}",
1322
- "wizard.settings.cwdClimbed": "{from} \u2192 scoped up to {root}",
1323
- "wizard.settings.noConfig": "none found (.nmhrc in cwd \u2192 home)",
1324
- "wizard.settings.defaultMode": "trash (wizard keeps it safe by default)",
1325
- "wizard.settings.depth": "default 3 here \u2014 flag --depth <n> overrides",
1326
- "wizard.settings.auto": "auto (TTY on)",
1327
- "wizard.settings.updateCheckOff": "off \u2014 opt-in via --update-check",
1328
- "wizard.settings.logDir": "~/.nmh (delete receipts)",
1329
- "wizard.settings.changeHint": "change with nmh config (set\xB7add\xB7remove\xB7unset) or .nmhrc \u2014 README \xA710 \xB7",
1330
- "wizard.settings.commandsHint": "this whole menu also exists as plain commands: nmh clean \xB7 nmh search <pattern> \xB7 nmh map \xB7 nmh stats",
1351
+ "wizard.settings.cwdClimbed": "{from} \u2192 \u5DF2\u6536\u7A84\u5230 {root}",
1352
+ "wizard.settings.noConfig": "\u672A\u627E\u5230\uFF08.nmhrc \u5728 cwd \u2192 home\uFF09",
1353
+ "wizard.settings.defaultMode": "\u56DE\u6536\u7AD9\uFF08\u5411\u5BFC\u9ED8\u8BA4\u4FDD\u8BC1\u5B89\u5168\uFF09",
1354
+ "wizard.settings.depth": "\u6B64\u5904\u9ED8\u8BA4 3 \u2014 \u53EF\u7528 --depth <n> \u8986\u76D6",
1355
+ "wizard.settings.auto": "auto\uFF08TTY \u65F6\u5F00\u542F\uFF09",
1356
+ "wizard.settings.updateCheckOff": "\u5173\u95ED \u2014 \u901A\u8FC7 --update-check \u5F00\u542F",
1357
+ "wizard.settings.logDir": "~/.nmh\uFF08\u5220\u9664\u56DE\u6267\uFF09",
1358
+ "wizard.settings.changeHint": "\u7528 nmh config\uFF08set\xB7add\xB7remove\xB7unset\uFF09\u6216 .nmhrc \u4FEE\u6539 \u2014 README \xA710 \xB7",
1359
+ "wizard.settings.commandsHint": "\u6574\u4E2A\u83DC\u5355\u4E5F\u90FD\u6709\u5BF9\u5E94\u7684\u666E\u901A\u547D\u4EE4\uFF1Anmh clean \xB7 nmh search <pattern> \xB7 nmh map \xB7 nmh stats",
1331
1360
  // ── commands/update.ts ──────────────────────────────────────────────────
1332
- "update.spin": "updating via npm\u2026",
1333
- "update.err.npmExit": "npm exited {code}",
1334
- "update.info.title": "nmh update \u2014 info registry (npm view node-modules-hunter)",
1335
- "update.info.installed": "installed {value}",
1336
- "update.info.latest": "latest {value}",
1337
- "update.info.update": "update {value}",
1338
- "update.info.available": "tersedia \u2014 jalankan `nmh update`",
1339
- "update.info.availableNonGlobal": " (atau: npm i -g node-modules-hunter)",
1340
- "update.info.none": "tidak ada \u2014 ini versi terbaru",
1341
- "update.info.summary": "summary {value}",
1342
- "update.info.tarball": "tarball {value}",
1343
- "update.info.sizeSuffix": " ({size}{files} files)",
1344
- "update.info.engines": "engines node {value}",
1345
- "update.info.license": "license {value}",
1346
- "update.info.published": "published {value}",
1347
- "update.err.noRegistry": "cannot read the latest version \u2014 is the registry reachable? (npm view node-modules-hunter version)",
1348
- "update.check.available": "\u2191 update tersedia: {current} \u2192 {latest} \u2014 jalankan `nmh update` untuk menginstall",
1349
- "update.check.latest": "\u2713 nmh {current} sudah versi terbaru (registry: {latest})",
1350
- "update.latestNoInstall": "\u2713 nmh {current} sudah versi terbaru (registry: {latest}) \u2014 tak ada yang diinstall",
1351
- "update.manual.title": "nmh {current} terpasang di luar npm global \u2014 update manual:",
1352
- "update.manual.command": " npm i -g node-modules-hunter (atau: pnpm add -g / bunx / brew upgrade node-modules-hunter)",
1353
- "update.err.needsAnswer": "update butuh jawaban eksplisit \u2014 -y untuk menginstall, -n untuk menolak (--check/--info untuk lihat saja)",
1354
- "update.confirm": "Update nmh {current} \u2192 {latest} via npm install -g?",
1355
- "update.declined": "\u2715 tetap nmh {current} \u2014 update ke {latest} tidak diinstall",
1356
- "update.err.failed": "\u26A0 update gagal: {detail}",
1357
- "update.err.manualHint": " coba manual: npm install -g node-modules-hunter@{latest}",
1358
- "update.done": "\u2713 terupdate {current} \u2192 {latest} (npm install -g node-modules-hunter)",
1361
+ "update.spin": "\u6B63\u5728\u901A\u8FC7 npm \u66F4\u65B0\u2026",
1362
+ "update.err.npmExit": "npm \u9000\u51FA\u7801 {code}",
1363
+ "update.info.title": "nmh update \u2014 registry \u4FE1\u606F\uFF08npm view node-modules-hunter\uFF09",
1364
+ "update.info.installed": "\u5DF2\u5B89\u88C5 {value}",
1365
+ "update.info.latest": "\u6700\u65B0\u7248 {value}",
1366
+ "update.info.update": "\u66F4\u65B0 {value}",
1367
+ "update.info.available": "\u53EF\u7528 \u2014 \u8BF7\u8FD0\u884C `nmh update`",
1368
+ "update.info.availableNonGlobal": "\uFF08\u6216\uFF1Anpm i -g node-modules-hunter\uFF09",
1369
+ "update.info.none": "\u65E0 \u2014 \u5DF2\u662F\u6700\u65B0\u7248\u672C",
1370
+ "update.info.summary": "\u6458\u8981 {value}",
1371
+ "update.info.tarball": "tarball {value}",
1372
+ "update.info.sizeSuffix": "\uFF08{size}\uFF0C{files} \u4E2A\u6587\u4EF6\uFF09",
1373
+ "update.info.engines": "engines node {value}",
1374
+ "update.info.license": "\u8BB8\u53EF\u8BC1 {value}",
1375
+ "update.info.published": "\u53D1\u5E03\u65F6\u95F4 {value}",
1376
+ "update.err.noRegistry": "\u65E0\u6CD5\u8BFB\u53D6\u6700\u65B0\u7248\u672C \u2014 registry \u53EF\u8FBE\u5417\uFF1F\uFF08npm view node-modules-hunter version\uFF09",
1377
+ "update.check.available": "\u2191 \u6709\u66F4\u65B0\u53EF\u7528\uFF1A{current} \u2192 {latest} \u2014 \u8FD0\u884C `nmh update` \u5B89\u88C5",
1378
+ "update.check.latest": "\u2713 nmh {current} \u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF08registry\uFF1A{latest}\uFF09",
1379
+ "update.latestNoInstall": "\u2713 nmh {current} \u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF08registry\uFF1A{latest}\uFF09\u2014 \u672A\u5B89\u88C5\u4EFB\u4F55\u5185\u5BB9",
1380
+ "update.manual.title": "nmh {current} \u5B89\u88C5\u5728 npm \u5168\u5C40\u4E4B\u5916 \u2014 \u8BF7\u624B\u52A8\u66F4\u65B0\uFF1A",
1381
+ "update.manual.command": " npm i -g node-modules-hunter (\u6216: pnpm add -g / bunx / brew upgrade node-modules-hunter)",
1382
+ "update.err.needsAnswer": "\u66F4\u65B0\u9700\u8981\u663E\u5F0F\u56DE\u7B54 \u2014 -y \u5B89\u88C5\uFF0C-n \u62D2\u7EDD\uFF08--check/--info \u4EC5\u67E5\u770B\uFF09",
1383
+ "update.confirm": "\u901A\u8FC7 npm install -g \u628A nmh \u4ECE {current} \u66F4\u65B0\u5230 {latest}\uFF1F",
1384
+ "update.declined": "\u2715 \u4FDD\u6301 nmh {current} \u2014 \u672A\u5B89\u88C5 {latest} \u7684\u66F4\u65B0",
1385
+ "update.err.failed": "\u26A0 \u66F4\u65B0\u5931\u8D25\uFF1A{detail}",
1386
+ "update.err.manualHint": " \u624B\u52A8\u5C1D\u8BD5\uFF1Anpm install -g node-modules-hunter@{latest}",
1387
+ "update.done": "\u2713 \u5DF2\u66F4\u65B0 {current} \u2192 {latest}\uFF08npm install -g node-modules-hunter\uFF09",
1388
+ "update.info.tags": "dist-tags {tags}",
1389
+ "update.check.onTag": "\uFF08dist-tag\uFF1A{tag}\uFF09",
1390
+ "update.confirm.downgrade": '\u5C06 nmh {current} \u964D\u7EA7\u5230 {target}\uFF08\u6765\u81EA dist-tag "{tag}"\uFF09\uFF1F',
1391
+ "update.err.tagUnknown": '\u672A\u627E\u5230 dist-tag "{tag}" \u2014 \u53EF\u7528\uFF1A{tags}',
1392
+ "update.err.invalidTag": 'dist-tag "{value}" \u65E0\u6548 \u2014 \u53EA\u80FD\u4F7F\u7528\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u8FDE\u5B57\u7B26\u3001\u4E0B\u5212\u7EBF',
1359
1393
  // ── commands/global.ts ──────────────────────────────────────────────────
1360
- "global.spin.probe": "probing global prefixes\u2026",
1361
- "global.spin.progress": "global {pm} \u2014 {done}/{total} packages",
1362
- "global.warn.none": "no global install roots found \u2014 nothing to analyze here \u{1F310}\u{1F643}",
1363
- "global.deadKind.broken": "broken bin symlink",
1364
- "global.deadKind.missing": "missing bin symlink",
1394
+ "global.spin.probe": "\u6B63\u5728\u63A2\u6D4B\u5168\u5C40\u524D\u7F00\u2026",
1395
+ "global.spin.progress": "\u5168\u5C40 {pm} \u2014 {done}/{total} \u4E2A\u5305",
1396
+ "global.warn.none": "\u672A\u627E\u5230\u5168\u5C40\u5B89\u88C5\u6839\u76EE\u5F55 \u2014 \u8FD9\u91CC\u6CA1\u6709\u53EF\u5206\u6790\u7684 \u{1F310}\u{1F643}",
1397
+ "global.deadKind.broken": "bin \u7B26\u53F7\u94FE\u63A5\u635F\u574F",
1398
+ "global.deadKind.missing": "bin \u7B26\u53F7\u94FE\u63A5\u7F3A\u5931",
1365
1399
  // ── commands/map / search / why / treemap ──────────────────────────────
1366
- "map.spin.progress": "mapping {done}/{total} projects\u2026",
1367
- "map.warn.none": "no node_modules found \u2014 nothing to map here \u{1F643}",
1368
- "map.warn.notDeclared": "no project declares '{pkg}' in its manifest \u{1F643}",
1369
- "search.spin.progress": "searching {done}/{total} node_modules\u2026",
1370
- "search.warn.noMatch": "no match for '{pattern}' in any scanned node_modules \u{1F643}",
1371
- "why.warn.none": "no instance of '{pkg}' in the scanned node_modules \u2014 nmh why <pkg> [dirs]",
1372
- "treemap.warn.none": "no node_modules found \u2014 nothing to draw here \u{1F643}",
1373
- "treemap.err.write": "\u{1F6D1} could not write the treemap file \u2192 {path} \u2014 {detail}",
1374
- "treemap.done": "\u{1F5FA}\uFE0F treemap \u2192 {path} \u2014 buka di browser, hover cell buat detail",
1400
+ "map.spin.progress": "\u6B63\u5728\u6620\u5C04 {done}/{total} \u4E2A\u9879\u76EE\u2026",
1401
+ "map.warn.none": "\u672A\u627E\u5230 node_modules \u2014 \u8FD9\u91CC\u6CA1\u6709\u53EF\u6620\u5C04\u7684 \u{1F643}",
1402
+ "map.warn.notDeclared": "\u6CA1\u6709\u9879\u76EE\u5728 manifest \u4E2D\u58F0\u660E '{pkg}' \u{1F643}",
1403
+ "search.spin.progress": "\u6B63\u5728\u641C\u7D22 {done}/{total} \u4E2A node_modules\u2026",
1404
+ "search.warn.noMatch": "\u6240\u6709\u626B\u63CF\u8FC7\u7684 node_modules \u4E2D\u90FD\u6CA1\u6709\u5339\u914D '{pattern}' \u{1F643}",
1405
+ "why.warn.none": "\u626B\u63CF\u7684 node_modules \u4E2D\u6CA1\u6709 '{pkg}' \u7684\u5B9E\u4F8B \u2014 nmh why <pkg> [dirs]",
1406
+ "treemap.warn.none": "\u672A\u627E\u5230 node_modules \u2014 \u8FD9\u91CC\u6CA1\u6709\u53EF\u7ED8\u5236\u7684 \u{1F643}",
1407
+ "treemap.err.write": "\u{1F6D1} \u65E0\u6CD5\u5199\u5165 treemap \u6587\u4EF6 \u2192 {path} \u2014 {detail}",
1408
+ "treemap.done": "\u{1F5FA}\uFE0F treemap \u2192 {path} \u2014 \u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\uFF0C\u60AC\u505C\u5355\u5143\u683C\u67E5\u770B\u8BE6\u60C5",
1375
1409
  // ── verbose diagnostics & utils ─────────────────────────────────────────
1376
- "verbose.deleteLogUnavailable": "delete log unavailable: {detail}",
1377
- "verbose.configUsing": "config: using {file}",
1378
- "verbose.configFound": "config: found {file}",
1379
- "verbose.baselineReadFailed": "baseline read failed: {detail}",
1380
- "warn.baselineSkip": "skipping unreadable baseline: {file}",
1381
- "verbose.updateCacheWriteFailed": "update-cache write failed: {detail}",
1382
- "verbose.updateCheckFailed": "update check failed: {detail}",
1383
- "verbose.updateRegistryStatus": "update check: registry responded {status}",
1384
- "verbose.updateRegistryUnreachable": "update check: registry unreachable ({detail})",
1385
- "verbose.scanTargets": "targets: {targets}",
1386
- "verbose.walkRoots": "walk roots: {walk}, direct node_modules: {direct}",
1387
- "verbose.scanFound": "found {n} node_modules \u2014 measuring",
1388
- "verbose.scanDone": "scan finished in {ms} ms",
1389
- "verbose.searchMatched": "search '{pattern}': {found}/{total} entries matched",
1390
- "verbose.mapProjects": "map: {n} project(s)",
1391
- "verbose.statsSummary": "stats: {entries} entries, {instances} instances, {unique} unique",
1392
- "verbose.globalNone": "global: {pm} \u2014 no global node_modules found",
1393
- "verbose.whyRequirers": "why: {pkg} in {path} \u2014 {count} requirer(s) ({grade})",
1394
- "verbose.treemapData": "treemap data: {entries} entries, {packages} packages",
1395
- "verbose.updateOverrideUnreadable": "update: override file unreadable ({detail})",
1396
- "verbose.npmViewFailed": "npm view failed (rc {code}): {stderr}",
1410
+ "verbose.deleteLogUnavailable": "\u5220\u9664\u65E5\u5FD7\u4E0D\u53EF\u7528\uFF1A{detail}",
1411
+ "verbose.configUsing": "config: \u4F7F\u7528 {file}",
1412
+ "verbose.configFound": "config: \u627E\u5230 {file}",
1413
+ "verbose.baselineReadFailed": "\u57FA\u7EBF\u8BFB\u53D6\u5931\u8D25\uFF1A{detail}",
1414
+ "warn.baselineSkip": "\u8DF3\u8FC7\u4E0D\u53EF\u8BFB\u7684\u57FA\u7EBF\uFF1A{file}",
1415
+ "verbose.updateCacheWriteFailed": "\u66F4\u65B0\u7F13\u5B58\u5199\u5165\u5931\u8D25\uFF1A{detail}",
1416
+ "verbose.updateCheckFailed": "\u66F4\u65B0\u68C0\u67E5\u5931\u8D25\uFF1A{detail}",
1417
+ "verbose.updateRegistryStatus": "\u66F4\u65B0\u68C0\u67E5\uFF1Aregistry \u54CD\u5E94 {status}",
1418
+ "verbose.updateRegistryUnreachable": "\u66F4\u65B0\u68C0\u67E5\uFF1Aregistry \u4E0D\u53EF\u8FBE\uFF08{detail}\uFF09",
1419
+ "verbose.scanTargets": "\u76EE\u6807\uFF1A{targets}",
1420
+ "verbose.walkRoots": "\u904D\u5386\u6839\uFF1A{walk}\uFF0C\u76F4\u63A5\u7684 node_modules\uFF1A{direct}",
1421
+ "verbose.scanFound": "\u627E\u5230 {n} \u4E2A node_modules \u2014 \u6B63\u5728\u6D4B\u91CF",
1422
+ "verbose.scanDone": "\u626B\u63CF\u5728 {ms} \u6BEB\u79D2\u5185\u5B8C\u6210",
1423
+ "verbose.searchMatched": "\u641C\u7D22 '{pattern}'\uFF1A{found}/{total} \u6761\u5339\u914D",
1424
+ "verbose.mapProjects": "map\uFF1A{n} \u4E2A\u9879\u76EE",
1425
+ "verbose.statsSummary": "stats\uFF1A{entries} \u6761\u76EE\uFF0C{instances} \u4E2A\u5B9E\u4F8B\uFF0C{unique} \u4E2A\u552F\u4E00",
1426
+ "verbose.globalNone": "global\uFF1A{pm} \u2014 \u672A\u627E\u5230\u5168\u5C40 node_modules",
1427
+ "verbose.whyRequirers": "why\uFF1A{pkg} \u4F4D\u4E8E {path} \u2014 {count} \u4E2A\u4F9D\u8D56\u65B9\uFF08{grade}\uFF09",
1428
+ "verbose.treemapData": "treemap \u6570\u636E\uFF1A{entries} \u6761\u76EE\uFF0C{packages} \u4E2A\u5305",
1429
+ "verbose.updateOverrideUnreadable": "update\uFF1A\u8986\u76D6\u6587\u4EF6\u4E0D\u53EF\u8BFB\uFF08{detail}\uFF09",
1430
+ "verbose.npmViewFailed": "npm view \u5931\u8D25\uFF08rc {code}\uFF09\uFF1A{stderr}",
1397
1431
  // ── commands/stats.ts ───────────────────────────────────────────────────
1398
- "stats.spin.progress": "analyzing {done}/{total} node_modules\u2026",
1399
- "stats.hint.noDeclared": "copies resolusinya ikut parent masing-masing \u2014 tidak ada knob langsung di project level",
1400
- "stats.hint.tail": " (declared {range})",
1401
- "stats.hint.pnpm": "range declared identik \u2014 pnpm virtual store melipat copy hoisted; cukup satu versi di workspace root{tail}",
1402
- "stats.hint.sameRange": "range declared identik \u2014 jalankan install ulang / npm dedupe \xB7 yarn dedupe melipat copy hoisted{tail}",
1403
- "stats.hint.diffRanges": "range declared beda ({ranges}) \u2014 samakan dulu di package.json, lalu install ulang",
1404
- "stats.err.noBaseline": "no baseline named '{name}' \u2014 {detail}",
1405
- "stats.err.baselinesSaved": "saved: {list}",
1406
- "stats.err.saveFirst": "save one first with nmh stats --save-baseline <name>",
1407
- "stats.note.savedEmpty": "\u{1F4BE} baseline saved \u2192 {name} (empty snapshot \u2014 no node_modules yet)",
1408
- "stats.warn.nothingToCompare": "nothing to compare \u2014 no node_modules scanned; baseline '{name}' kept as-is",
1409
- "stats.warn.none": "no node_modules found \u2014 nothing to analyze here \u{1F643}",
1410
- "stats.note.saved": "\u{1F4BE} baseline saved \u2192 {name}",
1411
- "stats.err.saveFailed": "could not save baseline '{name}': {detail}",
1432
+ "stats.spin.progress": "\u6B63\u5728\u5206\u6790 {done}/{total} \u4E2A node_modules\u2026",
1433
+ "stats.hint.noDeclared": "\u526F\u672C\u7684\u89E3\u6790\u8DDF\u968F\u5404\u81EA\u7684\u7236\u7EA7 \u2014 \u9879\u76EE\u5C42\u6CA1\u6709\u76F4\u63A5\u7684\u63A7\u5236\u5F00\u5173",
1434
+ "stats.hint.tail": "\uFF08\u58F0\u660E {range}\uFF09",
1435
+ "stats.hint.pnpm": "\u58F0\u660E\u7684\u8303\u56F4\u76F8\u540C \u2014 pnpm \u865A\u62DF\u5B58\u50A8\u4F1A\u6298\u53E0\u63D0\u5347\u7684\u526F\u672C\uFF1Bworkspace \u6839\u53EA\u9700\u4E00\u4E2A\u7248\u672C{tail}",
1436
+ "stats.hint.sameRange": "\u58F0\u660E\u7684\u8303\u56F4\u76F8\u540C \u2014 \u91CD\u65B0\u5B89\u88C5 / npm dedupe \xB7 yarn dedupe \u4F1A\u6298\u53E0\u63D0\u5347\u7684\u526F\u672C{tail}",
1437
+ "stats.hint.diffRanges": "\u58F0\u660E\u7684\u8303\u56F4\u4E0D\u540C\uFF08{ranges}\uFF09\u2014 \u5148\u5728 package.json \u4E2D\u7EDF\u4E00\uFF0C\u518D\u91CD\u65B0\u5B89\u88C5",
1438
+ "stats.err.noBaseline": "\u6CA1\u6709\u540D\u4E3A '{name}' \u7684\u57FA\u7EBF \u2014 {detail}",
1439
+ "stats.err.baselinesSaved": "\u5DF2\u4FDD\u5B58\uFF1A{list}",
1440
+ "stats.err.saveFirst": "\u5148\u7528 nmh stats --save-baseline <name> \u4FDD\u5B58\u4E00\u4E2A",
1441
+ "stats.note.savedEmpty": "\u{1F4BE} \u57FA\u7EBF\u5DF2\u4FDD\u5B58 \u2192 {name}\uFF08\u7A7A\u5FEB\u7167 \u2014 \u5C1A\u65E0 node_modules\uFF09",
1442
+ "stats.warn.nothingToCompare": "\u6CA1\u6709\u53EF\u6BD4\u8F83\u7684\u5185\u5BB9 \u2014 \u672A\u626B\u63CF\u5230 node_modules\uFF1B\u57FA\u7EBF '{name}' \u539F\u6837\u4FDD\u7559",
1443
+ "stats.warn.none": "\u672A\u627E\u5230 node_modules \u2014 \u8FD9\u91CC\u6CA1\u6709\u53EF\u5206\u6790\u7684 \u{1F643}",
1444
+ "stats.note.saved": "\u{1F4BE} \u57FA\u7EBF\u5DF2\u4FDD\u5B58 \u2192 {name}",
1445
+ "stats.err.saveFailed": "\u65E0\u6CD5\u4FDD\u5B58\u57FA\u7EBF '{name}'\uFF1A{detail}",
1412
1446
  // ── core/treemap.ts (HTML artifact) ────────────────────────────────────
1413
- "treemap.link": " \u27F6link",
1414
- "treemap.html.header": "nmh treemap \u2014 {entries} \u2014 {count} node_modules \u2014 hover buat detail disk, generated {at}",
1415
- "treemap.html.aria": "treemap ukuran node_modules",
1447
+ "treemap.link": " \u27F6\u94FE\u63A5",
1448
+ "treemap.html.header": "nmh treemap \u2014 {entries} \u2014 {count} \u4E2A node_modules \u2014 \u60AC\u505C\u67E5\u770B\u78C1\u76D8\u8BE6\u60C5\uFF0C\u751F\u6210\u4E8E {at}",
1449
+ "treemap.html.aria": "node_modules \u5927\u5C0F treemap",
1416
1450
  // ── help manual ─────────────────────────────────────────────────────────
1417
- "help.tagline": "hunt bloated node_modules folders: scan, measure, clean safely (npm/pnpm/yarn/bun)",
1418
- "help.usage.title": "Usage",
1451
+ "help.tagline": "\u730E\u6355\u81C3\u80BF\u7684 node_modules \u6587\u4EF6\u5939\uFF1A\u626B\u63CF\u3001\u5EA6\u91CF\u3001\u5B89\u5168\u6E05\u7406\uFF08npm/pnpm/yarn/bun\uFF09",
1452
+ "help.usage.title": "\u7528\u6CD5",
1419
1453
  "help.usage.line": "nmh <command|targets> [options]",
1420
- "help.commands.title": "Commands",
1421
- "help.statsSub.title": "Stats subcommands",
1422
- "help.options.title": "Options \u2014 {group}",
1423
- "help.examples.title": "Examples",
1424
- "help.cmd.bare": "interactive wizard: arrow menu (delete all / pick / search / map / report / settings)",
1425
- "help.cmd.paths": "shortcut: scan given path(s); one-liner actions via flags (--delete, --search, \u2026)",
1426
- "help.cmd.wizard": "v1.2: the wizard on explicit targets (--dir=./a,./b skips the auto-climb); -- <view> opens a view first",
1427
- "help.cmd.scan": "full scan across targets (default: cwd)",
1428
- "help.cmd.clean": "scan + delete everything safe (trash by default)",
1429
- "help.cmd.search": "find installed packages by name (+ versions & sizes) \u2014 read-only",
1430
- "help.cmd.map": "project \u2192 PM \u2192 size \u2192 top packages \u2192 declared deps \u2014 read-only",
1431
- "help.cmd.stats": "size analytics: dup factor, waste, top-N, per-package tree (aliases: analyze, info)",
1432
- "help.cmd.why": "reverse depend: where is <pkg> and who requires it \u2014 read-only",
1433
- "help.cmd.treemap": "single-file interactive HTML treemap \u2192 nmh-treemap.html",
1434
- "help.cmd.global": "global installs across npm/pnpm/yarn/bun \u2014 read-only",
1435
- "help.cmd.config": "manage .nmhrc from the CLI: info \xB7 set \xB7 add \xB7 remove \xB7 unset",
1436
- "help.cmd.update": "v1.2: shows the facts and asks before installing \u2014 --check / --info compare only; -y installs, -n declines, --force skips the ask",
1437
- "help.cmd.version": "banner: tool version, node+abi, OS/arch/kernel, tty (alias: -v / --version)",
1438
- "help.cmd.help": "this help (alias: -h / --help)",
1439
- "help.statsSub.byType": "breakdown per dependency field (dep/dev/optional/peer/transitive)",
1440
- "help.statsSub.licenses": "license buckets (+ \u26A0 copyleft inside production deps)",
1441
- "help.statsSub.score": "experimental: composite bloat score 0-100 / rough CO2 estimate",
1442
- "help.statsSub.graph": "dependency graph from the lockfile \u2014 npm/yarn/pnpm/bun, no extra deps",
1443
- "help.statsSub.reinstall": 'naive npm-ci-style "how long would reinstalling everything take"',
1444
- "help.group.actions": "Actions",
1445
- "help.group.stale": "Stale hunting & output shape (v1.1)",
1446
- "help.group.scoping": "Scoping & filters",
1447
- "help.group.stats": "Stats suite",
1448
- "help.group.config": "Config family",
1449
- "help.flag.delete": "delete found folders: hard | trash (soft alias) \u2014 no value = pick interactively",
1450
- "help.flag.trash": "v1.1: whose trash takes victims \u2014 system backend (default) or restorable ~/.nmh/trash",
1451
- "help.flag.dryRun": "preview what would be deleted \u2014 nothing is touched",
1452
- "help.flag.yes": "answer yes to every prompt (required for non-TTY deletes)",
1453
- "help.flag.force": "skip all confirmations (implies --yes)",
1454
- "help.flag.search": "search installed packages (substring, glob, or /regex/) \u2014 read-only",
1455
- "help.flag.map": "map projects: PM, size, top packages, declared deps \u2014 read-only",
1456
- "help.flag.depend": "map only: show declared deps; with a value, list who declares it",
1457
- "help.flag.tree": "map/stats only: list per-project packages (tree view, with sizes)",
1458
- "help.flag.why": "read-only: explain an installed package \u2014 instances and requirers",
1459
- "help.flag.stats": "stats report: overview + dup factor + waste + top sizes \u2014 read-only",
1460
- "help.flag.treemap": "treemap export: single-file HTML (default nmh-treemap.html; --out is an alias)",
1461
- "help.flag.dir": "target dir(s), comma separated or repeated; globs and ~ allowed",
1462
- "help.flag.size": "output shape: 'total' (just aggregate) or 'each' (default: per-folder table)",
1463
- "help.flag.saveReport": "also write the printed report to a file (.json/.md/.txt; --report <file> aliases it)",
1464
- "help.flag.wizard": "v1.2: open the wizard explicitly \u2014 same as bare `nmh`, but a pipe refuses with directions instead of a scan",
1465
- "help.flag.updateFamily": "v1.2: read-only views vs consented install \u2014 see `nmh update` row above",
1466
- "help.flag.updateCheck": "peek npm for a newer release (non-blocking, 24 h cache; also settable in .nmhrc)",
1467
- "help.flag.stale": "keep only projects idle >= <days>; ladder = git commit \u2192 manifest \u2192 folder mtime; no evidence = dropped",
1468
- "help.flag.fastSize": "measure with one `du -sk` per entry (KiB granularity) instead of walking every file",
1469
- "help.flag.sort": "order results: size (default, desc) | path | idle (oldest project first) | mtime (newest first)",
1470
- "help.flag.noSkip": "stop hiding system noise (.Trash*, Library/, *.app) during discovery \u2014 default: hidden",
1471
- "help.flag.animate": "live size counter while measuring: auto = real TTY only",
1472
- "help.flag.json": "machine-readable payload (pipe into jq); additive-only keys \u2014 v1.0 keys stay frozen",
1473
- "help.flag.quiet": "minimal output \u2014 pretty tables/notes mute, the --json payload still prints",
1474
- "help.flag.verbose": "debug chatter on stderr",
1475
- "help.flag.noColor": "disable ANSI colors (auto: colors only on a real TTY or with --color / FORCE_COLOR)",
1476
- "help.flag.color": "force ANSI colors even on a piped run (wins over a config color:false)",
1477
- "help.flag.recursive": "also look INSIDE found node_modules (nested audit; totals stay top-level only)",
1478
- "help.flag.pm": "filter by detected PM: npm|pnpm|yarn|bun|vp \u2014 no value lists what was detected",
1479
- "help.flag.exclude": "exclude paths from results (comma list of globs, e.g. **/e2e/**)",
1480
- "help.flag.keep": 'refuse to delete node_modules of these projects (comma list, glob ok; "self" works)',
1481
- "help.flag.depth": "max scan depth in levels below the target",
1482
- "help.flag.expand": "full absolute paths + extra detail in output",
1483
- "help.flag.top": "rows in the focused size list (default 10)",
1484
- "help.flag.by": "breakdown mode \u2014 'size' (alias: package), 'type', 'licenses'",
1485
- "help.flag.global": "analyze global installs (per-PM prefix scan; read-only)",
1486
- "help.flag.config": "use this config file instead of the .nmhrc lookup (cwd \u2192 home)",
1487
- "help.flag.saveBaseline": "save a metadata snapshot of this run to ~/.nmh/baselines/<name>.json",
1488
- "help.flag.compare": "diff this run against a stored baseline (totals, per-folder, package movers)",
1489
- "help.flag.history": "list stored baselines \u2014 no scan at all",
1490
- "help.flag.phantom": "stats only: imports found in sources but declared nowhere (best-effort regex audit)",
1491
- "help.flag.dead": "stats only: installed + declared but never imported (best-effort regex audit)",
1492
- "help.flag.licenses": "stats only: bucket instances by license field; flags copyleft in production deps",
1493
- "help.flag.score": "stats only: experimental composite bloat score 0-100",
1494
- "help.flag.co2": "stats only: experimental carbon estimate (storage-year + one redownload)",
1495
- "help.flag.online": "stats only: deprecated scan \u2014 offline manifests + lazy cached registry fallback",
1496
- "help.flag.graph": "stats only: dependency graph from the lockfile (npm/yarn/pnpm/bun) with BFS depth",
1497
- "help.flag.reinstall": "stats only: naive npm-ci-style estimate of the time to reinstall everything",
1498
- "help.flag.out": "treemap only: where to write the HTML file (same as --treemap <file>)",
1499
- "help.flag.defaultExclude": 'manage the persisted exclude list (comma list; special value "self")',
1500
- "help.flag.defaultKeep": 'manage the persisted keep list (comma list; special value "self")',
1501
- "help.flag.defaultMode": "set the persisted delete default (hard | soft | trash)",
1502
- "help.flag.logDir": "set the persisted recovery-log directory (logDir)",
1503
- "help.ex.bare": "wizard; the no-args menu auto-climbs to the nearest project root",
1504
- "help.ex.wizardDir": "wizard scoped to explicit targets \u2014 no auto-climb",
1505
- "help.ex.wizardRouter": "v1.2 router: stats view first, then the wizard menu",
1506
- "help.ex.multiTarget": "multi-target scan",
1507
- "help.ex.stale": "bury the stale boneyard, restorable trash",
1508
- "help.ex.why": "reverse-depend: who declares + who requires",
1509
- "help.ex.byType": "dep-field breakdown as a machine payload",
1510
- "help.ex.globalTop": "the 20 biggest global installs across PMs",
1511
- "help.ex.updateCheck": "compare installed vs registry \u2014 nothing installs",
1512
- "help.ex.configSet": "persist a default delete mode in .nmhrc",
1513
- "help.footer.safety": "Safety first: guards refuse dangerous targets (exit 3), deletes confirm unless --yes/--force, symlinks never get followed.",
1514
- "help.footer.exitCodes": "Exit codes: 0 ok \xB7 1 usage error \xB7 2 nothing found \xB7 3 guard refused \xB7 4 permission denied.",
1515
- "help.footer.docs": "Everything is documented in depth at: https://github.com/jhedev96/node-modules-hunter",
1454
+ "help.commands.title": "\u547D\u4EE4",
1455
+ "help.statsSub.title": "stats \u5B50\u547D\u4EE4",
1456
+ "help.options.title": "\u9009\u9879 \u2014 {group}",
1457
+ "help.examples.title": "\u793A\u4F8B",
1458
+ "help.cmd.bare": "\u4EA4\u4E92\u5F0F\u5411\u5BFC\uFF1A\u65B9\u5411\u952E\u83DC\u5355\uFF08\u5168\u90E8\u5220\u9664 / \u6311\u9009 / \u641C\u7D22 / \u6620\u5C04 / \u62A5\u544A / \u66F4\u65B0 / \u8BBE\u7F6E\uFF09",
1459
+ "help.cmd.paths": "\u6377\u5F84\uFF1A\u626B\u63CF\u7ED9\u5B9A\u8DEF\u5F84\uFF1B\u901A\u8FC7 flag \u6267\u884C\u5355\u884C\u52A8\u4F5C\uFF08--delete\u3001--search \u7B49\uFF09",
1460
+ "help.cmd.wizard": "v1.2\uFF1A\u5BF9\u663E\u5F0F\u76EE\u6807\u8FD0\u884C\u5411\u5BFC\uFF08--dir=./a,./b \u8DF3\u8FC7\u81EA\u52A8\u4E0A\u6EAF\uFF09\uFF1B-- <view> \u5148\u6253\u5F00\u4E00\u4E2A\u89C6\u56FE\uFF1B\u83DC\u5355\u73B0\u5DF2\u5305\u542B \u{1F501} \u66F4\u65B0 nmh\uFF08v1.4\uFF09",
1461
+ "help.cmd.scan": "\u8DE8\u76EE\u6807\u5B8C\u6574\u626B\u63CF\uFF08\u9ED8\u8BA4\uFF1Acwd\uFF09",
1462
+ "help.cmd.clean": "\u626B\u63CF + \u5220\u9664\u6240\u6709\u5B89\u5168\u9879\uFF08\u9ED8\u8BA4\u56DE\u6536\u7AD9\uFF09",
1463
+ "help.cmd.search": "\u6309\u540D\u79F0\u67E5\u627E\u5DF2\u5B89\u88C5\u7684\u5305\uFF08\u542B\u7248\u672C\u4E0E\u5927\u5C0F\uFF09\u2014 \u53EA\u8BFB",
1464
+ "help.cmd.map": "\u9879\u76EE \u2192 PM \u2192 \u5927\u5C0F \u2192 \u4E3B\u8981\u5305 \u2192 \u58F0\u660E\u7684\u4F9D\u8D56 \u2014 \u53EA\u8BFB",
1465
+ "help.cmd.stats": "\u4F53\u79EF\u5206\u6790\uFF1A\u91CD\u590D\u7387\u3001\u6D6A\u8D39\u3001top-N\u3001\u9010\u5305\u6811\uFF08\u522B\u540D\uFF1Aanalyze\u3001info\uFF09",
1466
+ "help.cmd.why": "\u53CD\u5411\u4F9D\u8D56\uFF1A<pkg> \u5728\u54EA\u91CC\u3001\u8C01\u4F9D\u8D56\u5B83 \u2014 \u53EA\u8BFB",
1467
+ "help.cmd.treemap": "\u5355\u6587\u4EF6\u4EA4\u4E92\u5F0F HTML treemap \u2192 nmh-treemap.html",
1468
+ "help.cmd.global": "npm/pnpm/yarn/bun \u7684\u5168\u5C40\u5B89\u88C5 \u2014 \u53EA\u8BFB",
1469
+ "help.cmd.config": "\u5728 CLI \u4E2D\u7BA1\u7406 .nmhrc\uFF1Ainfo \xB7 set \xB7 add \xB7 remove \xB7 unset",
1470
+ "help.cmd.update": "v1.4\uFF1A\u5148\u5C55\u793A\u4FE1\u606F\uFF0C\u5B89\u88C5\u524D\u8BE2\u95EE \u2014 --check [tag] / --info \u4EC5\u5BF9\u6BD4\uFF1B--tag \u8BFB\u53D6 dist-tag\uFF08\u964D\u7EA7\u786E\u8BA4\u9ED8\u8BA4\u4E3A\u5426\uFF09\uFF1B-y \u5B89\u88C5\uFF0C-n \u62D2\u7EDD\uFF0C--force \u8DF3\u8FC7\u8BE2\u95EE",
1471
+ "help.cmd.version": "banner\uFF1A\u5DE5\u5177\u7248\u672C\u3001node+abi\u3001OS/arch/kernel\u3001tty\uFF08\u522B\u540D\uFF1A-v / --version\uFF09",
1472
+ "help.cmd.help": "\u672C\u5E2E\u52A9\uFF08\u522B\u540D\uFF1A-h / --help\uFF09",
1473
+ "help.statsSub.byType": "\u6309\u4F9D\u8D56\u5B57\u6BB5\u7EC6\u5206\uFF08dep/dev/optional/peer/transitive\uFF09",
1474
+ "help.statsSub.licenses": "\u8BB8\u53EF\u8BC1\u5206\u6876\uFF08+ \u26A0 \u751F\u4EA7\u4F9D\u8D56\u4E2D\u7684 copyleft\uFF09",
1475
+ "help.statsSub.score": "\u5B9E\u9A8C\u6027\uFF1A0-100 \u7EFC\u5408\u81C3\u80BF\u8BC4\u5206 / \u7C97\u7565 CO2 \u4F30\u7B97",
1476
+ "help.statsSub.graph": "\u6765\u81EA lockfile \u7684\u4F9D\u8D56\u56FE \u2014 npm/yarn/pnpm/bun\uFF0C\u65E0\u989D\u5916\u4F9D\u8D56",
1477
+ "help.statsSub.reinstall": "npm-ci \u98CE\u683C\u7684\u7C97\u7565\u4F30\u7B97\u201C\u91CD\u88C5\u5168\u90E8\u8981\u591A\u4E45\u201D",
1478
+ "help.group.actions": "\u64CD\u4F5C",
1479
+ "help.group.stale": "\u9648\u65E7\u730E\u6355\u4E0E\u8F93\u51FA\u5F62\u6001\uFF08v1.1\uFF09",
1480
+ "help.group.scoping": "\u8303\u56F4\u4E0E\u8FC7\u6EE4",
1481
+ "help.group.stats": "stats \u5957\u4EF6",
1482
+ "help.group.config": "config \u5BB6\u65CF",
1483
+ "help.flag.delete": "\u5220\u9664\u627E\u5230\u7684\u6587\u4EF6\u5939\uFF1Ahard | trash\uFF08soft \u522B\u540D\uFF09\u2014 \u65E0\u503C = \u4EA4\u4E92\u5F0F\u6311\u9009",
1484
+ "help.flag.trash": "v1.1\uFF1A\u7528\u8C01\u7684\u56DE\u6536\u7AD9 \u2014 \u7CFB\u7EDF\u540E\u7AEF\uFF08\u9ED8\u8BA4\uFF09\u6216\u53EF\u6062\u590D\u7684 ~/.nmh/trash",
1485
+ "help.flag.dryRun": "\u9884\u89C8\u5C06\u5220\u9664\u7684\u5185\u5BB9 \u2014 \u4E0D\u52A8\u4EFB\u4F55\u4E1C\u897F",
1486
+ "help.flag.yes": "\u5BF9\u6240\u6709\u63D0\u793A\u56DE\u7B54\u662F\uFF08\u975E TTY \u5220\u9664\u5FC5\u9700\uFF09",
1487
+ "help.flag.force": "\u8DF3\u8FC7\u6240\u6709\u786E\u8BA4\uFF08\u9690\u542B --yes\uFF09",
1488
+ "help.flag.search": "\u641C\u7D22\u5DF2\u5B89\u88C5\u7684\u5305\uFF08\u5B50\u4E32\u3001glob \u6216 /regex/\uFF09\u2014 \u53EA\u8BFB",
1489
+ "help.flag.map": "\u6620\u5C04\u9879\u76EE\uFF1APM\u3001\u5927\u5C0F\u3001\u4E3B\u8981\u5305\u3001\u58F0\u660E\u7684\u4F9D\u8D56 \u2014 \u53EA\u8BFB",
1490
+ "help.flag.depend": "\u4EC5 map\uFF1A\u663E\u793A\u58F0\u660E\u7684\u4F9D\u8D56\uFF1B\u5E26\u503C\u65F6\u5217\u51FA\u8C01\u58F0\u660E\u4E86\u5B83",
1491
+ "help.flag.tree": "\u4EC5 map/stats\uFF1A\u5217\u51FA\u6BCF\u4E2A\u9879\u76EE\u7684\u5305\uFF08\u6811\u89C6\u56FE\uFF0C\u542B\u5927\u5C0F\uFF09",
1492
+ "help.flag.why": "\u53EA\u8BFB\uFF1A\u89E3\u91CA\u4E00\u4E2A\u5DF2\u5B89\u88C5\u7684\u5305 \u2014 \u5B9E\u4F8B\u4E0E\u4F9D\u8D56\u65B9",
1493
+ "help.flag.stats": "stats \u62A5\u544A\uFF1A\u603B\u89C8 + \u91CD\u590D\u7387 + \u6D6A\u8D39 + \u4F53\u79EF top \u2014 \u53EA\u8BFB",
1494
+ "help.flag.treemap": "treemap \u5BFC\u51FA\uFF1A\u5355\u6587\u4EF6 HTML\uFF08\u9ED8\u8BA4 nmh-treemap.html\uFF1B--out \u662F\u522B\u540D\uFF09",
1495
+ "help.flag.dir": "\u76EE\u6807\u76EE\u5F55\uFF0C\u9017\u53F7\u5206\u9694\u6216\u91CD\u590D\u4F7F\u7528\uFF1B\u5141\u8BB8 glob \u548C ~",
1496
+ "help.flag.size": "\u8F93\u51FA\u5F62\u6001\uFF1A'total'\uFF08\u4EC5\u6C47\u603B\uFF09\u6216 'each'\uFF08\u9ED8\u8BA4\uFF1A\u9010\u6587\u4EF6\u5939\u8868\u683C\uFF09",
1497
+ "help.flag.saveReport": "\u540C\u65F6\u628A\u6253\u5370\u7684\u62A5\u544A\u5199\u5165\u6587\u4EF6\uFF08.json/.md/.txt\uFF1B--report <file> \u662F\u522B\u540D\uFF09",
1498
+ "help.flag.wizard": "v1.2\uFF1A\u663E\u5F0F\u6253\u5F00\u5411\u5BFC \u2014 \u4E0E\u88F8 `nmh` \u76F8\u540C\uFF0C\u4F46\u7BA1\u9053\u4E2D\u4F1A\u62D2\u7EDD\u5E76\u7ED9\u51FA\u6307\u5F15\u800C\u975E\u626B\u63CF",
1499
+ "help.flag.updateFamily": "v1.2\uFF1A\u53EA\u8BFB\u89C6\u56FE\u4E0E\u7ECF\u540C\u610F\u7684\u5B89\u88C5 \u2014 \u89C1\u4E0A\u65B9 `nmh update` \u4E00\u884C",
1500
+ "help.flag.tag": "\u8BFB\u53D6\u6307\u5B9A\u7684 npm dist-tag \u2014 nmh update --tag beta\uFF1B--check <tag> \u4E0E\u4E4B\u5BF9\u6BD4\uFF08v1.4\uFF09",
1501
+ "help.flag.updateTag": "\u6301\u4E45\u5316\u7684\u66F4\u65B0 dist-tag\uFF08.nmhrc \u4E2D\u7684 updateTag\uFF09\u2014 `nmh update` / `--check` \u9ED8\u8BA4\u8BFB\u53D6\u5B83\uFF08v1.4\uFF09",
1502
+ "help.flag.updateCheck": "\u67E5\u770B npm \u662F\u5426\u6709\u65B0\u7248\u672C\uFF08\u975E\u963B\u585E\uFF0C24 \u5C0F\u65F6\u7F13\u5B58\uFF1B\u4E5F\u53EF\u5728 .nmhrc \u4E2D\u8BBE\u7F6E\uFF09",
1503
+ "help.flag.stale": "\u53EA\u4FDD\u7559\u95F2\u7F6E >= <days> \u7684\u9879\u76EE\uFF1B\u4F9D\u636E = git commit \u2192 manifest \u2192 \u6587\u4EF6\u5939 mtime\uFF1B\u65E0\u8BC1\u636E = \u5254\u9664",
1504
+ "help.flag.fastSize": "\u6BCF\u9879\u7528\u4E00\u6B21 `du -sk` \u5EA6\u91CF\uFF08KiB \u7C92\u5EA6\uFF09\uFF0C\u800C\u975E\u904D\u5386\u6BCF\u4E2A\u6587\u4EF6",
1505
+ "help.flag.sort": "\u7ED3\u679C\u6392\u5E8F\uFF1Asize\uFF08\u9ED8\u8BA4\uFF0C\u964D\u5E8F\uFF09| path | idle\uFF08\u6700\u4E45\u672A\u52A8\u7684\u9879\u76EE\u5728\u524D\uFF09| mtime\uFF08\u6700\u65B0\u5728\u524D\uFF09",
1506
+ "help.flag.noSkip": "\u53D1\u73B0\u9636\u6BB5\u4E0D\u518D\u9690\u85CF\u7CFB\u7EDF\u566A\u97F3\uFF08.Trash*\u3001Library/\u3001*.app\uFF09\u2014 \u9ED8\u8BA4\uFF1A\u9690\u85CF",
1507
+ "help.flag.animate": "\u6D4B\u91CF\u65F6\u7684\u5B9E\u65F6\u5927\u5C0F\u8BA1\u6570\u5668\uFF1Aauto = \u4EC5\u771F\u5B9E TTY",
1508
+ "help.flag.json": "\u673A\u5668\u53EF\u8BFB\u8F7D\u8377\uFF08\u53EF\u7BA1\u9053\u7ED9 jq\uFF09\uFF1B\u4EC5\u589E\u91CF\u65B0\u589E\u952E \u2014 v1.0 \u7684\u952E\u4FDD\u6301\u51BB\u7ED3",
1509
+ "help.flag.quiet": "\u6700\u5C0F\u8F93\u51FA \u2014 \u7CBE\u7F8E\u8868\u683C/\u63D0\u793A\u9759\u9ED8\uFF0C--json \u8F7D\u8377\u4ECD\u4F1A\u6253\u5370",
1510
+ "help.flag.verbose": "stderr \u4E0A\u7684\u8C03\u8BD5\u8F93\u51FA",
1511
+ "help.flag.noColor": "\u7981\u7528 ANSI \u989C\u8272\uFF08auto\uFF1A\u4EC5\u771F\u5B9E TTY \u6216 --color / FORCE_COLOR \u65F6\u7740\u8272\uFF09",
1512
+ "help.flag.color": "\u5373\u4F7F\u5728\u7BA1\u9053\u8FD0\u884C\u4E2D\u4E5F\u5F3A\u5236 ANSI \u989C\u8272\uFF08\u4F18\u5148\u4E8E config color:false\uFF09",
1513
+ "help.flag.language": "\u754C\u9762\u8BED\u8A00\uFF1Aen | id | zh | ru | es \u2014 \u4E5F\u53EF\u901A\u8FC7 .nmhrc `language` \u4E0E NMH_LANG \u8BBE\u7F6E\uFF1B\u672A\u77E5\u503C\u9759\u9ED8\u56DE\u9000\u5230 en",
1514
+ "help.flag.recursive": "\u4E5F\u67E5\u770B\u627E\u5230\u7684 node_modules \u5185\u90E8\uFF08\u5D4C\u5957\u5BA1\u8BA1\uFF1B\u603B\u91CF\u4ECD\u53EA\u7B97\u9876\u5C42\uFF09",
1515
+ "help.flag.pm": "\u6309\u68C0\u6D4B\u5230\u7684 PM \u8FC7\u6EE4\uFF1Anpm|pnpm|yarn|bun|vp \u2014 \u65E0\u503C\u65F6\u5217\u51FA\u68C0\u6D4B\u7ED3\u679C",
1516
+ "help.flag.exclude": "\u4ECE\u7ED3\u679C\u4E2D\u6392\u9664\u8DEF\u5F84\uFF08\u9017\u53F7\u5206\u9694\u7684 glob\uFF0C\u5982 **/e2e/**\uFF09",
1517
+ "help.flag.keep": '\u62D2\u7EDD\u5220\u9664\u8FD9\u4E9B\u9879\u76EE\u7684 node_modules\uFF08\u9017\u53F7\u5217\u8868\uFF0C\u652F\u6301 glob\uFF1B\u53EF\u7528 "self"\uFF09',
1518
+ "help.flag.depth": "\u76EE\u6807\u4E4B\u4E0B\u7684\u6700\u5927\u626B\u63CF\u5C42\u6570",
1519
+ "help.flag.expand": "\u5B8C\u6574\u7EDD\u5BF9\u8DEF\u5F84 + \u8F93\u51FA\u4E2D\u7684\u989D\u5916\u7EC6\u8282",
1520
+ "help.flag.top": "\u805A\u7126\u4F53\u79EF\u5217\u8868\u7684\u884C\u6570\uFF08\u9ED8\u8BA4 10\uFF09",
1521
+ "help.flag.by": "\u7EC6\u5206\u6A21\u5F0F \u2014 'size'\uFF08\u522B\u540D\uFF1Apackage\uFF09\u3001'type'\u3001'licenses'",
1522
+ "help.flag.global": "\u5206\u6790\u5168\u5C40\u5B89\u88C5\uFF08\u6309 PM \u524D\u7F00\u626B\u63CF\uFF1B\u53EA\u8BFB\uFF09",
1523
+ "help.flag.config": "\u4F7F\u7528\u8BE5\u914D\u7F6E\u6587\u4EF6\u66FF\u4EE3 .nmhrc \u67E5\u627E\uFF08cwd \u2192 home\uFF09",
1524
+ "help.flag.saveBaseline": "\u628A\u672C\u6B21\u8FD0\u884C\u7684\u5143\u6570\u636E\u5FEB\u7167\u4FDD\u5B58\u5230 ~/.nmh/baselines/<name>.json",
1525
+ "help.flag.compare": "\u5C06\u672C\u6B21\u8FD0\u884C\u4E0E\u5DF2\u5B58\u57FA\u7EBF\u505A diff\uFF08\u603B\u91CF\u3001\u9010\u6587\u4EF6\u5939\u3001\u5305\u53D8\u52A8\uFF09",
1526
+ "help.flag.history": "\u5217\u51FA\u5DF2\u5B58\u7684\u57FA\u7EBF \u2014 \u5B8C\u5168\u4E0D\u626B\u63CF",
1527
+ "help.flag.phantom": "\u4EC5 stats\uFF1A\u6E90\u7801\u4E2D\u51FA\u73B0\u4F46\u65E0\u5904\u58F0\u660E\u7684\u5BFC\u5165\uFF08\u5C3D\u529B\u800C\u4E3A\u7684\u6B63\u5219\u5BA1\u8BA1\uFF09",
1528
+ "help.flag.dead": "\u4EC5 stats\uFF1A\u5DF2\u5B89\u88C5\u4E14\u5DF2\u58F0\u660E\u4F46\u4ECE\u672A\u5BFC\u5165\uFF08\u5C3D\u529B\u800C\u4E3A\u7684\u6B63\u5219\u5BA1\u8BA1\uFF09",
1529
+ "help.flag.licenses": "\u4EC5 stats\uFF1A\u6309\u8BB8\u53EF\u8BC1\u5B57\u6BB5\u7ED9\u5B9E\u4F8B\u5206\u6876\uFF1B\u6807\u8BB0\u751F\u4EA7\u4F9D\u8D56\u4E2D\u7684 copyleft",
1530
+ "help.flag.score": "\u4EC5 stats\uFF1A\u5B9E\u9A8C\u6027\u7684 0-100 \u7EFC\u5408\u81C3\u80BF\u8BC4\u5206",
1531
+ "help.flag.co2": "\u4EC5 stats\uFF1A\u5B9E\u9A8C\u6027\u78B3\u6392\u653E\u4F30\u7B97\uFF08\u4E00\u5E74\u5B58\u50A8 + \u4E00\u6B21\u91CD\u65B0\u4E0B\u8F7D\uFF09",
1532
+ "help.flag.online": "\u4EC5 stats\uFF1A\u5DF2\u5F03\u7528\u626B\u63CF \u2014 \u79BB\u7EBF manifest + \u60F0\u6027\u7F13\u5B58\u7684 registry \u56DE\u9000",
1533
+ "help.flag.graph": "\u4EC5 stats\uFF1A\u6765\u81EA lockfile \u7684\u4F9D\u8D56\u56FE\uFF08npm/yarn/pnpm/bun\uFF09\uFF0C\u5E26 BFS \u6DF1\u5EA6",
1534
+ "help.flag.reinstall": "\u4EC5 stats\uFF1Anpm-ci \u98CE\u683C\u7684\u7C97\u7565\u91CD\u88C5\u8017\u65F6\u4F30\u7B97",
1535
+ "help.flag.out": "\u4EC5 treemap\uFF1AHTML \u6587\u4EF6\u7684\u5199\u5165\u4F4D\u7F6E\uFF08\u540C --treemap <file>\uFF09",
1536
+ "help.flag.defaultExclude": '\u7BA1\u7406\u6301\u4E45\u5316\u7684 exclude \u5217\u8868\uFF08\u9017\u53F7\u5217\u8868\uFF1B\u7279\u6B8A\u503C "self"\uFF09',
1537
+ "help.flag.defaultKeep": '\u7BA1\u7406\u6301\u4E45\u5316\u7684 keep \u5217\u8868\uFF08\u9017\u53F7\u5217\u8868\uFF1B\u7279\u6B8A\u503C "self"\uFF09',
1538
+ "help.flag.defaultMode": "\u8BBE\u7F6E\u6301\u4E45\u5316\u7684\u5220\u9664\u9ED8\u8BA4\u503C\uFF08hard | soft | trash\uFF09",
1539
+ "help.flag.logDir": "\u8BBE\u7F6E\u6301\u4E45\u5316\u7684\u6062\u590D\u65E5\u5FD7\u76EE\u5F55\uFF08logDir\uFF09",
1540
+ "help.ex.bare": "\u5411\u5BFC\uFF1B\u65E0\u53C2\u6570\u83DC\u5355\u81EA\u52A8\u4E0A\u6EAF\u5230\u6700\u8FD1\u7684\u9879\u76EE\u6839",
1541
+ "help.ex.wizardDir": "\u5411\u5BFC\u9650\u5B9A\u4E8E\u663E\u5F0F\u76EE\u6807 \u2014 \u4E0D\u81EA\u52A8\u4E0A\u6EAF",
1542
+ "help.ex.wizardRouter": "v1.2 \u8DEF\u7531\uFF1A\u5148\u6253\u5F00 stats \u89C6\u56FE\uFF0C\u518D\u8FDB\u5411\u5BFC\u83DC\u5355",
1543
+ "help.ex.multiTarget": "\u591A\u76EE\u6807\u626B\u63CF",
1544
+ "help.ex.stale": "\u63A9\u57CB\u9648\u65E7\u9057\u9AB8\uFF0C\u53EF\u6062\u590D\u7684\u56DE\u6536\u7AD9",
1545
+ "help.ex.why": "\u53CD\u5411\u4F9D\u8D56\uFF1A\u8C01\u58F0\u660E + \u8C01\u4F9D\u8D56",
1546
+ "help.ex.byType": "\u4F5C\u4E3A\u673A\u5668\u8F7D\u8377\u7684\u4F9D\u8D56\u5B57\u6BB5\u7EC6\u5206",
1547
+ "help.ex.globalTop": "\u5404 PM \u4E2D\u6700\u5927\u7684 20 \u4E2A\u5168\u5C40\u5B89\u88C5",
1548
+ "help.ex.updateCheck": "\u5BF9\u6BD4\u5DF2\u88C5\u7248\u672C\u4E0E registry \u2014 \u4E0D\u5B89\u88C5\u4EFB\u4F55\u4E1C\u897F",
1549
+ "help.ex.configSet": "\u5728 .nmhrc \u4E2D\u6301\u4E45\u5316\u9ED8\u8BA4\u5220\u9664\u65B9\u5F0F",
1550
+ "help.footer.safety": "\u5B89\u5168\u7B2C\u4E00\uFF1A\u62A4\u680F\u62D2\u7EDD\u5371\u9669\u76EE\u6807\uFF08\u9000\u51FA\u7801 3\uFF09\uFF0C\u5220\u9664\u9700\u786E\u8BA4\u9664\u975E --yes/--force\uFF0C\u7B26\u53F7\u94FE\u63A5\u7EDD\u4E0D\u8DDF\u968F\u3002",
1551
+ "help.footer.exitCodes": "\u9000\u51FA\u7801\uFF1A0 \u6B63\u5E38 \xB7 1 \u7528\u6CD5\u9519\u8BEF \xB7 2 \u672A\u627E\u5230 \xB7 3 \u62A4\u680F\u62D2\u7EDD \xB7 4 \u6743\u9650\u4E0D\u8DB3\u3002",
1552
+ "help.footer.docs": "\u6240\u6709\u5185\u5BB9\u90FD\u5728\u8FD9\u91CC\u6709\u6DF1\u5165\u6587\u6863\uFF1Ahttps://github.com/jhedev96/node-modules-hunter",
1516
1553
  // ── cli.ts guards & usage errors ────────────────────────────────────────
1517
- "cli.err.configNeedsPath": "--config needs a file path \u2014 nmh --config <file> \u2026",
1518
- "cli.err.languageNeedsValue": "--language needs a value \u2014 nmh --language id (en | id | zh | ru | es)",
1519
- "cli.err.invalidLanguage": "invalid --language: {value} (expected en | id | zh | ru | es)",
1520
- "cli.warn.futureFlag": "{flag} lands in a later version (v0.2+) \u2014 ignored for now",
1521
- "cli.warn.sizeTopN": "--size <n> (top-N list) lands in a later version \u2014 listing every folder for now",
1522
- "cli.err.invalidSize": "invalid --size: {value} (expected 'total' or 'each')",
1523
- "cli.err.sizeNeedsValue": "--size needs a value \u2014 use --size=total or --size=each (a bare --size doesn't select a mode)",
1524
- "cli.err.sizeTwice": "--size given more than once \u2014 pass a single value (total | each)",
1525
- "cli.err.staleNeedsValue": "--stale needs a value \u2014 use --stale=<days> (e.g. --stale=90)",
1526
- "cli.err.staleTwice": "--stale given more than once \u2014 pass a single value (days)",
1527
- "cli.err.invalidStale": "invalid --stale: {value} (expected a positive whole number of days)",
1528
- "cli.err.sortNeedsValue": "--sort needs a value \u2014 use --sort=size | path | idle | mtime",
1529
- "cli.err.sortTwice": "--sort given more than once \u2014 pass a single key",
1530
- "cli.err.invalidSort": "invalid --sort: {key} (expected size | path | idle | mtime)",
1531
- "cli.err.trashNeedsValue": "--trash needs a value \u2014 use --trash=system or --trash=nmh",
1532
- "cli.err.trashTwice": "--trash given more than once \u2014 pass a single mode",
1533
- "cli.err.invalidTrash": "invalid --trash: {mode} (expected system | nmh)",
1534
- "cli.err.invalidDelete": "invalid --delete: {value} (expected 'hard' | 'soft' | 'trash')",
1535
- "cli.verbose.deleteModeFromRc": "delete mode from .nmhrc: {mode}",
1536
- "cli.err.invalidPm": "invalid --pm: {value} (expected npm | pnpm | yarn | bun | vp)",
1537
- "cli.err.depthNeedsValue": "--depth needs a non-negative integer \u2014 use --depth=<n> (e.g. --depth=2)",
1538
- "cli.err.invalidDepth": "invalid --depth: {value} (expected a non-negative integer)",
1539
- "cli.err.saveReportNeedsValue": "--save-report needs a file path (.json/.md/.txt)",
1540
- "cli.err.reportNeedsValue": "--report needs a file path (.json/.md/.txt)",
1541
- "cli.err.invalidReportExt": "unknown report format: {file} (expected .json/.md/.txt)",
1542
- "cli.err.baselineNeedsName": "--save-baseline needs a name \u2014 nmh stats --save-baseline <name>",
1543
- "cli.err.compareNeedsName": "--compare needs a name \u2014 nmh stats --compare <name>",
1544
- "cli.err.invalidBaseline": "invalid baseline name: '{name}' (expected letters/digits/._-, max 64)",
1545
- "cli.err.unknownCommand": "unknown command '{cmd}' \u2014 run `nmh help` for the command list (paths are passed to `nmh scan` or `--dir`)",
1546
- "cli.err.pmBare": "--pm without a value only lists detected PMs \u2014 give a family (npm|pnpm|yarn|bun|vp) to filter a delete op or the --global analysis",
1547
- "cli.err.reportNotDelete": "--save-report rides along with scan \u2014 delete/clean runs are not scan reports",
1548
- "cli.warn.trashOnly": "--trash only matters for delete/clean runs \u2014 ignored for scans and read-only commands",
1549
- "cli.err.rootRefusal": "refusing a delete op over the filesystem root \u2014 point --dir at the project directory you want cleaned",
1550
- "cli.err.checkOnlyUpdate": "--check only works with the update command \u2014 nmh update --check",
1551
- "cli.err.infoOnlyUpdate": "--info only works with the update command \u2014 nmh update --info",
1552
- "cli.err.updateArgs": "update takes no arguments \u2014 plain `nmh update` (add --json for the payload)",
1553
- "cli.err.checkInfoExclusive": "--check and --info are two different read-only views \u2014 pick one (nmh update --check | --info)",
1554
- "cli.err.routerOrphan": "the `--` router belongs to the wizard \u2014 nmh wizard -- stats|map|search|why|treemap \u2026",
1555
- "cli.err.unknownWizardView": "unknown wizard view: {view} \u2014 the router opens a read-only view: stats (analyze, info) | map | search | why | treemap",
1556
- "cli.err.wizardPositional": "wizard takes no positional targets \u2014 scope it with --dir=./repo1,./repo2 (or `nmh wizard -- <view> \u2026`)",
1557
- "cli.err.wizardDelete": "--delete does not belong to the wizard \u2014 the menu asks for the mode itself",
1558
- "cli.err.wizardNeedsTTY": "the wizard needs a TTY (it is an arrow-key menu) \u2014 use nmh scan / --dir / the plain commands instead; bare `nmh` in a pipe stays a read-only scan",
1559
- "cli.err.configOp": "config needs an op \u2014 nmh config info | set | add | remove | unset (take a look: nmh config info)",
1560
- "cli.err.configPositional": "config {op} takes no positional args \u2014 use flags (--default-exclude \u2026, --depth \u2026)",
1561
- "cli.err.configDelete": "--delete does not belong to nmh config \u2014 it manages the .nmhrc file, that is all",
1562
- "cli.err.statsFlagsOnly": "--phantom/--dead/--licenses/--score/--co2/--online/--graph/--reinstall only work with the stats command \u2014 nmh stats --reinstall",
1563
- "cli.err.searchReadOnly": "--search is read-only \u2014 combine it with scan, not with delete/clean",
1564
- "cli.err.searchNeedsPattern": "search needs a pattern \u2014 nmh search <pattern> [dirs]",
1565
- "cli.err.whyReadOnly": "--why is read-only \u2014 combine it with scan, not with delete/clean",
1566
- "cli.err.whyNeedsPkg": "why needs a package name \u2014 nmh why <pkg> [dirs]",
1567
- "cli.err.whyConflict": "--why ({why}) conflicts with the why subcommand's package ({pkg}) \u2014 pick one",
1568
- "cli.err.whyFlagNeedsPkg": "--why needs a package name \u2014 nmh why <pkg> [dirs]",
1569
- "cli.err.treemapReadOnly": "--treemap is read-only \u2014 combine it with scan, not with delete/clean",
1570
- "cli.err.reportNotTreemap": "--save-report does not work with treemap \u2014 the HTML file IS the report (nmh treemap --out <file>)",
1571
- "cli.err.outNeedsValue": "--out needs a file path \u2014 nmh treemap --out report.html",
1572
- "cli.err.outOnlyTreemap": "--out only works with the treemap command \u2014 nmh treemap --out file.html",
1573
- "cli.err.invalidBy": "invalid --by: {value} (expected 'package' | 'size' | 'type' | 'licenses')",
1574
- "cli.err.dependOnlyMap": "--depend only works with the map command \u2014 nmh map <dirs> --depend [pkg]",
1575
- "cli.err.treeMapStats": "--tree works with map or stats, --depend is map-only \u2014 nmh map <dirs> --depend [pkg]",
1576
- "cli.err.mapReadOnly": "--map is read-only \u2014 combine it with scan, not with delete/clean",
1577
- "cli.err.baselineOnlyStats": "--save-baseline/--compare/--history only work with the stats command \u2014 nmh stats --save-baseline <name>",
1578
- "cli.err.statsReadOnly": "--stats is read-only \u2014 combine it with scan, not with delete/clean",
1579
- "cli.err.globalShapeFlags": "--tree/--top/--by/--graph/--reinstall shape per-project stats \u2014 global mode has its own table",
1580
- "cli.err.globalNoDir": "--global analyzes the PM global prefixes \u2014 no [dir] needed",
1581
- "cli.err.invalidTop": "invalid --top: {value} (expected a positive integer)",
1582
- "cli.err.topByStats": "--top/--by only work with the stats command",
1583
- "cli.err.globalOnlyStats": "--global only works with the stats command \u2014 nmh stats -g",
1584
- "cli.err.trashNotHard": "--trash applies to trash mode \u2014 hard delete is permanent by design, there is no trash to choose",
1585
- "cli.err.deleteNeedsTty": "--delete without a value needs an interactive terminal \u2014 pass hard | soft | trash (soft = trash)",
1586
- "cli.verbose.configSource": "config: {file}",
1587
- "cli.verbose.configFamilySkip": "config: read-phase lookup skipped for the config family",
1554
+ "cli.err.configNeedsPath": "--config \u9700\u8981\u6587\u4EF6\u8DEF\u5F84 \u2014 nmh --config <file> \u2026",
1555
+ "cli.err.languageNeedsValue": "--language \u9700\u8981\u4E00\u4E2A\u503C \u2014 nmh --language id\uFF08en | id | zh | ru | es\uFF09",
1556
+ "cli.err.invalidLanguage": "\u65E0\u6548\u7684 --language\uFF1A{value}\uFF08\u5E94\u4E3A en | id | zh | ru | es\uFF09",
1557
+ "cli.warn.futureFlag": "{flag} \u5C06\u5728\u540E\u7EED\u7248\u672C\uFF08v0.2+\uFF09\u51FA\u73B0 \u2014 \u5F53\u524D\u5FFD\u7565",
1558
+ "cli.warn.sizeTopN": "--size <n>\uFF08top-N \u5217\u8868\uFF09\u5C06\u5728\u540E\u7EED\u7248\u672C\u51FA\u73B0 \u2014 \u5F53\u524D\u5217\u51FA\u6BCF\u4E2A\u6587\u4EF6\u5939",
1559
+ "cli.err.invalidSize": "\u65E0\u6548\u7684 --size\uFF1A{value}\uFF08\u5E94\u4E3A 'total' \u6216 'each'\uFF09",
1560
+ "cli.err.sizeNeedsValue": "--size \u9700\u8981\u4E00\u4E2A\u503C \u2014 \u7528 --size=total \u6216 --size=each\uFF08\u88F8 --size \u4E0D\u9009\u62E9\u6A21\u5F0F\uFF09",
1561
+ "cli.err.sizeTwice": "--size \u4F20\u4E86\u591A\u6B21 \u2014 \u53EA\u4F20\u4E00\u4E2A\u503C\uFF08total | each\uFF09",
1562
+ "cli.err.staleNeedsValue": "--stale \u9700\u8981\u4E00\u4E2A\u503C \u2014 \u7528 --stale=<days>\uFF08\u5982 --stale=90\uFF09",
1563
+ "cli.err.staleTwice": "--stale \u4F20\u4E86\u591A\u6B21 \u2014 \u53EA\u4F20\u4E00\u4E2A\u503C\uFF08\u5929\u6570\uFF09",
1564
+ "cli.err.invalidStale": "\u65E0\u6548\u7684 --stale\uFF1A{value}\uFF08\u5E94\u4E3A\u6B63\u6574\u6570\u5929\u6570\uFF09",
1565
+ "cli.err.sortNeedsValue": "--sort \u9700\u8981\u4E00\u4E2A\u503C \u2014 \u7528 --sort=size | path | idle | mtime",
1566
+ "cli.err.sortTwice": "--sort \u4F20\u4E86\u591A\u6B21 \u2014 \u53EA\u4F20\u4E00\u4E2A\u952E",
1567
+ "cli.err.invalidSort": "\u65E0\u6548\u7684 --sort\uFF1A{key}\uFF08\u5E94\u4E3A size | path | idle | mtime\uFF09",
1568
+ "cli.err.trashNeedsValue": "--trash \u9700\u8981\u4E00\u4E2A\u503C \u2014 \u7528 --trash=system \u6216 --trash=nmh",
1569
+ "cli.err.trashTwice": "--trash \u4F20\u4E86\u591A\u6B21 \u2014 \u53EA\u4F20\u4E00\u4E2A\u6A21\u5F0F",
1570
+ "cli.err.invalidTrash": "\u65E0\u6548\u7684 --trash\uFF1A{mode}\uFF08\u5E94\u4E3A system | nmh\uFF09",
1571
+ "cli.err.invalidDelete": "\u65E0\u6548\u7684 --delete\uFF1A{value}\uFF08\u5E94\u4E3A 'hard' | 'soft' | 'trash'\uFF09",
1572
+ "cli.verbose.deleteModeFromRc": "\u6765\u81EA .nmhrc \u7684\u5220\u9664\u65B9\u5F0F\uFF1A{mode}",
1573
+ "cli.err.invalidPm": "\u65E0\u6548\u7684 --pm\uFF1A{value}\uFF08\u5E94\u4E3A npm | pnpm | yarn | bun | vp\uFF09",
1574
+ "cli.err.depthNeedsValue": "--depth \u9700\u8981\u975E\u8D1F\u6574\u6570 \u2014 \u7528 --depth=<n>\uFF08\u5982 --depth=2\uFF09",
1575
+ "cli.err.invalidDepth": "\u65E0\u6548\u7684 --depth\uFF1A{value}\uFF08\u5E94\u4E3A\u975E\u8D1F\u6574\u6570\uFF09",
1576
+ "cli.err.saveReportNeedsValue": "--save-report \u9700\u8981\u6587\u4EF6\u8DEF\u5F84\uFF08.json/.md/.txt\uFF09",
1577
+ "cli.err.reportNeedsValue": "--report \u9700\u8981\u6587\u4EF6\u8DEF\u5F84\uFF08.json/.md/.txt\uFF09",
1578
+ "cli.err.invalidReportExt": "\u672A\u77E5\u7684\u62A5\u544A\u683C\u5F0F\uFF1A{file}\uFF08\u5E94\u4E3A .json/.md/.txt\uFF09",
1579
+ "cli.err.baselineNeedsName": "--save-baseline \u9700\u8981\u540D\u79F0 \u2014 nmh stats --save-baseline <name>",
1580
+ "cli.err.compareNeedsName": "--compare \u9700\u8981\u540D\u79F0 \u2014 nmh stats --compare <name>",
1581
+ "cli.err.invalidBaseline": "\u65E0\u6548\u7684\u57FA\u7EBF\u540D\u79F0\uFF1A'{name}'\uFF08\u5E94\u4E3A\u5B57\u6BCD/\u6570\u5B57/._-\uFF0C\u6700\u591A 64\uFF09",
1582
+ "cli.err.unknownCommand": "\u672A\u77E5\u547D\u4EE4 '{cmd}' \u2014 \u8FD0\u884C `nmh help` \u67E5\u770B\u547D\u4EE4\u5217\u8868\uFF08\u8DEF\u5F84\u4F1A\u4F20\u7ED9 `nmh scan` \u6216 `--dir`\uFF09",
1583
+ "cli.err.pmBare": "\u4E0D\u5E26\u503C\u7684 --pm \u4EC5\u5217\u51FA\u68C0\u6D4B\u5230\u7684 PM \u2014 \u7ED9\u51FA\u5BB6\u65CF\uFF08npm|pnpm|yarn|bun|vp\uFF09\u4EE5\u8FC7\u6EE4\u5220\u9664\u64CD\u4F5C\u6216 --global \u5206\u6790",
1584
+ "cli.err.reportNotDelete": "--save-report \u53EA\u968F scan \u4F7F\u7528 \u2014 delete/clean \u8FD0\u884C\u4E0D\u662F\u626B\u63CF\u62A5\u544A",
1585
+ "cli.warn.trashOnly": "--trash \u53EA\u5BF9 delete/clean \u8FD0\u884C\u6709\u610F\u4E49 \u2014 \u626B\u63CF\u548C\u53EA\u8BFB\u547D\u4EE4\u4E2D\u5FFD\u7565",
1586
+ "cli.err.rootRefusal": "\u62D2\u7EDD\u5728\u6587\u4EF6\u7CFB\u7EDF\u6839\u76EE\u5F55\u4E0A\u6267\u884C\u5220\u9664 \u2014 \u628A --dir \u6307\u5411\u8981\u6E05\u7406\u7684\u9879\u76EE\u76EE\u5F55",
1587
+ "cli.err.checkOnlyUpdate": "--check \u53EA\u9002\u7528\u4E8E update \u547D\u4EE4 \u2014 nmh update --check",
1588
+ "cli.err.infoOnlyUpdate": "--info \u53EA\u9002\u7528\u4E8E update \u547D\u4EE4 \u2014 nmh update --info",
1589
+ "cli.err.tagNeedsValue": "--tag \u9700\u8981 dist-tag \u540D\u79F0 \u2014 nmh update --tag beta\uFF08\u4E0D\u5E26\u503C\u7684 --check \u8BFB\u53D6 --tag / .nmhrc / latest\uFF09",
1590
+ "cli.err.invalidTag": 'dist-tag "{value}" \u65E0\u6548 \u2014 \u53EA\u80FD\u4F7F\u7528\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u8FDE\u5B57\u7B26\u3001\u4E0B\u5212\u7EBF',
1591
+ "cli.err.tagOnlyUpdate": "--tag \u53EA\u9002\u7528\u4E8E update \u547D\u4EE4 \u2014 nmh update --tag beta",
1592
+ "cli.err.updateArgs": "update \u4E0D\u63A5\u53D7\u53C2\u6570 \u2014 \u76F4\u63A5 `nmh update`\uFF08\u52A0 --json \u83B7\u53D6\u8F7D\u8377\uFF09",
1593
+ "cli.err.checkInfoExclusive": "--check \u4E0E --info \u662F\u4E24\u4E2A\u4E0D\u540C\u7684\u53EA\u8BFB\u89C6\u56FE \u2014 \u4E8C\u9009\u4E00\uFF08nmh update --check | --info\uFF09",
1594
+ "cli.err.routerOrphan": "`--` \u8DEF\u7531\u5C5E\u4E8E\u5411\u5BFC \u2014 nmh wizard -- stats|map|search|why|treemap \u2026",
1595
+ "cli.err.unknownWizardView": "\u672A\u77E5\u7684\u5411\u5BFC\u89C6\u56FE\uFF1A{view} \u2014 \u8DEF\u7531\u53EF\u6253\u5F00\u53EA\u8BFB\u89C6\u56FE\uFF1Astats\uFF08analyze\u3001info\uFF09| map | search | why | treemap",
1596
+ "cli.err.wizardPositional": "\u5411\u5BFC\u4E0D\u63A5\u53D7\u4F4D\u7F6E\u76EE\u6807 \u2014 \u7528 --dir=./repo1,./repo2 \u9650\u5B9A\uFF08\u6216 `nmh wizard -- <view> \u2026`\uFF09",
1597
+ "cli.err.wizardDelete": "--delete \u4E0D\u5C5E\u4E8E\u5411\u5BFC \u2014 \u83DC\u5355\u4F1A\u81EA\u5DF1\u8BE2\u95EE\u65B9\u5F0F",
1598
+ "cli.err.wizardNeedsTTY": "\u5411\u5BFC\u9700\u8981 TTY\uFF08\u5B83\u662F\u65B9\u5411\u952E\u83DC\u5355\uFF09\u2014 \u8BF7\u6539\u7528 nmh scan / --dir / \u666E\u901A\u547D\u4EE4\uFF1B\u7BA1\u9053\u4E2D\u7684\u88F8 `nmh` \u4ECD\u662F\u4E00\u6B21\u53EA\u8BFB\u626B\u63CF",
1599
+ "cli.err.configOp": "config \u9700\u8981\u4E00\u4E2A\u64CD\u4F5C \u2014 nmh config info | set | add | remove | unset\uFF08\u53EF\u5148\u770B\u770B\uFF1Anmh config info\uFF09",
1600
+ "cli.err.configPositional": "config {op} \u4E0D\u63A5\u53D7\u4F4D\u7F6E\u53C2\u6570 \u2014 \u7528 flag\uFF08--default-exclude \u2026\u3001--depth \u2026\uFF09",
1601
+ "cli.err.configDelete": "--delete \u4E0D\u5C5E\u4E8E nmh config \u2014 \u5B83\u53EA\u7BA1\u7406 .nmhrc \u6587\u4EF6\uFF0C\u4EC5\u6B64\u800C\u5DF2",
1602
+ "cli.err.statsFlagsOnly": "--phantom/--dead/--licenses/--score/--co2/--online/--graph/--reinstall \u53EA\u9002\u7528\u4E8E stats \u547D\u4EE4 \u2014 nmh stats --reinstall",
1603
+ "cli.err.searchReadOnly": "--search \u662F\u53EA\u8BFB\u7684 \u2014 \u4E0E scan \u7EC4\u5408\uFF0C\u800C\u975E delete/clean",
1604
+ "cli.err.searchNeedsPattern": "search \u9700\u8981\u6A21\u5F0F \u2014 nmh search <pattern> [dirs]",
1605
+ "cli.err.whyReadOnly": "--why \u662F\u53EA\u8BFB\u7684 \u2014 \u4E0E scan \u7EC4\u5408\uFF0C\u800C\u975E delete/clean",
1606
+ "cli.err.whyNeedsPkg": "why \u9700\u8981\u5305\u540D \u2014 nmh why <pkg> [dirs]",
1607
+ "cli.err.whyConflict": "--why\uFF08{why}\uFF09\u4E0E why \u5B50\u547D\u4EE4\u7684\u5305\uFF08{pkg}\uFF09\u51B2\u7A81 \u2014 \u4E8C\u9009\u4E00",
1608
+ "cli.err.whyFlagNeedsPkg": "--why \u9700\u8981\u5305\u540D \u2014 nmh why <pkg> [dirs]",
1609
+ "cli.err.treemapReadOnly": "--treemap \u662F\u53EA\u8BFB\u7684 \u2014 \u4E0E scan \u7EC4\u5408\uFF0C\u800C\u975E delete/clean",
1610
+ "cli.err.reportNotTreemap": "--save-report \u4E0D\u9002\u7528\u4E8E treemap \u2014 HTML \u6587\u4EF6\u5C31\u662F\u62A5\u544A\uFF08nmh treemap --out <file>\uFF09",
1611
+ "cli.err.outNeedsValue": "--out \u9700\u8981\u6587\u4EF6\u8DEF\u5F84 \u2014 nmh treemap --out report.html",
1612
+ "cli.err.outOnlyTreemap": "--out \u53EA\u9002\u7528\u4E8E treemap \u547D\u4EE4 \u2014 nmh treemap --out file.html",
1613
+ "cli.err.invalidBy": "\u65E0\u6548\u7684 --by\uFF1A{value}\uFF08\u5E94\u4E3A 'package' | 'size' | 'type' | 'licenses'\uFF09",
1614
+ "cli.err.dependOnlyMap": "--depend \u53EA\u9002\u7528\u4E8E map \u547D\u4EE4 \u2014 nmh map <dirs> --depend [pkg]",
1615
+ "cli.err.treeMapStats": "--tree \u9002\u7528\u4E8E map \u6216 stats\uFF0C--depend \u4EC5\u9650 map \u2014 nmh map <dirs> --depend [pkg]",
1616
+ "cli.err.mapReadOnly": "--map \u662F\u53EA\u8BFB\u7684 \u2014 \u4E0E scan \u7EC4\u5408\uFF0C\u800C\u975E delete/clean",
1617
+ "cli.err.baselineOnlyStats": "--save-baseline/--compare/--history \u53EA\u9002\u7528\u4E8E stats \u547D\u4EE4 \u2014 nmh stats --save-baseline <name>",
1618
+ "cli.err.statsReadOnly": "--stats \u662F\u53EA\u8BFB\u7684 \u2014 \u4E0E scan \u7EC4\u5408\uFF0C\u800C\u975E delete/clean",
1619
+ "cli.err.globalShapeFlags": "--tree/--top/--by/--graph/--reinstall \u5851\u9020\u9010\u9879\u76EE stats \u2014 \u5168\u5C40\u6A21\u5F0F\u6709\u81EA\u5DF1\u7684\u8868\u683C",
1620
+ "cli.err.globalNoDir": "--global \u5206\u6790 PM \u7684\u5168\u5C40\u524D\u7F00 \u2014 \u4E0D\u9700\u8981 [dir]",
1621
+ "cli.err.invalidTop": "\u65E0\u6548\u7684 --top\uFF1A{value}\uFF08\u5E94\u4E3A\u6B63\u6574\u6570\uFF09",
1622
+ "cli.err.topByStats": "--top/--by \u53EA\u9002\u7528\u4E8E stats \u547D\u4EE4",
1623
+ "cli.err.globalOnlyStats": "--global \u53EA\u9002\u7528\u4E8E stats \u547D\u4EE4 \u2014 nmh stats -g",
1624
+ "cli.err.trashNotHard": "--trash \u9002\u7528\u4E8E\u56DE\u6536\u7AD9\u6A21\u5F0F \u2014 \u5F7B\u5E95\u5220\u9664\u6309\u8BBE\u8BA1\u5C31\u662F\u6C38\u4E45\u7684\uFF0C\u6CA1\u6709\u56DE\u6536\u7AD9\u53EF\u9009",
1625
+ "cli.err.deleteNeedsTty": "\u4E0D\u5E26\u503C\u7684 --delete \u9700\u8981\u4EA4\u4E92\u5F0F\u7EC8\u7AEF \u2014 \u4F20\u5165 hard | soft | trash\uFF08soft = trash\uFF09",
1626
+ "cli.verbose.configSource": "config\uFF1A{file}",
1627
+ "cli.verbose.configFamilySkip": "config\uFF1Aconfig \u5BB6\u65CF\u8DF3\u8FC7\u8BFB\u53D6\u9636\u6BB5\u67E5\u627E",
1588
1628
  // ── config family ───────────────────────────────────────────────────────
1589
- "config.err.notJson": "invalid config: {file} is not valid JSON ({detail})",
1590
- "config.err.notJsonWritable": "invalid config: {file} is not valid JSON ({detail}) \u2014 fix it before nmh config writes",
1591
- "config.err.notObject": "invalid config: {file} must contain a JSON object",
1592
- "config.err.invalidMode": "invalid config: {file}: defaultMode must be 'hard' | 'soft' | 'trash' (got {value})",
1593
- "config.err.invalidDepth": "invalid config: {file}: depth must be a non-negative integer (got {value})",
1594
- "config.err.invalidList": "invalid config: {file}: {key} must be an array of non-empty strings",
1595
- "config.err.notBoolean": "invalid config: {file}: {key} must be true or false (got {value})",
1596
- "config.err.invalidLanguage": "invalid config: {file}: language must be one of en | id | zh | ru | es (got {value})",
1597
- "config.err.invalidLogDir": "invalid config: {file}: logDir must be a non-empty string",
1598
- "config.err.unreadable": "config unreadable: {file} ({code})",
1599
- "config.err.notFound": "config file not found: {file}",
1600
- "config.warn.unknownKey": '{file}: unknown config key "{key}" \u2014 ignored',
1601
- "config.err.depthNeedsValue": "--depth needs a non-negative integer \u2014 nmh config set --depth 2",
1602
- "config.err.invalidDepthValue": "invalid --depth value: {value} (expected a non-negative integer)",
1603
- "config.err.invalidModeValue": "invalid --default-mode: {value} (expected hard | soft | trash)",
1604
- "config.err.invalidLanguageValue": "invalid --language value: {value} (expected en | id | zh | ru | es)",
1605
- "config.err.boolNeedsValue": "{label} needs true or false \u2014 e.g. nmh config set --animate=false",
1606
- "config.err.setListNeedsValue": "config set --{flag} needs the list value \u2014 e.g. --{flag}=.npm,.nvm",
1607
- "config.err.addListNeedsValue": "config add --{flag} needs items to append \u2014 e.g. --{flag}=.cache,self",
1608
- "config.err.logDirNeedsValue": "--log-dir needs a non-empty directory path",
1609
- "config.err.setNeedsKey": "config set needs at least one key \u2014 nmh config set --depth 2 | --default-mode trash | --default-exclude .npm,self | \u2026",
1610
- "config.err.listOpsOnly": "config {op} works on list keys \u2014 use --default-exclude or --default-keep",
1611
- "config.err.unsetNeedsKey": "config unset needs a key \u2014 e.g. nmh config unset --default-exclude (or --depth)",
1612
- "config.err.infoReadOnly": "nmh config info is read-only \u2014 key flags belong to set/add/remove",
1613
- "config.info.activeFile": "active file",
1614
- "config.info.noFile": "none \u2014 defaults in effect (create one: nmh config set \u2026)",
1615
- "config.info.items": "{n} item(s): {list}",
1616
- "config.info.manageHint": "manage: nmh config set \xB7 add \xB7 remove \xB7 unset (lists: --default-exclude / --default-keep)",
1617
- "config.info.selfHint": 'special value "self" in exclude/keep = protect the folder nmh runs from (scan-level guard)',
1618
- "config.info.removed": "(removed from file)"
1629
+ "config.err.notJson": "\u65E0\u6548\u914D\u7F6E\uFF1A{file} \u4E0D\u662F\u5408\u6CD5 JSON\uFF08{detail}\uFF09",
1630
+ "config.err.notJsonWritable": "\u65E0\u6548\u914D\u7F6E\uFF1A{file} \u4E0D\u662F\u5408\u6CD5 JSON\uFF08{detail}\uFF09\u2014 \u5728 nmh config \u5199\u5165\u524D\u5148\u4FEE\u590D",
1631
+ "config.err.notObject": "\u65E0\u6548\u914D\u7F6E\uFF1A{file} \u5FC5\u987B\u5305\u542B\u4E00\u4E2A JSON \u5BF9\u8C61",
1632
+ "config.err.invalidMode": "\u65E0\u6548\u914D\u7F6E\uFF1A{file}\uFF1AdefaultMode \u5FC5\u987B\u662F 'hard' | 'soft' | 'trash'\uFF08\u5F97\u5230 {value}\uFF09",
1633
+ "config.err.invalidDepth": "\u65E0\u6548\u914D\u7F6E\uFF1A{file}\uFF1Adepth \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570\uFF08\u5F97\u5230 {value}\uFF09",
1634
+ "config.err.invalidList": "\u65E0\u6548\u914D\u7F6E\uFF1A{file}\uFF1A{key} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u6570\u7EC4",
1635
+ "config.err.notBoolean": "\u65E0\u6548\u914D\u7F6E\uFF1A{file}\uFF1A{key} \u5FC5\u987B\u662F true \u6216 false\uFF08\u5F97\u5230 {value}\uFF09",
1636
+ "config.err.invalidLanguage": "\u65E0\u6548\u914D\u7F6E\uFF1A{file}\uFF1Alanguage \u5FC5\u987B\u662F en | id | zh | ru | es \u4E4B\u4E00\uFF08\u5F97\u5230 {value}\uFF09",
1637
+ "config.err.invalidLogDir": "\u65E0\u6548\u914D\u7F6E\uFF1A{file}\uFF1AlogDir \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32",
1638
+ "config.err.invalidUpdateTag": "\u65E0\u6548\u914D\u7F6E\uFF1A{file}\uFF1AupdateTag \u5FC5\u987B\u662F dist-tag \u540D\u79F0 \u2014 \u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u8FDE\u5B57\u7B26\u3001\u4E0B\u5212\u7EBF\uFF08\u5F97\u5230 {value}\uFF09",
1639
+ "config.err.unreadable": "\u914D\u7F6E\u4E0D\u53EF\u8BFB\uFF1A{file}\uFF08{code}\uFF09",
1640
+ "config.err.notFound": "\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A{file}",
1641
+ "config.warn.unknownKey": '{file}\uFF1A\u672A\u77E5\u7684\u914D\u7F6E\u952E "{key}" \u2014 \u5DF2\u5FFD\u7565',
1642
+ "config.err.depthNeedsValue": "--depth \u9700\u8981\u975E\u8D1F\u6574\u6570 \u2014 nmh config set --depth 2",
1643
+ "config.err.invalidDepthValue": "\u65E0\u6548\u7684 --depth \u503C\uFF1A{value}\uFF08\u5E94\u4E3A\u975E\u8D1F\u6574\u6570\uFF09",
1644
+ "config.err.invalidModeValue": "\u65E0\u6548\u7684 --default-mode\uFF1A{value}\uFF08\u5E94\u4E3A hard | soft | trash\uFF09",
1645
+ "config.err.invalidLanguageValue": "\u65E0\u6548\u7684 --language \u503C\uFF1A{value}\uFF08\u5E94\u4E3A en | id | zh | ru | es\uFF09",
1646
+ "config.err.invalidUpdateTagValue": "\u65E0\u6548\u7684 --update-tag \u503C\uFF1A{value}\uFF08\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u8FDE\u5B57\u7B26\u3001\u4E0B\u5212\u7EBF\uFF09",
1647
+ "config.err.boolNeedsValue": "{label} \u9700\u8981 true \u6216 false \u2014 \u5982 nmh config set --animate=false",
1648
+ "config.err.setListNeedsValue": "config set --{flag} \u9700\u8981\u5217\u8868\u503C \u2014 \u5982 --{flag}=.npm,.nvm",
1649
+ "config.err.addListNeedsValue": "config add --{flag} \u9700\u8981\u8981\u8FFD\u52A0\u7684\u9879 \u2014 \u5982 --{flag}=.cache,self",
1650
+ "config.err.logDirNeedsValue": "--log-dir \u9700\u8981\u975E\u7A7A\u7684\u76EE\u5F55\u8DEF\u5F84",
1651
+ "config.err.setNeedsKey": "config set \u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u952E \u2014 nmh config set --depth 2 | --default-mode trash | --default-exclude .npm,self | \u2026",
1652
+ "config.err.listOpsOnly": "config {op} \u53EA\u4F5C\u7528\u4E8E\u5217\u8868\u952E \u2014 \u7528 --default-exclude \u6216 --default-keep",
1653
+ "config.err.unsetNeedsKey": "config unset \u9700\u8981\u4E00\u4E2A\u952E \u2014 \u5982 nmh config unset --default-exclude\uFF08\u6216 --depth\uFF09",
1654
+ "config.err.infoReadOnly": "nmh config info \u662F\u53EA\u8BFB\u7684 \u2014 \u952E flag \u5C5E\u4E8E set/add/remove",
1655
+ "config.info.activeFile": "\u6D3B\u52A8\u6587\u4EF6",
1656
+ "config.info.noFile": "\u65E0 \u2014 \u9ED8\u8BA4\u503C\u751F\u6548\uFF08\u521B\u5EFA\u4E00\u4E2A\uFF1Anmh config set \u2026\uFF09",
1657
+ "config.info.items": "{n} \u9879\uFF1A{list}",
1658
+ "config.info.manageHint": "\u7BA1\u7406\uFF1Anmh config set \xB7 add \xB7 remove \xB7 unset\uFF08\u5217\u8868\uFF1A--default-exclude / --default-keep\uFF09",
1659
+ "config.info.selfHint": 'exclude/keep \u4E2D\u7684\u7279\u6B8A\u503C "self" = \u4FDD\u62A4 nmh \u81EA\u8EAB\u6240\u5728\u7684\u6587\u4EF6\u5939\uFF08\u626B\u63CF\u7EA7\u62A4\u680F\uFF09',
1660
+ "config.info.removed": "\uFF08\u5DF2\u4ECE\u6587\u4EF6\u79FB\u9664\uFF09"
1619
1661
  };
1620
1662
  var zh_default = zh;
1621
1663
 
1622
1664
  // src/i18n/locales/ru.ts
1623
1665
  var ru = {
1624
1666
  // ── banner ──────────────────────────────────────────────────────────────
1625
- "banner.tagline": "scan \xB7 measure \xB7 clean \u2014 safety rails on",
1626
- "banner.compact": "read-only scan",
1627
- "banner.updateLine": "\u2191 {version} available \u2014 run `nmh update`",
1667
+ "banner.tagline": "\u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \xB7 \u0438\u0437\u043C\u0435\u0440\u0435\u043D\u0438\u0435 \xB7 \u043E\u0447\u0438\u0441\u0442\u043A\u0430 \u2014 \u0437\u0430\u0449\u0438\u0442\u0430 \u0432\u043A\u043B\u044E\u0447\u0435\u043D\u0430",
1668
+ "banner.compact": "\u0441\u043A\u0430\u043D \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F",
1669
+ "banner.updateLine": "\u2191 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430 {version} \u2014 \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u0435 `nmh update`",
1628
1670
  // ── generic ─────────────────────────────────────────────────────────────
1629
- "common.path": "Path",
1630
- "common.size": "Size",
1631
- "common.share": "Share",
1632
- "common.packages": "Pkgs",
1671
+ "common.path": "\u041F\u0443\u0442\u044C",
1672
+ "common.size": "\u0420\u0430\u0437\u043C\u0435\u0440",
1673
+ "common.share": "\u0414\u043E\u043B\u044F",
1674
+ "common.packages": "\u041F\u0430\u043A\u0435\u0442\u044B",
1633
1675
  "common.pm": "PM",
1634
- "common.modified": "Modified",
1635
- "common.idle": "Idle",
1676
+ "common.modified": "\u0418\u0437\u043C\u0435\u043D\u0451\u043D",
1677
+ "common.idle": "\u041F\u0440\u043E\u0441\u0442\u043E\u0439",
1636
1678
  // ── core/render.ts ──────────────────────────────────────────────────────
1637
- "render.scan.nested": " nested ",
1638
- "render.scan.nestedNote": " (+{n} nested, not counted)",
1639
- "render.scan.total": "\u{1F4BE} Total: {size} across {folders} folder(s), {packages} packages",
1640
- "render.warn.permission": "\u26A0 {n} directory(ies) unreadable (permission denied) \u2014 exit code 4",
1641
- "render.plan.hardLabel": "DELETE (permanent)",
1642
- "render.plan.trashLabel": "TRASH (restorable)",
1643
- "render.plan.dryRun": "[DRY RUN] Would {label} {count} folder(s) ({size}):",
1644
- "render.plan.more": " \u2026 plus {n} more",
1645
- "render.plan.rerun": "Run again without --dry-run to execute.",
1646
- "render.delete.verbHard": "Deleted",
1647
- "render.delete.verbTrash": "Trashed",
1648
- "render.delete.deleted": "\u2705 {verb}: {size} from {count} folder(s)",
1649
- "render.delete.failed": "\u26A0 {count} folder(s) failed \u2014 rerun with --verbose for details",
1650
- "render.search.header": "\u{1F50D} '{pattern}' \u2192 {count} package(s) in {dirs} node_modules",
1651
- "render.search.pathMatch": " (path match)",
1652
- "render.map.head.project": "Project",
1653
- "render.map.head.topPkgs": "TopPkgs",
1654
- "render.map.head.declared": "Declared",
1655
- "render.map.noPkgs": " (no top-level packages)",
1656
- "render.map.noManifest": " (no manifest with declared dependencies)",
1657
- "render.map.noDeclared": " (no declared dependencies)",
1658
- "render.map.declaredBy": "\u{1F517} '{pkg}' is declared by {count} project(s):",
1659
- "render.section.overview": "OVERVIEW",
1660
- "render.section.byType": "BY TYPE",
1661
- "render.section.licenses": "LICENSES",
1662
- "render.section.score": "BLOAT SCORE",
1663
- "render.section.co2": "CO2 ESTIMATE",
1664
- "render.section.deprecated": "DEPRECATED",
1665
- "render.section.graph": "GRAPH",
1666
- "render.section.reinstall": "REINSTALL",
1667
- "render.section.top": "TOP {n} SIZE",
1668
- "render.section.longTail": "LONG TAIL",
1669
- "render.section.dedup": "DEDUP SUGGESTION",
1670
- "render.section.baseline": "BASELINE COMPARE",
1671
- "render.section.audit": "DEPS AUDIT",
1679
+ "render.scan.nested": " \u0432\u043B\u043E\u0436\u0435\u043D\u043D\u044B\u0439 ",
1680
+ "render.scan.nestedNote": " (\u0435\u0449\u0451 {n} \u0432\u043B\u043E\u0436\u0435\u043D\u043D\u044B\u0445, \u043D\u0435 \u0443\u0447\u0442\u0435\u043D\u043E)",
1681
+ "render.scan.total": "\u{1F4BE} \u0418\u0442\u043E\u0433\u043E: {size} \u2014 \u043F\u0430\u043F\u043E\u043A: {folders}, \u043F\u0430\u043A\u0435\u0442\u043E\u0432: {packages}",
1682
+ "render.warn.permission": "\u26A0 \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u043E\u0432 \u043D\u0435 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u043D\u043E: {n} (\u043D\u0435\u0442 \u043F\u0440\u0430\u0432) \u2014 \u043A\u043E\u0434 \u0432\u044B\u0445\u043E\u0434\u0430 4",
1683
+ "render.plan.hardLabel": "\u0423\u0414\u0410\u041B\u0415\u041D\u0418\u0415 (\u0431\u0435\u0437\u0432\u043E\u0437\u0432\u0440\u0430\u0442\u043D\u043E\u0435)",
1684
+ "render.plan.trashLabel": "\u041F\u0415\u0420\u0415\u041D\u041E\u0421 \u0412 \u041A\u041E\u0420\u0417\u0418\u041D\u0423 (\u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043C\u043E)",
1685
+ "render.plan.dryRun": "[\u041F\u0420\u041E\u0411\u041D\u042B\u0419 \u0417\u0410\u041F\u0423\u0421\u041A] {label}: \u043F\u0430\u043F\u043E\u043A {count} ({size}):",
1686
+ "render.plan.more": " \u2026 \u043F\u043B\u044E\u0441 \u0435\u0449\u0451 {n}",
1687
+ "render.plan.rerun": "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u0431\u0435\u0437 --dry-run, \u0447\u0442\u043E\u0431\u044B \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C.",
1688
+ "render.delete.verbHard": "\u0423\u0434\u0430\u043B\u0435\u043D\u043E",
1689
+ "render.delete.verbTrash": "\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0435",
1690
+ "render.delete.deleted": "\u2705 {verb}: {size} \u0438\u0437 \u043F\u0430\u043F\u043E\u043A: {count}",
1691
+ "render.delete.failed": "\u26A0 \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0430\u043F\u043E\u043A: {count} \u2014 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u0441 --verbose \u0434\u043B\u044F \u0434\u0435\u0442\u0430\u043B\u0435\u0439",
1692
+ "render.search.header": "\u{1F50D} '{pattern}' \u2192 \u043F\u0430\u043A\u0435\u0442\u043E\u0432: {count} \u0432 {dirs} node_modules",
1693
+ "render.search.pathMatch": " (\u0441\u043E\u0432\u043F\u0430\u0434\u0435\u043D\u0438\u0435 \u043F\u043E \u043F\u0443\u0442\u0438)",
1694
+ "render.map.head.project": "\u041F\u0440\u043E\u0435\u043A\u0442",
1695
+ "render.map.head.topPkgs": "\u0422\u043E\u043F-\u043F\u0430\u043A\u0435\u0442\u044B",
1696
+ "render.map.head.declared": "\u0417\u0430\u044F\u0432\u043B\u0435\u043D\u043E",
1697
+ "render.map.noPkgs": " (\u043D\u0435\u0442 \u043F\u0430\u043A\u0435\u0442\u043E\u0432 \u0432\u0435\u0440\u0445\u043D\u0435\u0433\u043E \u0443\u0440\u043E\u0432\u043D\u044F)",
1698
+ "render.map.noManifest": " (\u043D\u0435\u0442 \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442\u0430 \u0441 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u043C\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u044F\u043C\u0438)",
1699
+ "render.map.noDeclared": " (\u043D\u0435\u0442 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439)",
1700
+ "render.map.declaredBy": "\u{1F517} '{pkg}' \u0437\u0430\u044F\u0432\u043B\u044F\u044E\u0442 \u043F\u0440\u043E\u0435\u043A\u0442\u043E\u0432: {count}:",
1701
+ "render.section.overview": "\u041E\u0411\u0417\u041E\u0420",
1702
+ "render.section.byType": "\u041F\u041E \u0422\u0418\u041F\u0423",
1703
+ "render.section.licenses": "\u041B\u0418\u0426\u0415\u041D\u0417\u0418\u0418",
1704
+ "render.section.score": "\u041E\u0426\u0415\u041D\u041A\u0410 \u0420\u0410\u0417\u0414\u0423\u0422\u041E\u0421\u0422\u0418",
1705
+ "render.section.co2": "\u041E\u0426\u0415\u041D\u041A\u0410 CO2",
1706
+ "render.section.deprecated": "\u0423\u0421\u0422\u0410\u0420\u0415\u0412\u0428\u0418\u0415",
1707
+ "render.section.graph": "\u0413\u0420\u0410\u0424",
1708
+ "render.section.reinstall": "\u041F\u0415\u0420\u0415\u0423\u0421\u0422\u0410\u041D\u041E\u0412\u041A\u0410",
1709
+ "render.section.top": "\u0422\u041E\u041F {n} \u041F\u041E \u0420\u0410\u0417\u041C\u0415\u0420\u0423",
1710
+ "render.section.longTail": "\u0414\u041B\u0418\u041D\u041D\u042B\u0419 \u0425\u0412\u041E\u0421\u0422",
1711
+ "render.section.dedup": "\u041F\u0420\u0415\u0414\u041B\u041E\u0416\u0415\u041D\u0418\u0415 \u0414\u0415\u0414\u0423\u041F\u041B\u0418\u041A\u0410\u0426\u0418\u0418",
1712
+ "render.section.baseline": "\u0421\u0420\u0410\u0412\u041D\u0415\u041D\u0418\u0415 \u0421 \u0411\u0410\u0417\u041E\u0419",
1713
+ "render.section.audit": "\u0410\u0423\u0414\u0418\u0422 \u0417\u0410\u0412\u0418\u0421\u0418\u041C\u041E\u0421\u0422\u0415\u0419",
1672
1714
  "render.stats.title": "\u{1F4CA} nmh stats \u2014 {badges}",
1673
- "render.stats.dedupPotential": " \xB7 dedup potential detected",
1674
- "render.stats.totalSize": "Total size : {size} across {count} node_modules",
1675
- "render.stats.packages": "Packages : {instances} instances / {unique} unique (dup {dup}\xD7)",
1676
- "render.stats.directDeps": "Direct deps : {count} declared across the scanned projects",
1677
- "render.stats.waste": "Waste (dedupable) : {size} ({percent}% of package sizes)",
1678
- "render.stats.noLicenses": "no package manifests found \u2014 nothing to license",
1679
- "render.stats.copyleftProd": " \u26A0 copyleft di production dependencies",
1680
- "render.stats.copyleftOther": " (copyleft, bukan prod-dep)",
1681
- "render.stats.experimental": "(experimental)",
1682
- "render.stats.grade": "grade",
1683
- "render.stats.wasteLabel": "waste",
1684
- "render.stats.dupLabel": "dup factor",
1685
- "render.stats.deadLabel": "dead",
1686
- "render.stats.deadNotAudited": "(tidak diaudit \u2014 tambahkan --dead untuk daftar)",
1687
- "render.stats.sizeLabel": "size",
1688
- "render.stats.co2Storage": "estimasi kasar, bukan audit karbon \u2014 simpan setahun",
1689
- "render.stats.co2Transfer": "kalau men-download ulang semuanya sekali",
1690
- "render.stats.deprecatedNone": "tidak ada paket deprecated \u2600\uFE0F",
1691
- "render.stats.deprecatedCount": "{count} instance deprecated:",
1692
- "render.stats.moreDeprecations": "\u2026dan {n} lainnya",
1693
- "render.stats.lockfileGrade": "(lockfile-grade)",
1694
- "render.stats.graphSuffix": "lockfile-grade \u2014 sisanya manifest-grade",
1695
- "render.stats.graphRoot": "root direct : {declared} declared \u2192 {nodes} tree nodes via {edges} edges",
1696
- "render.stats.graphNoDepth": "tidak ada kedalaman yang bisa dilacak dari root \u2014 bisa jadi lockfile ini v1/pecah",
1697
- "render.stats.graphUnreachable": "+ {n} node(s) unreachable from the root (optional/peer pruning)",
1698
- "render.stats.noLockfile": "no usable lockfile \u2014 manifest-grade",
1699
- "render.stats.reinstallNaive": "(naif)",
1700
- "render.stats.reinstallLine": "pasang ulang semuanya sekali : ~{duration}",
1701
- "render.stats.copies": "\xD7{n} copies",
1702
- "render.stats.oneCopy": "\xD71 copy",
1703
- "render.stats.dedupSaving": " \u2190 dedup bisa hemat {size}",
1704
- "render.stats.longTail": "\u2026 plus {names} more package name(s) \xB7 {instances} instances \xB7 {size}",
1705
- "render.stats.bisaHemat": " bisa hemat",
1706
- "render.stats.declaredRange": "{project} declared {range} ({field})",
1707
- "render.stats.transitive": "transitive (tidak dideklarasi di manifest)",
1708
- "render.global.title": "\u{1F310} nmh stats \u2014 global installation analysis",
1709
- "render.global.readonly": "(\u26A0\uFE0F global mode \u2014 read-only; needs access to the PM prefixes \u2014 sudo is never auto-applied)",
1710
- "render.global.pmDetected": "PM detected : {pms}{skipped}",
1711
- "render.global.total": "Total global : {count} packages \u2014 {size}",
1712
- "render.global.dead": "\u26A0 dead globals in {pm}: {count} (broken/missing bin symlink)",
1713
- "render.global.more": " \u2026 plus {n} more",
1714
- "render.global.crossDup": "\u26A0 Cross-PM duplicates : {count} package(s) (~{size} could be saved \u2014 uninstall one of them)",
1715
- "render.global.unreadable": "\u26A0 {count} unreadable location(s) \u2014 exit code 4",
1716
- "render.global.notFound": " (not found: {list})",
1717
- "render.global.multiPm": " \u2190 in more than one PM",
1718
- "render.global.head.package": "Package",
1719
- "render.global.head.version": "Version",
1720
- "render.baseline.saved": "Baseline : '{name}' saved {date}",
1721
- "render.baseline.totalSize": "Total size : {delta}{pct} \u2014 was {before}, now {after}",
1722
- "render.baseline.packages": "Packages : {delta}",
1723
- "render.baseline.headBefore": "Before",
1724
- "render.baseline.headNow": "Now",
1715
+ "render.stats.dedupPotential": " \xB7 \u043E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D \u043F\u043E\u0442\u0435\u043D\u0446\u0438\u0430\u043B \u0434\u0435\u0434\u0443\u043F\u043B\u0438\u043A\u0430\u0446\u0438\u0438",
1716
+ "render.stats.totalSize": "\u041E\u0431\u0449\u0438\u0439 \u0440\u0430\u0437\u043C\u0435\u0440 : {size} \u0432 {count} node_modules",
1717
+ "render.stats.packages": "\u041F\u0430\u043A\u0435\u0442\u044B : {instances} \u044D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440\u043E\u0432 / {unique} \u0443\u043D\u0438\u043A\u0430\u043B\u044C\u043D\u044B\u0445 (\u0434\u0443\u0431\u043B\u0435\u0439 {dup}\xD7)",
1718
+ "render.stats.directDeps": "\u041F\u0440\u044F\u043C\u044B\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438: {count} \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043E \u0432 \u043F\u0440\u043E\u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0445 \u043F\u0440\u043E\u0435\u043A\u0442\u0430\u0445",
1719
+ "render.stats.waste": "\u041E\u0442\u0445\u043E\u0434\u044B (\u0434\u0435\u0434\u0443\u043F) : {size} ({percent}% \u043E\u0442 \u0440\u0430\u0437\u043C\u0435\u0440\u043E\u0432 \u043F\u0430\u043A\u0435\u0442\u043E\u0432)",
1720
+ "render.stats.noLicenses": "\u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442\u044B \u043F\u0430\u043A\u0435\u0442\u043E\u0432 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B \u2014 \u043B\u0438\u0446\u0435\u043D\u0437\u0438\u0439 \u043D\u0435\u0442",
1721
+ "render.stats.copyleftProd": " \u26A0 copyleft \u0432 production-\u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u044F\u0445",
1722
+ "render.stats.copyleftOther": " (copyleft, \u043D\u0435 prod-\u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438)",
1723
+ "render.stats.experimental": "(\u044D\u043A\u0441\u043F\u0435\u0440\u0438\u043C\u0435\u043D\u0442\u0430\u043B\u044C\u043D\u043E)",
1724
+ "render.stats.grade": "\u043E\u0446\u0435\u043D\u043A\u0430",
1725
+ "render.stats.wasteLabel": "\u043E\u0442\u0445\u043E\u0434\u044B",
1726
+ "render.stats.dupLabel": "\u043A\u043E\u044D\u0444. \u0434\u0443\u0431\u043B\u0435\u0439",
1727
+ "render.stats.deadLabel": "\u043C\u0451\u0440\u0442\u0432\u043E\u0435",
1728
+ "render.stats.deadNotAudited": "(\u043D\u0435 \u0430\u0443\u0434\u0438\u0440\u043E\u0432\u0430\u043B\u043E\u0441\u044C \u2014 \u0434\u043E\u0431\u0430\u0432\u044C\u0442\u0435 --dead \u0434\u043B\u044F \u0441\u043F\u0438\u0441\u043A\u0430)",
1729
+ "render.stats.sizeLabel": "\u0440\u0430\u0437\u043C\u0435\u0440",
1730
+ "render.stats.co2Storage": "\u0433\u0440\u0443\u0431\u0430\u044F \u043E\u0446\u0435\u043D\u043A\u0430, \u043D\u0435 \u0443\u0433\u043B\u0435\u0440\u043E\u0434\u043D\u044B\u0439 \u0430\u0443\u0434\u0438\u0442 \u2014 \u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435 \u0437\u0430 \u0433\u043E\u0434",
1731
+ "render.stats.co2Transfer": "\u0435\u0441\u043B\u0438 \u043E\u0434\u0438\u043D \u0440\u0430\u0437 \u0432\u0441\u0451 \u043F\u0435\u0440\u0435\u043A\u0430\u0447\u0430\u0442\u044C \u0437\u0430\u043D\u043E\u0432\u043E",
1732
+ "render.stats.deprecatedNone": "\u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0445 \u043F\u0430\u043A\u0435\u0442\u043E\u0432 \u043D\u0435\u0442 \u2600\uFE0F",
1733
+ "render.stats.deprecatedCount": "\u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0445 \u044D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440\u043E\u0432: {count}:",
1734
+ "render.stats.moreDeprecations": "\u2026\u0438 \u0435\u0449\u0451 {n}",
1735
+ "render.stats.lockfileGrade": "(\u0443\u0440\u043E\u0432\u0435\u043D\u044C lockfile)",
1736
+ "render.stats.graphSuffix": "\u0443\u0440\u043E\u0432\u0435\u043D\u044C lockfile \u2014 \u043E\u0441\u0442\u0430\u043B\u044C\u043D\u043E\u0435 \u0443\u0440\u043E\u0432\u043D\u044F \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442\u0430",
1737
+ "render.stats.graphRoot": "\u043A\u043E\u0440\u043D\u0435\u0432\u044B\u0435 \u043F\u0440\u044F\u043C\u044B\u0435 : {declared} \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043E \u2192 {nodes} \u0443\u0437\u043B\u043E\u0432 \u0434\u0435\u0440\u0435\u0432\u0430 \u0447\u0435\u0440\u0435\u0437 {edges} \u0440\u0451\u0431\u0435\u0440",
1738
+ "render.stats.graphNoDepth": "\u043E\u0442 \u043A\u043E\u0440\u043D\u044F \u043D\u0435\u0447\u0435\u0433\u043E \u043E\u0442\u0441\u043B\u0435\u0436\u0438\u0432\u0430\u0442\u044C \u0432\u0433\u043B\u0443\u0431\u044C \u2014 \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E, \u044D\u0442\u043E lockfile v1/\u0431\u0438\u0442\u044B\u0439",
1739
+ "render.stats.graphUnreachable": "+ {n} \u0443\u0437\u043B(\u043E\u0432) \u043D\u0435\u0434\u043E\u0441\u0442\u0438\u0436\u0438\u043C\u044B \u043E\u0442 \u043A\u043E\u0440\u043D\u044F (\u0441\u0440\u0435\u0437 optional/peer)",
1740
+ "render.stats.noLockfile": "\u043D\u0435\u0442 \u043F\u0440\u0438\u0433\u043E\u0434\u043D\u043E\u0433\u043E lockfile \u2014 \u0443\u0440\u043E\u0432\u0435\u043D\u044C \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442\u0430",
1741
+ "render.stats.reinstallNaive": "(\u043D\u0430\u0438\u0432\u043D\u043E)",
1742
+ "render.stats.reinstallLine": "\u043F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u0432\u0441\u0451 \u0440\u0430\u0437\u043E\u043C : ~{duration}",
1743
+ "render.stats.copies": "\xD7{n} \u043A\u043E\u043F\u0438\u0439",
1744
+ "render.stats.oneCopy": "\xD71 \u043A\u043E\u043F\u0438\u044F",
1745
+ "render.stats.dedupSaving": " \u2190 \u0434\u0435\u0434\u0443\u043F \u043C\u043E\u0436\u0435\u0442 \u0441\u044D\u043A\u043E\u043D\u043E\u043C\u0438\u0442\u044C {size}",
1746
+ "render.stats.longTail": "\u2026 \u043F\u043B\u044E\u0441 \u0435\u0449\u0451 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0439 \u043F\u0430\u043A\u0435\u0442\u043E\u0432: {names} \xB7 \u044D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440\u043E\u0432: {instances} \xB7 {size}",
1747
+ "render.stats.bisaHemat": " \u043C\u043E\u0436\u043D\u043E \u0441\u044D\u043A\u043E\u043D\u043E\u043C\u0438\u0442\u044C",
1748
+ "render.stats.declaredRange": "{project} \u0437\u0430\u044F\u0432\u043B\u044F\u0435\u0442 {range} ({field})",
1749
+ "render.stats.transitive": "\u0442\u0440\u0430\u043D\u0437\u0438\u0442\u0438\u0432\u043D\u044B\u0435 (\u043D\u0435 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u044B \u0432 \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442\u0435)",
1750
+ "render.global.title": "\u{1F310} nmh stats \u2014 \u0430\u043D\u0430\u043B\u0438\u0437 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0445 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043E\u043A",
1751
+ "render.global.readonly": "(\u26A0\uFE0F \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0439 \u0440\u0435\u0436\u0438\u043C \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435; \u043D\u0443\u0436\u0435\u043D \u0434\u043E\u0441\u0442\u0443\u043F \u043A \u043F\u0440\u0435\u0444\u0438\u043A\u0441\u0430\u043C PM \u2014 sudo \u043D\u0438\u043A\u043E\u0433\u0434\u0430 \u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F \u0441\u0430\u043C)",
1752
+ "render.global.pmDetected": "\u041E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D PM : {pms}{skipped}",
1753
+ "render.global.total": "\u0412\u0441\u0435\u0433\u043E \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E : {count} \u043F\u0430\u043A\u0435\u0442\u043E\u0432 \u2014 {size}",
1754
+ "render.global.dead": "\u26A0 \u043C\u0451\u0440\u0442\u0432\u044B\u0435 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0435 \u0432 {pm}: {count} (\u0431\u0438\u0442\u0430\u044F/\u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0430\u044F bin-\u0441\u0441\u044B\u043B\u043A\u0430)",
1755
+ "render.global.more": " \u2026 \u043F\u043B\u044E\u0441 \u0435\u0449\u0451 {n}",
1756
+ "render.global.crossDup": "\u26A0 \u041C\u0435\u0436-PM \u0434\u0443\u0431\u043B\u0438 : {count} \u043F\u0430\u043A\u0435\u0442(\u043E\u0432) (~{size} \u043C\u043E\u0436\u043D\u043E \u0441\u044D\u043A\u043E\u043D\u043E\u043C\u0438\u0442\u044C \u2014 \u0443\u0434\u0430\u043B\u0438\u0442\u0435 \u043E\u0434\u0438\u043D \u0438\u0437 \u043D\u0438\u0445)",
1757
+ "render.global.unreadable": "\u26A0 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0445 \u043C\u0435\u0441\u0442: {count} \u2014 \u043A\u043E\u0434 \u0432\u044B\u0445\u043E\u0434\u0430 4",
1758
+ "render.global.notFound": " (\u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E: {list})",
1759
+ "render.global.multiPm": " \u2190 \u0431\u043E\u043B\u0435\u0435 \u0447\u0435\u043C \u0432 \u043E\u0434\u043D\u043E\u043C PM",
1760
+ "render.global.head.package": "\u041F\u0430\u043A\u0435\u0442",
1761
+ "render.global.head.version": "\u0412\u0435\u0440\u0441\u0438\u044F",
1762
+ "render.baseline.saved": "\u0411\u0430\u0437\u0430 : '{name}' \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0430 {date}",
1763
+ "render.baseline.totalSize": "\u041E\u0431\u0449\u0438\u0439 \u0440\u0430\u0437\u043C\u0435\u0440 : {delta}{pct} \u2014 \u0431\u044B\u043B\u043E {before}, \u0441\u0442\u0430\u043B\u043E {after}",
1764
+ "render.baseline.packages": "\u041F\u0430\u043A\u0435\u0442\u044B : {delta}",
1765
+ "render.baseline.headBefore": "\u0411\u044B\u043B\u043E",
1766
+ "render.baseline.headNow": "\u0421\u0442\u0430\u043B\u043E",
1725
1767
  "render.baseline.headDelta": "\u0394",
1726
- "render.baseline.new": "new",
1727
- "render.baseline.gone": "gone",
1728
- "render.baseline.moreChanged": "\u2026 plus {n} more changed path(s)",
1729
- "render.baseline.movers": "Package movers :",
1730
- "render.baseline.bloatGrowth": "\u{1F6A8} bloat growth detected \u2014 node_modules grew by more than 30% since the baseline",
1731
- "render.baselineHistory.title": "\u2696 nmh baselines \u2014 {count} saved",
1732
- "render.baselineHistory.saveHint": "save one with: nmh stats --save-baseline <name>",
1733
- "render.baselineHistory.head.name": "Name",
1734
- "render.baselineHistory.head.saved": "Saved",
1768
+ "render.baseline.new": "\u043D\u043E\u0432\u044B\u0439",
1769
+ "render.baseline.gone": "\u0438\u0441\u0447\u0435\u0437",
1770
+ "render.baseline.moreChanged": "\u2026 \u043F\u043B\u044E\u0441 \u0435\u0449\u0451 \u0438\u0437\u043C\u0435\u043D\u0451\u043D\u043D\u044B\u0445 \u043F\u0443\u0442\u0435\u0439: {n}",
1771
+ "render.baseline.movers": "\u041F\u0435\u0440\u0435\u043C\u0435\u0449\u0435\u043D\u0438\u044F :",
1772
+ "render.baseline.bloatGrowth": "\u{1F6A8} \u043E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D \u0440\u043E\u0441\u0442 \u0440\u0430\u0437\u0434\u0443\u0442\u043E\u0441\u0442\u0438 \u2014 node_modules \u0432\u044B\u0440\u043E\u0441\u043B\u0438 \u0431\u043E\u043B\u0435\u0435 \u0447\u0435\u043C \u043D\u0430 30% \u0441 \u043C\u043E\u043C\u0435\u043D\u0442\u0430 \u0431\u0430\u0437\u044B",
1773
+ "render.baselineHistory.title": "\u2696 \u0431\u0430\u0437\u044B nmh \u2014 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u043E: {count}",
1774
+ "render.baselineHistory.saveHint": "\u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C: nmh stats --save-baseline <name>",
1775
+ "render.baselineHistory.head.name": "\u0418\u043C\u044F",
1776
+ "render.baselineHistory.head.saved": "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0430",
1735
1777
  "render.baselineHistory.head.modules": "Node_modules",
1736
- "render.baselineHistory.head.where": "Where",
1737
- "render.baselineHistory.thisDir": " \xB7 this dir",
1738
- "render.why.title": "\u{1F50D} why '{pkg}' \u2014 {count} instance(s)",
1739
- "render.why.linked": "linked",
1740
- "render.why.declares": " project : {project} declares {range} ({field})",
1741
- "render.why.noName": "(manifest tanpa nama)",
1742
- "render.why.transitive": " project : transitive \u2014 tidak dideklarasi di manifest manapun",
1743
- "render.why.requiredBy": " required by : {count} package(s)",
1744
- "render.why.moreRequirers": " \u2026 plus {n} more requirer(s)",
1745
- "render.why.rootOnly": " required by : no package in the lockfile graph depends on it (root-only copy?)",
1746
- "render.why.orphan": " required by : no package manifest names it \u2014 orphan copy",
1747
- "render.audit.disclaimer": "\xB7 best-effort regex scan \u2014 {count} source file(s) (real graph: nmh stats --graph)",
1748
- "render.audit.clean": "\u2713 no phantom imports and no dead declarations detected",
1749
- "render.audit.phantom": "\u{1F9DF} phantom imports \u2014 imported in code, declared nowhere ({count})",
1750
- "render.audit.dead": "\u{1FAA6} dead declarations \u2014 installed + declared, never imported ({count})",
1778
+ "render.baselineHistory.head.where": "\u0413\u0434\u0435",
1779
+ "render.baselineHistory.thisDir": " \xB7 \u044D\u0442\u0430 \u043F\u0430\u043F\u043A\u0430",
1780
+ "render.why.title": "\u{1F50D} why '{pkg}' \u2014 \u044D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440\u043E\u0432: {count}",
1781
+ "render.why.linked": "\u0441\u0432\u044F\u0437\u0430\u043D",
1782
+ "render.why.declares": " \u043F\u0440\u043E\u0435\u043A\u0442 : {project} \u0437\u0430\u044F\u0432\u043B\u044F\u0435\u0442 {range} ({field})",
1783
+ "render.why.noName": "(\u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442 \u0431\u0435\u0437 \u0438\u043C\u0435\u043D\u0438)",
1784
+ "render.why.transitive": " \u043F\u0440\u043E\u0435\u043A\u0442 : \u0442\u0440\u0430\u043D\u0437\u0438\u0442\u0438\u0432\u043D\u043E \u2014 \u043D\u0435 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043E \u043D\u0438 \u0432 \u043E\u0434\u043D\u043E\u043C \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442\u0435",
1785
+ "render.why.requiredBy": " \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F : \u043F\u0430\u043A\u0435\u0442\u043E\u0432: {count}",
1786
+ "render.why.moreRequirers": " \u2026 \u043F\u043B\u044E\u0441 \u0435\u0449\u0451 \u0442\u0440\u0435\u0431\u0443\u044E\u0449\u0438\u0445: {n}",
1787
+ "render.why.rootOnly": " \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F : \u043D\u0438 \u043E\u0434\u0438\u043D \u043F\u0430\u043A\u0435\u0442 \u0432 \u0433\u0440\u0430\u0444\u0435 lockfile \u043E\u0442 \u043D\u0435\u0433\u043E \u043D\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 (\u043A\u043E\u043F\u0438\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u043A\u043E\u0440\u043D\u0435?)",
1788
+ "render.why.orphan": " \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F : \u043D\u0438 \u043E\u0434\u0438\u043D \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442 \u0435\u0433\u043E \u043D\u0435 \u0443\u043F\u043E\u043C\u0438\u043D\u0430\u0435\u0442 \u2014 \u043A\u043E\u043F\u0438\u044F-\u0441\u0438\u0440\u043E\u0442\u0430",
1789
+ "render.audit.disclaimer": "\xB7 \u0441\u043A\u0430\u043D \u043F\u043E \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043A\u0430\u043C, \u043A\u0430\u043A \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u0441\u044F \u2014 \u0444\u0430\u0439\u043B\u043E\u0432 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u043E\u0432: {count} (\u043D\u0430\u0441\u0442\u043E\u044F\u0449\u0438\u0439 \u0433\u0440\u0430\u0444: nmh stats --graph)",
1790
+ "render.audit.clean": "\u2713 \u0444\u0430\u043D\u0442\u043E\u043C\u043D\u044B\u0445 \u0438\u043C\u043F\u043E\u0440\u0442\u043E\u0432 \u0438 \u043C\u0451\u0440\u0442\u0432\u044B\u0445 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u0438\u0439 \u043D\u0435 \u043E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D\u043E",
1791
+ "render.audit.phantom": "\u{1F9DF} \u0444\u0430\u043D\u0442\u043E\u043C\u043D\u044B\u0435 \u0438\u043C\u043F\u043E\u0440\u0442\u044B \u2014 \u0438\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044F \u0432 \u043A\u043E\u0434\u0435, \u043D\u0438\u0433\u0434\u0435 \u043D\u0435 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043E ({count})",
1792
+ "render.audit.dead": "\u{1FAA6} \u043C\u0451\u0440\u0442\u0432\u044B\u0435 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u0438\u044F \u2014 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E + \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043E, \u043D\u043E \u043D\u0438\u043A\u043E\u0433\u0434\u0430 \u043D\u0435 \u0438\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044F ({count})",
1751
1793
  // ── utils: format / update-check / version ─────────────────────────────
1752
- "format.now": "now",
1753
- "format.ago": "{n} ago",
1754
- "update.note": "update tersedia: {current} \u2192 {latest} \u2014 npm i -g node-modules-hunter (cek 24 jam sekali, opt-in via --update-check)",
1755
- "version.tagline": "hunt node_modules \u2014 scan \xB7 measure \xB7 clean safely",
1756
- "version.yes": "yes",
1757
- "version.no": "no",
1794
+ "format.now": "\u0441\u0435\u0439\u0447\u0430\u0441",
1795
+ "format.ago": "{n} \u043D\u0430\u0437\u0430\u0434",
1796
+ "update.note": "\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435: {current} \u2192 {latest} \u2014 npm i -g node-modules-hunter (\u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u0440\u0430\u0437 \u0432 24 \u0447\u0430\u0441\u0430, \u0432\u043A\u043B\u044E\u0447\u0430\u0435\u0442\u0441\u044F \u0447\u0435\u0440\u0435\u0437 --update-check)",
1797
+ "version.tagline": "\u043E\u0445\u043E\u0442\u0430 \u043D\u0430 node_modules \u2014 \u0441\u043A\u0430\u043D\u0438\u0440\u0443\u0439 \xB7 \u0438\u0437\u043C\u0435\u0440\u044F\u0439 \xB7 \u0447\u0438\u0441\u0442\u0438 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E",
1798
+ "version.yes": "\u0434\u0430",
1799
+ "version.no": "\u043D\u0435\u0442",
1758
1800
  // ── commands/scan.ts ────────────────────────────────────────────────────
1759
- "scan.warn.noMatch": "no match for pattern: {pattern}",
1760
- "scan.warn.unresolvable": "cannot resolve real path (symlink loop?): {path}",
1761
- "scan.detectedPms": "detected PMs: {pms}",
1762
- "scan.spin.measuring": "measuring {done}/{total} folders \xB7 {size}",
1763
- "scan.warn.none": "no node_modules found \u2014 nothing to hunt here \u{1F643}",
1801
+ "scan.warn.noMatch": "\u043D\u0435\u0442 \u0441\u043E\u0432\u043F\u0430\u0434\u0435\u043D\u0438\u0439 \u0441 \u0448\u0430\u0431\u043B\u043E\u043D\u043E\u043C: {pattern}",
1802
+ "scan.warn.unresolvable": "\u043D\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044F \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044C \u0440\u0435\u0430\u043B\u044C\u043D\u044B\u0439 \u043F\u0443\u0442\u044C (\u043F\u0435\u0442\u043B\u044F \u0441\u0438\u043C\u043B\u0438\u043D\u043A\u043E\u0432?): {path}",
1803
+ "scan.detectedPms": "\u043E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D\u043D\u044B\u0435 PM: {pms}",
1804
+ "scan.spin.measuring": "\u0438\u0437\u043C\u0435\u0440\u0435\u043D\u0438\u0435 {done}/{total} \u043F\u0430\u043F\u043E\u043A \xB7 {size}",
1805
+ "scan.warn.none": "node_modules \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B \u2014 \u0437\u0434\u0435\u0441\u044C \u043D\u0435 \u043D\u0430 \u0447\u0442\u043E \u043E\u0445\u043E\u0442\u0438\u0442\u044C\u0441\u044F \u{1F643}",
1764
1806
  // ── commands/delete.ts + core/guards.ts ─────────────────────────────────
1765
- "delete.spin.progress": "\u{1F5D1} {done}/{total} folders\u2026",
1766
- "delete.note.trashFallback": "no OS trash backend (install gio or trash-cli) \u2014 fell back to the restorable nmh trash: {batch}",
1767
- "delete.note.trashBatch": "restorable nmh trash: {batch} (manifest: manifest.jsonl \u2014 restore by moving folders back)",
1768
- "delete.guard.unresolvable": "\u{1F6D1} {path} \u2014 refusing: cannot resolve real path (symlink loop?)",
1807
+ "delete.spin.progress": "\u{1F5D1} {done}/{total} \u043F\u0430\u043F\u043E\u043A\u2026",
1808
+ "delete.note.trashFallback": "\u043D\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u0433\u043E \u0431\u044D\u043A\u0435\u043D\u0434\u0430 \u043A\u043E\u0440\u0437\u0438\u043D\u044B (\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 gio \u0438\u043B\u0438 trash-cli) \u2014 \u043E\u0442\u043A\u0430\u0442 \u043A \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043C\u043E\u0439 \u043A\u043E\u0440\u0437\u0438\u043D\u0435 nmh: {batch}",
1809
+ "delete.note.trashBatch": "\u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043C\u0430\u044F \u043A\u043E\u0440\u0437\u0438\u043D\u0430 nmh: {batch} (\u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442: manifest.jsonl \u2014 \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0432\u043E\u0437\u0432\u0440\u0430\u0442\u043E\u043C \u043F\u0430\u043F\u043E\u043A \u043D\u0430 \u043C\u0435\u0441\u0442\u043E)",
1810
+ "delete.guard.unresolvable": "\u{1F6D1} {path} \u2014 \u043E\u0442\u043A\u0430\u0437: \u043D\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044F \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044C \u0440\u0435\u0430\u043B\u044C\u043D\u044B\u0439 \u043F\u0443\u0442\u044C (\u043F\u0435\u0442\u043B\u044F \u0441\u0438\u043C\u043B\u0438\u043D\u043A\u043E\u0432?)",
1769
1811
  "delete.guard.blocked": "\u{1F6D1} {path} \u2014 {reason}",
1770
- "delete.guard.abort": "delete aborted \u2014 safety guard refused; nothing was deleted (exit 3)",
1771
- "delete.warn.unresolvableSkipped": "{n} unresolvable target(s) skipped",
1772
- "delete.warn.guardSkipped": "{n} target(s) skipped by safety guard \u2014 continuing with the safe ones",
1773
- "delete.warn.jsonNeedsYes": "--json deletes require an explicit --yes (or --force) \u2014 there is no interactive confirm inside --json; nothing was deleted",
1774
- "delete.warn.nonInteractive": "non-interactive shell \u2014 nothing deleted without --yes (tip: --dry-run previews first)",
1775
- "delete.cancelled": "cancelled \u2014 nothing deleted",
1776
- "delete.select.mode": "Deletion mode:",
1777
- "delete.select.trash": "trash \u2014 move to OS bin (safe, restorable) \xB7 recommended",
1778
- "delete.select.hard": "hard \u2014 delete permanently \xB7 no undo",
1779
- "delete.confirm.hard": "Delete {count} folder(s) \u2014 {size} \u2014 PERMANENTLY (no undo)?",
1780
- "delete.confirm.trash": "Move {count} folder(s) \u2014 {size} \u2014 to the OS trash?",
1781
- "render.plan.notExecuted": "[NOT EXECUTED] Would {label} {count} folder(s) ({size}):",
1782
- "guard.reason.notFound": "path does not exist",
1783
- "guard.reason.notDirectory": "not a directory",
1784
- "guard.reason.symlinkLoop": "cannot resolve real path (symlink loop?)",
1785
- "guard.reason.name": "refusing: folder is not named node_modules ({name})",
1786
- "guard.reason.root": "refusing: target is a filesystem root",
1787
- "guard.reason.home": "refusing: target is the user home directory",
1788
- "guard.reason.rootParent": "refusing: node_modules directly inside the filesystem root",
1789
- "guard.reason.homeParent": "refusing: node_modules directly inside the home directory",
1790
- "guard.reason.unsafe": "unsafe target",
1812
+ "delete.guard.abort": "\u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u043E \u2014 \u0437\u0430\u0449\u0438\u0442\u043D\u044B\u0439 \u0431\u0430\u0440\u044C\u0435\u0440 \u043E\u0442\u043A\u0430\u0437\u0430\u043B; \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u043E (\u0432\u044B\u0445\u043E\u0434 3)",
1813
+ "delete.warn.unresolvableSkipped": "\u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D\u043E \u043D\u0435\u0440\u0430\u0437\u0440\u0435\u0448\u0438\u043C\u044B\u0445 \u0446\u0435\u043B\u0435\u0439: {n}",
1814
+ "delete.warn.guardSkipped": "\u0431\u0430\u0440\u044C\u0435\u0440 \u043F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u043B \u0446\u0435\u043B\u0435\u0439: {n} \u2014 \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0435\u043C \u0441 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u044B\u043C\u0438",
1815
+ "delete.warn.jsonNeedsYes": "--json-\u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u0442\u0440\u0435\u0431\u0443\u044E\u0442 \u044F\u0432\u043D\u043E\u0433\u043E --yes (\u0438\u043B\u0438 --force) \u2014 \u0432\u043D\u0443\u0442\u0440\u0438 --json \u043D\u0435\u0442 \u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0433\u043E \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F; \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u043E",
1816
+ "delete.warn.nonInteractive": "\u043D\u0435\u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u0430\u044F \u043E\u0431\u043E\u043B\u043E\u0447\u043A\u0430 \u2014 \u0431\u0435\u0437 --yes \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u043E (\u0441\u043E\u0432\u0435\u0442: \u0441\u043F\u0435\u0440\u0432\u0430 --dry-run \u0434\u043B\u044F \u043F\u0440\u0435\u0432\u044C\u044E)",
1817
+ "delete.cancelled": "\u043E\u0442\u043C\u0435\u043D\u0435\u043D\u043E \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u043E",
1818
+ "delete.select.mode": "\u0420\u0435\u0436\u0438\u043C \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F:",
1819
+ "delete.select.trash": "\u043A\u043E\u0440\u0437\u0438\u043D\u0430 \u2014 \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0443\u044E \u043A\u043E\u0440\u0437\u0438\u043D\u0443 (\u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E, \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043C\u043E) \xB7 \u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434\u0443\u0435\u0442\u0441\u044F",
1820
+ "delete.select.hard": "\u0436\u0451\u0441\u0442\u043A\u043E \u2014 \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0431\u0435\u0437\u0432\u043E\u0437\u0432\u0440\u0430\u0442\u043D\u043E \xB7 \u0431\u0435\u0437 \u043E\u0442\u043A\u0430\u0442\u0430",
1821
+ "delete.confirm.hard": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0411\u0415\u0417\u0412\u041E\u0417\u0412\u0420\u0410\u0422\u041D\u041E (\u0431\u0435\u0437 \u043E\u0442\u043A\u0430\u0442\u0430) \u043F\u0430\u043F\u043E\u043A: {count} \u2014 {size}?",
1822
+ "delete.confirm.trash": "\u041F\u0435\u0440\u0435\u043D\u0435\u0441\u0442\u0438 {count} \u043F\u0430\u043F\u043E\u043A \u2014 {size} \u2014 \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0443\u044E \u043A\u043E\u0440\u0437\u0438\u043D\u0443?",
1823
+ "render.plan.notExecuted": "[\u041D\u0415 \u0412\u042B\u041F\u041E\u041B\u041D\u0415\u041D\u041E] {label}: \u043F\u0430\u043F\u043E\u043A {count} ({size}):",
1824
+ "guard.reason.notFound": "\u043F\u0443\u0442\u044C \u043D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442",
1825
+ "guard.reason.notDirectory": "\u044D\u0442\u043E \u043D\u0435 \u043A\u0430\u0442\u0430\u043B\u043E\u0433",
1826
+ "guard.reason.symlinkLoop": "\u043D\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044F \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044C \u0440\u0435\u0430\u043B\u044C\u043D\u044B\u0439 \u043F\u0443\u0442\u044C (\u043F\u0435\u0442\u043B\u044F \u0441\u0438\u043C\u043B\u0438\u043D\u043A\u043E\u0432?)",
1827
+ "guard.reason.name": "\u043E\u0442\u043A\u0430\u0437: \u043F\u0430\u043F\u043A\u0430 \u043D\u0435 \u043D\u0430\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F node_modules ({name})",
1828
+ "guard.reason.root": "\u043E\u0442\u043A\u0430\u0437: \u0446\u0435\u043B\u044C \u2014 \u043A\u043E\u0440\u0435\u043D\u044C \u0444\u0430\u0439\u043B\u043E\u0432\u043E\u0439 \u0441\u0438\u0441\u0442\u0435\u043C\u044B",
1829
+ "guard.reason.home": "\u043E\u0442\u043A\u0430\u0437: \u0446\u0435\u043B\u044C \u2014 \u0434\u043E\u043C\u0430\u0448\u043D\u0438\u0439 \u043A\u0430\u0442\u0430\u043B\u043E\u0433 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F",
1830
+ "guard.reason.rootParent": "\u043E\u0442\u043A\u0430\u0437: node_modules \u043F\u0440\u044F\u043C\u043E \u0432 \u043A\u043E\u0440\u043D\u0435 \u0444\u0430\u0439\u043B\u043E\u0432\u043E\u0439 \u0441\u0438\u0441\u0442\u0435\u043C\u044B",
1831
+ "guard.reason.homeParent": "\u043E\u0442\u043A\u0430\u0437: node_modules \u043F\u0440\u044F\u043C\u043E \u0432 \u0434\u043E\u043C\u0430\u0448\u043D\u0435\u043C \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0435",
1832
+ "guard.reason.unsafe": "\u043D\u0435\u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u0430\u044F \u0446\u0435\u043B\u044C",
1791
1833
  // ── commands/wizard.ts ──────────────────────────────────────────────────
1792
- "wizard.warn.climbed": "no node_modules within 3 levels of cwd \u2014 scoped to the project root above: {root}",
1793
- "wizard.warn.noneHere": "no node_modules found in this folder",
1794
- "wizard.warn.scouted": "project ancestors were scouted too (\u22648 hops up) \u2014 no node_modules anywhere",
1795
- "wizard.warn.needsTty": "the interactive wizard needs a TTY \u2014 this was a plain read-only scan; every menu action exists as a command: see nmh --help",
1796
- "wizard.info.scopedUp": "cwd has no node_modules in 3 levels \u2014 scoped up to the project root {root}",
1797
- "wizard.outro.nothingFound": "nothing found \u{1F643}",
1798
- "wizard.menu.message": "{count} node_modules found in this tree \u2014 {size} \xB7 next move?",
1799
- "wizard.menu.deleteAll": "\u{1F5D1}\uFE0F Delete everything found (guards, mode & confirm included)",
1800
- "wizard.menu.pick": "\u2611\uFE0F Pick manually \u2014 checkboxes (space to select)",
1801
- "wizard.menu.search": "\u{1F50D} Search installed packages by pattern",
1802
- "wizard.menu.map": "\u{1F5FA}\uFE0F Map dependencies \u2014 project \u2192 PM \u2192 declared deps",
1803
- "wizard.menu.stats": "\u{1F4CA} Detailed report \u2014 the full stats read-out",
1804
- "wizard.menu.settings": "\u2699\uFE0F Settings & integration (read-only view)",
1805
- "wizard.menu.quit": "\u23F9 Exit nmh",
1806
- "wizard.outro.bye": "bye \u{1F44B} \u2014 nothing deleted",
1807
- "wizard.search.message": "Search installed packages \u2014 which pattern?",
1808
- "wizard.search.validate": "give a pattern \u2014 substring, glob, or /regex/",
1809
- "wizard.search.skipped": "search skipped \u2014 back to the menu",
1810
- "wizard.guard.blocked": "\u{1F6D1} {path} \u2014 {reason} (excluded from wizard)",
1811
- "wizard.outro.nothingSafe": "nothing safe to select \u2014 done",
1812
- "wizard.pick.message": "{count} node_modules \u2014 {size} found \xB7 space to select, enter to continue",
1813
- "wizard.outro.nothingSelected": "nothing selected \u2014 bye \u{1F44B}",
1814
- "wizard.outro.failures": "{icon} done with {n} failure(s) \u2014 freed {size}",
1815
- "wizard.outro.freed": "{icon} Freed: {size} from {count} folder(s)",
1816
- "wizard.mode.message": "How should these die?",
1817
- "wizard.mode.trash": "Move to OS trash \u2014 safe & restorable (recommended)",
1818
- "wizard.mode.hard": "Delete permanently \u2014 there is no undo",
1819
- "wizard.settings.title": "\u2699 settings & integration",
1820
- "wizard.settings.none": "(none)",
1834
+ "wizard.warn.climbed": "\u0432 3 \u0443\u0440\u043E\u0432\u043D\u044F\u0445 \u043E\u0442 cwd \u043D\u0435\u0442 node_modules \u2014 \u0441\u0443\u0436\u0435\u043D\u043E \u0434\u043E \u043A\u043E\u0440\u043D\u044F \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u0432\u044B\u0448\u0435: {root}",
1835
+ "wizard.warn.noneHere": "\u0432 \u044D\u0442\u043E\u0439 \u043F\u0430\u043F\u043A\u0435 node_modules \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B",
1836
+ "wizard.warn.scouted": "\u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u043F\u0440\u043E\u0435\u043A\u0442\u044B \u0442\u043E\u0436\u0435 \u043E\u0441\u043C\u043E\u0442\u0440\u0435\u043D\u044B (\u22648 \u0443\u0440\u043E\u0432\u043D\u0435\u0439 \u0432\u0432\u0435\u0440\u0445) \u2014 node_modules \u043D\u0435\u0442 \u043D\u0438\u0433\u0434\u0435",
1837
+ "wizard.warn.needsTty": "\u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u043E\u043C\u0443 \u043C\u0430\u0441\u0442\u0435\u0440\u0443 \u043D\u0443\u0436\u0435\u043D TTY \u2014 \u044D\u0442\u043E \u0431\u044B\u043B \u043F\u0440\u043E\u0441\u0442\u043E\u0439 \u0441\u043A\u0430\u043D \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F; \u0443 \u043A\u0430\u0436\u0434\u043E\u0433\u043E \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u043C\u0435\u043D\u044E \u0435\u0441\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0430: \u0441\u043C. nmh --help",
1838
+ "wizard.info.scopedUp": "\u0432 3 \u0443\u0440\u043E\u0432\u043D\u044F\u0445 \u043E\u0442 cwd \u043D\u0435\u0442 node_modules \u2014 \u0441\u0443\u0436\u0435\u043D\u043E \u0434\u043E \u043A\u043E\u0440\u043D\u044F \u043F\u0440\u043E\u0435\u043A\u0442\u0430 {root}",
1839
+ "wizard.outro.nothingFound": "\u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u{1F643}",
1840
+ "wizard.menu.message": "\u0432 \u044D\u0442\u043E\u043C \u0434\u0435\u0440\u0435\u0432\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E node_modules: {count} \u2014 {size} \xB7 \u0447\u0442\u043E \u0434\u0430\u043B\u044C\u0448\u0435?",
1841
+ "wizard.menu.deleteAll": "\u{1F5D1}\uFE0F \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u0441\u0451 \u043D\u0430\u0439\u0434\u0435\u043D\u043D\u043E\u0435 (\u0441 \u0431\u0430\u0440\u044C\u0435\u0440\u0430\u043C\u0438, \u0440\u0435\u0436\u0438\u043C\u043E\u043C \u0438 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0435\u043C)",
1842
+ "wizard.menu.pick": "\u2611\uFE0F \u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0432\u0440\u0443\u0447\u043D\u0443\u044E \u2014 \u0447\u0435\u043A\u0431\u043E\u043A\u0441\u044B (\u043F\u0440\u043E\u0431\u0435\u043B \u2014 \u043E\u0442\u043C\u0435\u0442\u0438\u0442\u044C)",
1843
+ "wizard.menu.search": "\u{1F50D} \u0418\u0441\u043A\u0430\u0442\u044C \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u043F\u0430\u043A\u0435\u0442\u044B \u043F\u043E \u0448\u0430\u0431\u043B\u043E\u043D\u0443",
1844
+ "wizard.menu.map": "\u{1F5FA}\uFE0F \u041A\u0430\u0440\u0442\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439 \u2014 \u043F\u0440\u043E\u0435\u043A\u0442 \u2192 PM \u2192 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438",
1845
+ "wizard.menu.stats": "\u{1F4CA} \u041F\u043E\u0434\u0440\u043E\u0431\u043D\u044B\u0439 \u043E\u0442\u0447\u0451\u0442 \u2014 \u043F\u043E\u043B\u043D\u044B\u0439 \u0432\u044B\u0432\u043E\u0434 stats",
1846
+ "wizard.menu.settings": "\u2699\uFE0F \u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0438 \u0438\u043D\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044F (\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F)",
1847
+ "wizard.menu.update": "\u{1F501} \u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C nmh (\u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u0442 \u0440\u0435\u0435\u0441\u0442\u0440, \u0441\u043F\u0435\u0440\u0432\u0430 \u0441\u043F\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442)",
1848
+ "wizard.menu.quit": "\u23F9 \u0412\u044B\u0439\u0442\u0438 \u0438\u0437 nmh",
1849
+ "wizard.outro.bye": "\u043F\u043E\u043A\u0430 \u{1F44B} \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u043E",
1850
+ "wizard.search.message": "\u041F\u043E\u0438\u0441\u043A \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0445 \u043F\u0430\u043A\u0435\u0442\u043E\u0432 \u2014 \u043A\u0430\u043A\u043E\u0439 \u0448\u0430\u0431\u043B\u043E\u043D?",
1851
+ "wizard.search.validate": "\u0434\u0430\u0439\u0442\u0435 \u0448\u0430\u0431\u043B\u043E\u043D \u2014 \u043F\u043E\u0434\u0441\u0442\u0440\u043E\u043A\u0430, glob \u0438\u043B\u0438 /regex/",
1852
+ "wizard.search.skipped": "\u043F\u043E\u0438\u0441\u043A \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D \u2014 \u043D\u0430\u0437\u0430\u0434 \u0432 \u043C\u0435\u043D\u044E",
1853
+ "wizard.guard.blocked": "\u{1F6D1} {path} \u2014 {reason} (\u0438\u0441\u043A\u043B\u044E\u0447\u0435\u043D\u043E \u0438\u0437 \u043C\u0430\u0441\u0442\u0435\u0440\u0430)",
1854
+ "wizard.outro.nothingSafe": "\u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u044B\u0445 \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u043E\u0432 \u043D\u0435\u0442 \u2014 \u0433\u043E\u0442\u043E\u0432\u043E",
1855
+ "wizard.pick.message": "\u043D\u0430\u0439\u0434\u0435\u043D\u043E node_modules: {count} \u2014 {size} \xB7 \u043F\u0440\u043E\u0431\u0435\u043B \u2014 \u043E\u0442\u043C\u0435\u0442\u0438\u0442\u044C, enter \u2014 \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C",
1856
+ "wizard.outro.nothingSelected": "\u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043E \u2014 \u043F\u043E\u043A\u0430 \u{1F44B}",
1857
+ "wizard.outro.failures": "{icon} \u0433\u043E\u0442\u043E\u0432\u043E, \u0441\u0431\u043E\u0435\u0432: {n} \u2014 \u043E\u0441\u0432\u043E\u0431\u043E\u0436\u0434\u0435\u043D\u043E {size}",
1858
+ "wizard.outro.freed": "{icon} \u041E\u0441\u0432\u043E\u0431\u043E\u0436\u0434\u0435\u043D\u043E: {size} \u0438\u0437 \u043F\u0430\u043F\u043E\u043A: {count}",
1859
+ "wizard.mode.message": "\u041A\u0430\u043A \u0438\u0445 \u0443\u043D\u0438\u0447\u0442\u043E\u0436\u0438\u0442\u044C?",
1860
+ "wizard.mode.trash": "\u0412 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0443\u044E \u043A\u043E\u0440\u0437\u0438\u043D\u0443 \u2014 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E \u0438 \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043C\u043E (\u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434\u0443\u0435\u0442\u0441\u044F)",
1861
+ "wizard.mode.hard": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0431\u0435\u0437\u0432\u043E\u0437\u0432\u0440\u0430\u0442\u043D\u043E \u2014 \u043E\u0442\u043A\u0430\u0442\u0430 \u043D\u0435\u0442",
1862
+ "wizard.settings.title": "\u2699 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0438 \u0438\u043D\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044F",
1863
+ "wizard.settings.none": "(\u043D\u0435\u0442)",
1821
1864
  "wizard.settings.list": "{n}: {list}",
1822
- "wizard.settings.cwdClimbed": "{from} \u2192 scoped up to {root}",
1823
- "wizard.settings.noConfig": "none found (.nmhrc in cwd \u2192 home)",
1824
- "wizard.settings.defaultMode": "trash (wizard keeps it safe by default)",
1825
- "wizard.settings.depth": "default 3 here \u2014 flag --depth <n> overrides",
1826
- "wizard.settings.auto": "auto (TTY on)",
1827
- "wizard.settings.updateCheckOff": "off \u2014 opt-in via --update-check",
1828
- "wizard.settings.logDir": "~/.nmh (delete receipts)",
1829
- "wizard.settings.changeHint": "change with nmh config (set\xB7add\xB7remove\xB7unset) or .nmhrc \u2014 README \xA710 \xB7",
1830
- "wizard.settings.commandsHint": "this whole menu also exists as plain commands: nmh clean \xB7 nmh search <pattern> \xB7 nmh map \xB7 nmh stats",
1865
+ "wizard.settings.cwdClimbed": "{from} \u2192 \u0441\u0443\u0436\u0435\u043D\u043E \u0434\u043E {root}",
1866
+ "wizard.settings.noConfig": "\u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D (.nmhrc \u0432 cwd \u2192 home)",
1867
+ "wizard.settings.defaultMode": "\u043A\u043E\u0440\u0437\u0438\u043D\u0430 (\u043C\u0430\u0441\u0442\u0435\u0440 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u0435\u043D)",
1868
+ "wizard.settings.depth": "\u0437\u0434\u0435\u0441\u044C \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 3 \u2014 \u0444\u043B\u0430\u0433 --depth <n> \u043F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u044F\u0435\u0442",
1869
+ "wizard.settings.auto": "auto (\u043F\u0440\u0438 TTY \u0432\u043A\u043B\u044E\u0447\u0435\u043D\u043E)",
1870
+ "wizard.settings.updateCheckOff": "\u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u043E \u2014 \u0432\u043A\u043B\u044E\u0447\u0430\u0435\u0442\u0441\u044F \u0447\u0435\u0440\u0435\u0437 --update-check",
1871
+ "wizard.settings.logDir": "~/.nmh (\u043A\u0432\u0438\u0442\u0430\u043D\u0446\u0438\u0438 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F)",
1872
+ "wizard.settings.changeHint": "\u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F \u0447\u0435\u0440\u0435\u0437 nmh config (set\xB7add\xB7remove\xB7unset) \u0438\u043B\u0438 .nmhrc \u2014 README \xA710 \xB7",
1873
+ "wizard.settings.commandsHint": "\u0432\u0441\u0451 \u044D\u0442\u043E \u043C\u0435\u043D\u044E \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438 \u043A\u0430\u043A \u043E\u0431\u044B\u0447\u043D\u044B\u0435 \u043A\u043E\u043C\u0430\u043D\u0434\u044B: nmh clean \xB7 nmh search <pattern> \xB7 nmh map \xB7 nmh stats",
1831
1874
  // ── commands/update.ts ──────────────────────────────────────────────────
1832
- "update.spin": "updating via npm\u2026",
1833
- "update.err.npmExit": "npm exited {code}",
1834
- "update.info.title": "nmh update \u2014 info registry (npm view node-modules-hunter)",
1835
- "update.info.installed": "installed {value}",
1836
- "update.info.latest": "latest {value}",
1837
- "update.info.update": "update {value}",
1838
- "update.info.available": "tersedia \u2014 jalankan `nmh update`",
1839
- "update.info.availableNonGlobal": " (atau: npm i -g node-modules-hunter)",
1840
- "update.info.none": "tidak ada \u2014 ini versi terbaru",
1841
- "update.info.summary": "summary {value}",
1842
- "update.info.tarball": "tarball {value}",
1843
- "update.info.sizeSuffix": " ({size}{files} files)",
1844
- "update.info.engines": "engines node {value}",
1845
- "update.info.license": "license {value}",
1846
- "update.info.published": "published {value}",
1847
- "update.err.noRegistry": "cannot read the latest version \u2014 is the registry reachable? (npm view node-modules-hunter version)",
1848
- "update.check.available": "\u2191 update tersedia: {current} \u2192 {latest} \u2014 jalankan `nmh update` untuk menginstall",
1849
- "update.check.latest": "\u2713 nmh {current} sudah versi terbaru (registry: {latest})",
1850
- "update.latestNoInstall": "\u2713 nmh {current} sudah versi terbaru (registry: {latest}) \u2014 tak ada yang diinstall",
1851
- "update.manual.title": "nmh {current} terpasang di luar npm global \u2014 update manual:",
1852
- "update.manual.command": " npm i -g node-modules-hunter (atau: pnpm add -g / bunx / brew upgrade node-modules-hunter)",
1853
- "update.err.needsAnswer": "update butuh jawaban eksplisit \u2014 -y untuk menginstall, -n untuk menolak (--check/--info untuk lihat saja)",
1854
- "update.confirm": "Update nmh {current} \u2192 {latest} via npm install -g?",
1855
- "update.declined": "\u2715 tetap nmh {current} \u2014 update ke {latest} tidak diinstall",
1856
- "update.err.failed": "\u26A0 update gagal: {detail}",
1857
- "update.err.manualHint": " coba manual: npm install -g node-modules-hunter@{latest}",
1858
- "update.done": "\u2713 terupdate {current} \u2192 {latest} (npm install -g node-modules-hunter)",
1875
+ "update.spin": "\u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 npm\u2026",
1876
+ "update.err.npmExit": "npm \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0441\u044F \u0441 \u043A\u043E\u0434\u043E\u043C {code}",
1877
+ "update.info.title": "nmh update \u2014 \u0441\u0432\u0435\u0434\u0435\u043D\u0438\u044F \u0438\u0437 registry (npm view node-modules-hunter)",
1878
+ "update.info.installed": "\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0430 {value}",
1879
+ "update.info.latest": "\u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F {value}",
1880
+ "update.info.update": "\u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 {value}",
1881
+ "update.info.available": "\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E \u2014 \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u0435 `nmh update`",
1882
+ "update.info.availableNonGlobal": " (\u0438\u043B\u0438: npm i -g node-modules-hunter)",
1883
+ "update.info.none": "\u043D\u0435\u0442 \u2014 \u044D\u0442\u043E \u0438 \u0435\u0441\u0442\u044C \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u0432\u0435\u0440\u0441\u0438\u044F",
1884
+ "update.info.summary": "\u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 {value}",
1885
+ "update.info.tarball": "tarball {value}",
1886
+ "update.info.sizeSuffix": " ({size}, \u0444\u0430\u0439\u043B\u043E\u0432: {files})",
1887
+ "update.info.engines": "engines node {value}",
1888
+ "update.info.license": "\u043B\u0438\u0446\u0435\u043D\u0437\u0438\u044F {value}",
1889
+ "update.info.published": "\u043E\u043F\u0443\u0431\u043B\u0438\u043A\u043E\u0432\u0430\u043D\u0430 {value}",
1890
+ "update.err.noRegistry": "\u043D\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044F \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044E\u044E \u0432\u0435\u0440\u0441\u0438\u044E \u2014 registry \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D? (npm view node-modules-hunter version)",
1891
+ "update.check.available": "\u2191 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435: {current} \u2192 {latest} \u2014 \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u0435 `nmh update` \u0434\u043B\u044F \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438",
1892
+ "update.check.latest": "\u2713 nmh {current} \u2014 \u0443\u0436\u0435 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u0432\u0435\u0440\u0441\u0438\u044F (registry: {latest})",
1893
+ "update.latestNoInstall": "\u2713 nmh {current} \u2014 \u0443\u0436\u0435 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u0432\u0435\u0440\u0441\u0438\u044F (registry: {latest}) \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u043B\u043E\u0441\u044C",
1894
+ "update.manual.title": "nmh {current} \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D \u0432\u043D\u0435 npm global \u2014 \u043E\u0431\u043D\u043E\u0432\u0438\u0442\u0435 \u0432\u0440\u0443\u0447\u043D\u0443\u044E:",
1895
+ "update.manual.command": " npm i -g node-modules-hunter (\u0438\u043B\u0438: pnpm add -g / bunx / brew upgrade node-modules-hunter)",
1896
+ "update.err.needsAnswer": "\u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044E \u043D\u0443\u0436\u0435\u043D \u044F\u0432\u043D\u044B\u0439 \u043E\u0442\u0432\u0435\u0442 \u2014 -y \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C, -n \u043E\u0442\u043A\u0430\u0437\u0430\u0442\u044C\u0441\u044F (--check/--info \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C)",
1897
+ "update.confirm": "\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C nmh {current} \u2192 {latest} \u0447\u0435\u0440\u0435\u0437 npm install -g?",
1898
+ "update.declined": "\u2715 \u043E\u0441\u0442\u0430\u0451\u043C\u0441\u044F \u043D\u0430 nmh {current} \u2014 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0434\u043E {latest} \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E",
1899
+ "update.err.failed": "\u26A0 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C: {detail}",
1900
+ "update.err.manualHint": " \u043F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u0432\u0440\u0443\u0447\u043D\u0443\u044E: npm install -g node-modules-hunter@{latest}",
1901
+ "update.done": "\u2713 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u043E {current} \u2192 {latest} (npm install -g node-modules-hunter)",
1902
+ "update.info.tags": "dist-tags {tags}",
1903
+ "update.check.onTag": "(dist-tag: {tag})",
1904
+ "update.confirm.downgrade": '\u041E\u0442\u043A\u0430\u0442\u0438\u0442\u044C nmh {current} \u2192 {target} \u0438\u0437 dist-tag "{tag}"?',
1905
+ "update.err.tagUnknown": 'dist-tag "{tag}" \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u2014 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435: {tags}',
1906
+ "update.err.invalidTag": '\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 dist-tag "{value}" \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0431\u0443\u043A\u0432\u044B, \u0446\u0438\u0444\u0440\u044B, \u0442\u043E\u0447\u043A\u0430, \u0434\u0435\u0444\u0438\u0441, \u043F\u043E\u0434\u0447\u0451\u0440\u043A\u0438\u0432\u0430\u043D\u0438\u0435',
1859
1907
  // ── commands/global.ts ──────────────────────────────────────────────────
1860
- "global.spin.probe": "probing global prefixes\u2026",
1861
- "global.spin.progress": "global {pm} \u2014 {done}/{total} packages",
1862
- "global.warn.none": "no global install roots found \u2014 nothing to analyze here \u{1F310}\u{1F643}",
1863
- "global.deadKind.broken": "broken bin symlink",
1864
- "global.deadKind.missing": "missing bin symlink",
1908
+ "global.spin.probe": "\u043E\u043F\u0440\u043E\u0441 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0445 \u043F\u0440\u0435\u0444\u0438\u043A\u0441\u043E\u0432\u2026",
1909
+ "global.spin.progress": "\u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0439 {pm} \u2014 {done}/{total} \u043F\u0430\u043A\u0435\u0442\u043E\u0432",
1910
+ "global.warn.none": "\u043A\u043E\u0440\u043D\u0438 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0445 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043E\u043A \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B \u2014 \u0430\u043D\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E \u{1F310}\u{1F643}",
1911
+ "global.deadKind.broken": "\u0431\u0438\u0442\u0430\u044F bin-\u0441\u0441\u044B\u043B\u043A\u0430",
1912
+ "global.deadKind.missing": "bin-\u0441\u0441\u044B\u043B\u043A\u0430 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442",
1865
1913
  // ── commands/map / search / why / treemap ──────────────────────────────
1866
- "map.spin.progress": "mapping {done}/{total} projects\u2026",
1867
- "map.warn.none": "no node_modules found \u2014 nothing to map here \u{1F643}",
1868
- "map.warn.notDeclared": "no project declares '{pkg}' in its manifest \u{1F643}",
1869
- "search.spin.progress": "searching {done}/{total} node_modules\u2026",
1870
- "search.warn.noMatch": "no match for '{pattern}' in any scanned node_modules \u{1F643}",
1871
- "why.warn.none": "no instance of '{pkg}' in the scanned node_modules \u2014 nmh why <pkg> [dirs]",
1872
- "treemap.warn.none": "no node_modules found \u2014 nothing to draw here \u{1F643}",
1873
- "treemap.err.write": "\u{1F6D1} could not write the treemap file \u2192 {path} \u2014 {detail}",
1874
- "treemap.done": "\u{1F5FA}\uFE0F treemap \u2192 {path} \u2014 buka di browser, hover cell buat detail",
1875
- // ── verbose diagnostics & utils ─────────────────────────────────────────
1876
- "verbose.deleteLogUnavailable": "delete log unavailable: {detail}",
1877
- "verbose.configUsing": "config: using {file}",
1878
- "verbose.configFound": "config: found {file}",
1879
- "verbose.baselineReadFailed": "baseline read failed: {detail}",
1880
- "warn.baselineSkip": "skipping unreadable baseline: {file}",
1881
- "verbose.updateCacheWriteFailed": "update-cache write failed: {detail}",
1882
- "verbose.updateCheckFailed": "update check failed: {detail}",
1883
- "verbose.updateRegistryStatus": "update check: registry responded {status}",
1884
- "verbose.updateRegistryUnreachable": "update check: registry unreachable ({detail})",
1885
- "verbose.scanTargets": "targets: {targets}",
1886
- "verbose.walkRoots": "walk roots: {walk}, direct node_modules: {direct}",
1887
- "verbose.scanFound": "found {n} node_modules \u2014 measuring",
1888
- "verbose.scanDone": "scan finished in {ms} ms",
1889
- "verbose.searchMatched": "search '{pattern}': {found}/{total} entries matched",
1890
- "verbose.mapProjects": "map: {n} project(s)",
1891
- "verbose.statsSummary": "stats: {entries} entries, {instances} instances, {unique} unique",
1892
- "verbose.globalNone": "global: {pm} \u2014 no global node_modules found",
1893
- "verbose.whyRequirers": "why: {pkg} in {path} \u2014 {count} requirer(s) ({grade})",
1894
- "verbose.treemapData": "treemap data: {entries} entries, {packages} packages",
1895
- "verbose.updateOverrideUnreadable": "update: override file unreadable ({detail})",
1896
- "verbose.npmViewFailed": "npm view failed (rc {code}): {stderr}",
1914
+ "map.spin.progress": "\u043A\u0430\u0440\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 {done}/{total} \u043F\u0440\u043E\u0435\u043A\u0442\u043E\u0432\u2026",
1915
+ "map.warn.none": "node_modules \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B \u2014 \u0437\u0434\u0435\u0441\u044C \u043D\u0435\u0447\u0435\u0433\u043E \u043A\u0430\u0440\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u{1F643}",
1916
+ "map.warn.notDeclared": "\u043D\u0438 \u043E\u0434\u0438\u043D \u043F\u0440\u043E\u0435\u043A\u0442 \u043D\u0435 \u0437\u0430\u044F\u0432\u043B\u044F\u0435\u0442 '{pkg}' \u0432 \u0441\u0432\u043E\u0451\u043C \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442\u0435 \u{1F643}",
1917
+ "search.spin.progress": "\u043F\u043E\u0438\u0441\u043A \u0432 {done}/{total} node_modules\u2026",
1918
+ "search.warn.noMatch": "\u0441\u043E\u0432\u043F\u0430\u0434\u0435\u043D\u0438\u0439 \u0441 '{pattern}' \u043D\u0438 \u0432 \u043E\u0434\u043D\u043E\u043C \u043F\u0440\u043E\u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u043C node_modules \u{1F643}",
1919
+ "why.warn.none": "\u044D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440\u043E\u0432 '{pkg}' \u0432 \u043F\u0440\u043E\u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0445 node_modules \u043D\u0435\u0442 \u2014 nmh why <pkg> [dirs]",
1920
+ "treemap.warn.none": "node_modules \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B \u2014 \u0440\u0438\u0441\u043E\u0432\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E \u{1F643}",
1921
+ "treemap.err.write": "\u{1F6D1} \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u0444\u0430\u0439\u043B treemap \u2192 {path} \u2014 {detail}",
1922
+ "treemap.done": "\u{1F5FA}\uFE0F treemap \u2192 {path} \u2014 \u043E\u0442\u043A\u0440\u043E\u0439\u0442\u0435 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u043D\u0430\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0430 \u044F\u0447\u0435\u0439\u043A\u0443 \u0434\u043B\u044F \u0434\u0435\u0442\u0430\u043B\u0435\u0439",
1923
+ // ── verbose diagnostics & utils ─────────────────────────────────────────
1924
+ "verbose.deleteLogUnavailable": "\u0436\u0443\u0440\u043D\u0430\u043B \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D: {detail}",
1925
+ "verbose.configUsing": "config: \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F {file}",
1926
+ "verbose.configFound": "config: \u043D\u0430\u0439\u0434\u0435\u043D {file}",
1927
+ "verbose.baselineReadFailed": "\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u0431\u0430\u0437\u0443: {detail}",
1928
+ "warn.baselineSkip": "\u043F\u0440\u043E\u043F\u0443\u0441\u043A \u043D\u0435\u0447\u0438\u0442\u0430\u0435\u043C\u043E\u0439 \u0431\u0430\u0437\u044B: {file}",
1929
+ "verbose.updateCacheWriteFailed": "\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u043A\u044D\u0448 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439: {detail}",
1930
+ "verbose.updateCheckFailed": "\u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C: {detail}",
1931
+ "verbose.updateRegistryStatus": "\u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F: registry \u043E\u0442\u0432\u0435\u0442\u0438\u043B {status}",
1932
+ "verbose.updateRegistryUnreachable": "\u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F: registry \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D ({detail})",
1933
+ "verbose.scanTargets": "\u0446\u0435\u043B\u0438: {targets}",
1934
+ "verbose.walkRoots": "\u043A\u043E\u0440\u043D\u0438 \u043E\u0431\u0445\u043E\u0434\u0430: {walk}, \u043F\u0440\u044F\u043C\u044B\u0435 node_modules: {direct}",
1935
+ "verbose.scanFound": "\u043D\u0430\u0439\u0434\u0435\u043D\u043E node_modules: {n} \u2014 \u0438\u0437\u043C\u0435\u0440\u044F\u0435\u043C",
1936
+ "verbose.scanDone": "\u0441\u043A\u0430\u043D \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D \u0437\u0430 {ms} \u043C\u0441",
1937
+ "verbose.searchMatched": "\u043F\u043E\u0438\u0441\u043A '{pattern}': \u0441\u043E\u0432\u043F\u0430\u043B\u043E \u0437\u0430\u043F\u0438\u0441\u0435\u0439 {found}/{total}",
1938
+ "verbose.mapProjects": "map: \u043F\u0440\u043E\u0435\u043A\u0442\u043E\u0432 {n}",
1939
+ "verbose.statsSummary": "stats: \u0437\u0430\u043F\u0438\u0441\u0435\u0439 {entries}, \u044D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440\u043E\u0432 {instances}, \u0443\u043D\u0438\u043A\u0430\u043B\u044C\u043D\u044B\u0445 {unique}",
1940
+ "verbose.globalNone": "global: {pm} \u2014 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0435 node_modules \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B",
1941
+ "verbose.whyRequirers": "why: {pkg} \u0432 {path} \u2014 \u0442\u0440\u0435\u0431\u0443\u044E\u0449\u0438\u0445: {count} ({grade})",
1942
+ "verbose.treemapData": "\u0434\u0430\u043D\u043D\u044B\u0435 treemap: \u0437\u0430\u043F\u0438\u0441\u0435\u0439 {entries}, \u043F\u0430\u043A\u0435\u0442\u043E\u0432 {packages}",
1943
+ "verbose.updateOverrideUnreadable": "update: \u0444\u0430\u0439\u043B \u043F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u044F \u043D\u0435\u0447\u0438\u0442\u0430\u0435\u043C ({detail})",
1944
+ "verbose.npmViewFailed": "npm view \u043D\u0435 \u0443\u0434\u0430\u043B\u0441\u044F (rc {code}): {stderr}",
1897
1945
  // ── commands/stats.ts ───────────────────────────────────────────────────
1898
- "stats.spin.progress": "analyzing {done}/{total} node_modules\u2026",
1899
- "stats.hint.noDeclared": "copies resolusinya ikut parent masing-masing \u2014 tidak ada knob langsung di project level",
1900
- "stats.hint.tail": " (declared {range})",
1901
- "stats.hint.pnpm": "range declared identik \u2014 pnpm virtual store melipat copy hoisted; cukup satu versi di workspace root{tail}",
1902
- "stats.hint.sameRange": "range declared identik \u2014 jalankan install ulang / npm dedupe \xB7 yarn dedupe melipat copy hoisted{tail}",
1903
- "stats.hint.diffRanges": "range declared beda ({ranges}) \u2014 samakan dulu di package.json, lalu install ulang",
1904
- "stats.err.noBaseline": "no baseline named '{name}' \u2014 {detail}",
1905
- "stats.err.baselinesSaved": "saved: {list}",
1906
- "stats.err.saveFirst": "save one first with nmh stats --save-baseline <name>",
1907
- "stats.note.savedEmpty": "\u{1F4BE} baseline saved \u2192 {name} (empty snapshot \u2014 no node_modules yet)",
1908
- "stats.warn.nothingToCompare": "nothing to compare \u2014 no node_modules scanned; baseline '{name}' kept as-is",
1909
- "stats.warn.none": "no node_modules found \u2014 nothing to analyze here \u{1F643}",
1910
- "stats.note.saved": "\u{1F4BE} baseline saved \u2192 {name}",
1911
- "stats.err.saveFailed": "could not save baseline '{name}': {detail}",
1946
+ "stats.spin.progress": "\u0430\u043D\u0430\u043B\u0438\u0437 {done}/{total} node_modules\u2026",
1947
+ "stats.hint.noDeclared": "\u043A\u043E\u043F\u0438\u0438 \u0440\u0435\u0437\u043E\u043B\u0432\u044F\u0442\u0441\u044F \u043A \u0441\u0432\u043E\u0438\u043C \u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044F\u043C \u2014 \u043F\u0440\u044F\u043C\u043E\u0433\u043E \u0440\u044B\u0447\u0430\u0433\u0430 \u043D\u0430 \u0443\u0440\u043E\u0432\u043D\u0435 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u043D\u0435\u0442",
1948
+ "stats.hint.tail": " (\u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043E {range})",
1949
+ "stats.hint.pnpm": "\u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0434\u0438\u0430\u043F\u0430\u0437\u043E\u043D\u044B \u043E\u0434\u0438\u043D\u0430\u043A\u043E\u0432\u044B \u2014 \u0432\u0438\u0440\u0442\u0443\u0430\u043B\u044C\u043D\u043E\u0435 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 pnpm \u0441\u0445\u043B\u043E\u043F\u044B\u0432\u0430\u0435\u0442 \u043F\u043E\u0434\u043D\u044F\u0442\u044B\u0435 \u043A\u043E\u043F\u0438\u0438; \u0432 \u043A\u043E\u0440\u043D\u0435 workspace \u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u043E\u0434\u043D\u043E\u0439 \u0432\u0435\u0440\u0441\u0438\u0438{tail}",
1950
+ "stats.hint.sameRange": "\u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0434\u0438\u0430\u043F\u0430\u0437\u043E\u043D\u044B \u043E\u0434\u0438\u043D\u0430\u043A\u043E\u0432\u044B \u2014 \u043F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 / npm dedupe \xB7 yarn dedupe \u0441\u0445\u043B\u043E\u043F\u043D\u0435\u0442 \u043F\u043E\u0434\u043D\u044F\u0442\u044B\u0435 \u043A\u043E\u043F\u0438\u0438{tail}",
1951
+ "stats.hint.diffRanges": "\u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0434\u0438\u0430\u043F\u0430\u0437\u043E\u043D\u044B \u0440\u0430\u0437\u043B\u0438\u0447\u0430\u044E\u0442\u0441\u044F ({ranges}) \u2014 \u0441\u043F\u0435\u0440\u0432\u0430 \u0443\u0440\u0430\u0432\u043D\u044F\u0439\u0442\u0435 \u0432 package.json, \u0437\u0430\u0442\u0435\u043C \u043F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435",
1952
+ "stats.err.noBaseline": "\u0431\u0430\u0437\u044B \u0441 \u0438\u043C\u0435\u043D\u0435\u043C '{name}' \u043D\u0435\u0442 \u2014 {detail}",
1953
+ "stats.err.baselinesSaved": "\u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u043E: {list}",
1954
+ "stats.err.saveFirst": "\u0441\u043F\u0435\u0440\u0432\u0430 \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u0435: nmh stats --save-baseline <name>",
1955
+ "stats.note.savedEmpty": "\u{1F4BE} \u0431\u0430\u0437\u0430 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0430 \u2192 {name} (\u043F\u0443\u0441\u0442\u043E\u0439 \u0441\u043D\u0438\u043C\u043E\u043A \u2014 node_modules \u043F\u043E\u043A\u0430 \u043D\u0435\u0442)",
1956
+ "stats.warn.nothingToCompare": "\u043D\u0435\u0447\u0435\u0433\u043E \u0441\u0440\u0430\u0432\u043D\u0438\u0432\u0430\u0442\u044C \u2014 node_modules \u043D\u0435 \u043F\u0440\u043E\u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u044B; \u0431\u0430\u0437\u0430 '{name}' \u043E\u0441\u0442\u0430\u0432\u043B\u0435\u043D\u0430 \u043A\u0430\u043A \u0435\u0441\u0442\u044C",
1957
+ "stats.warn.none": "node_modules \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B \u2014 \u0430\u043D\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E \u{1F643}",
1958
+ "stats.note.saved": "\u{1F4BE} \u0431\u0430\u0437\u0430 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0430 \u2192 {name}",
1959
+ "stats.err.saveFailed": "\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0431\u0430\u0437\u0443 '{name}': {detail}",
1912
1960
  // ── core/treemap.ts (HTML artifact) ────────────────────────────────────
1913
- "treemap.link": " \u27F6link",
1914
- "treemap.html.header": "nmh treemap \u2014 {entries} \u2014 {count} node_modules \u2014 hover buat detail disk, generated {at}",
1915
- "treemap.html.aria": "treemap ukuran node_modules",
1961
+ "treemap.link": " \u27F6\u0441\u0441\u044B\u043B\u043A\u0430",
1962
+ "treemap.html.header": "nmh treemap \u2014 {entries} \u2014 node_modules: {count} \u2014 \u043D\u0430\u0432\u0435\u0434\u0438\u0442\u0435 \u0434\u043B\u044F \u0434\u0435\u0442\u0430\u043B\u0435\u0439 \u043F\u043E \u0434\u0438\u0441\u043A\u0443, \u0441\u043E\u0437\u0434\u0430\u043D\u043E {at}",
1963
+ "treemap.html.aria": "treemap \u0440\u0430\u0437\u043C\u0435\u0440\u043E\u0432 node_modules",
1916
1964
  // ── help manual ─────────────────────────────────────────────────────────
1917
- "help.tagline": "hunt bloated node_modules folders: scan, measure, clean safely (npm/pnpm/yarn/bun)",
1918
- "help.usage.title": "Usage",
1965
+ "help.tagline": "\u043E\u0445\u043E\u0442\u0430 \u043D\u0430 \u0440\u0430\u0437\u0434\u0443\u0442\u044B\u0435 node_modules: \u0441\u043A\u0430\u043D\u0438\u0440\u0443\u0439, \u0438\u0437\u043C\u0435\u0440\u044F\u0439, \u0447\u0438\u0441\u0442\u0438 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E (npm/pnpm/yarn/bun)",
1966
+ "help.usage.title": "\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435",
1919
1967
  "help.usage.line": "nmh <command|targets> [options]",
1920
- "help.commands.title": "Commands",
1921
- "help.statsSub.title": "Stats subcommands",
1922
- "help.options.title": "Options \u2014 {group}",
1923
- "help.examples.title": "Examples",
1924
- "help.cmd.bare": "interactive wizard: arrow menu (delete all / pick / search / map / report / settings)",
1925
- "help.cmd.paths": "shortcut: scan given path(s); one-liner actions via flags (--delete, --search, \u2026)",
1926
- "help.cmd.wizard": "v1.2: the wizard on explicit targets (--dir=./a,./b skips the auto-climb); -- <view> opens a view first",
1927
- "help.cmd.scan": "full scan across targets (default: cwd)",
1928
- "help.cmd.clean": "scan + delete everything safe (trash by default)",
1929
- "help.cmd.search": "find installed packages by name (+ versions & sizes) \u2014 read-only",
1930
- "help.cmd.map": "project \u2192 PM \u2192 size \u2192 top packages \u2192 declared deps \u2014 read-only",
1931
- "help.cmd.stats": "size analytics: dup factor, waste, top-N, per-package tree (aliases: analyze, info)",
1932
- "help.cmd.why": "reverse depend: where is <pkg> and who requires it \u2014 read-only",
1933
- "help.cmd.treemap": "single-file interactive HTML treemap \u2192 nmh-treemap.html",
1934
- "help.cmd.global": "global installs across npm/pnpm/yarn/bun \u2014 read-only",
1935
- "help.cmd.config": "manage .nmhrc from the CLI: info \xB7 set \xB7 add \xB7 remove \xB7 unset",
1936
- "help.cmd.update": "v1.2: shows the facts and asks before installing \u2014 --check / --info compare only; -y installs, -n declines, --force skips the ask",
1937
- "help.cmd.version": "banner: tool version, node+abi, OS/arch/kernel, tty (alias: -v / --version)",
1938
- "help.cmd.help": "this help (alias: -h / --help)",
1939
- "help.statsSub.byType": "breakdown per dependency field (dep/dev/optional/peer/transitive)",
1940
- "help.statsSub.licenses": "license buckets (+ \u26A0 copyleft inside production deps)",
1941
- "help.statsSub.score": "experimental: composite bloat score 0-100 / rough CO2 estimate",
1942
- "help.statsSub.graph": "dependency graph from the lockfile \u2014 npm/yarn/pnpm/bun, no extra deps",
1943
- "help.statsSub.reinstall": 'naive npm-ci-style "how long would reinstalling everything take"',
1944
- "help.group.actions": "Actions",
1945
- "help.group.stale": "Stale hunting & output shape (v1.1)",
1946
- "help.group.scoping": "Scoping & filters",
1947
- "help.group.stats": "Stats suite",
1948
- "help.group.config": "Config family",
1949
- "help.flag.delete": "delete found folders: hard | trash (soft alias) \u2014 no value = pick interactively",
1950
- "help.flag.trash": "v1.1: whose trash takes victims \u2014 system backend (default) or restorable ~/.nmh/trash",
1951
- "help.flag.dryRun": "preview what would be deleted \u2014 nothing is touched",
1952
- "help.flag.yes": "answer yes to every prompt (required for non-TTY deletes)",
1953
- "help.flag.force": "skip all confirmations (implies --yes)",
1954
- "help.flag.search": "search installed packages (substring, glob, or /regex/) \u2014 read-only",
1955
- "help.flag.map": "map projects: PM, size, top packages, declared deps \u2014 read-only",
1956
- "help.flag.depend": "map only: show declared deps; with a value, list who declares it",
1957
- "help.flag.tree": "map/stats only: list per-project packages (tree view, with sizes)",
1958
- "help.flag.why": "read-only: explain an installed package \u2014 instances and requirers",
1959
- "help.flag.stats": "stats report: overview + dup factor + waste + top sizes \u2014 read-only",
1960
- "help.flag.treemap": "treemap export: single-file HTML (default nmh-treemap.html; --out is an alias)",
1961
- "help.flag.dir": "target dir(s), comma separated or repeated; globs and ~ allowed",
1962
- "help.flag.size": "output shape: 'total' (just aggregate) or 'each' (default: per-folder table)",
1963
- "help.flag.saveReport": "also write the printed report to a file (.json/.md/.txt; --report <file> aliases it)",
1964
- "help.flag.wizard": "v1.2: open the wizard explicitly \u2014 same as bare `nmh`, but a pipe refuses with directions instead of a scan",
1965
- "help.flag.updateFamily": "v1.2: read-only views vs consented install \u2014 see `nmh update` row above",
1966
- "help.flag.updateCheck": "peek npm for a newer release (non-blocking, 24 h cache; also settable in .nmhrc)",
1967
- "help.flag.stale": "keep only projects idle >= <days>; ladder = git commit \u2192 manifest \u2192 folder mtime; no evidence = dropped",
1968
- "help.flag.fastSize": "measure with one `du -sk` per entry (KiB granularity) instead of walking every file",
1969
- "help.flag.sort": "order results: size (default, desc) | path | idle (oldest project first) | mtime (newest first)",
1970
- "help.flag.noSkip": "stop hiding system noise (.Trash*, Library/, *.app) during discovery \u2014 default: hidden",
1971
- "help.flag.animate": "live size counter while measuring: auto = real TTY only",
1972
- "help.flag.json": "machine-readable payload (pipe into jq); additive-only keys \u2014 v1.0 keys stay frozen",
1973
- "help.flag.quiet": "minimal output \u2014 pretty tables/notes mute, the --json payload still prints",
1974
- "help.flag.verbose": "debug chatter on stderr",
1975
- "help.flag.noColor": "disable ANSI colors (auto: colors only on a real TTY or with --color / FORCE_COLOR)",
1976
- "help.flag.color": "force ANSI colors even on a piped run (wins over a config color:false)",
1977
- "help.flag.recursive": "also look INSIDE found node_modules (nested audit; totals stay top-level only)",
1978
- "help.flag.pm": "filter by detected PM: npm|pnpm|yarn|bun|vp \u2014 no value lists what was detected",
1979
- "help.flag.exclude": "exclude paths from results (comma list of globs, e.g. **/e2e/**)",
1980
- "help.flag.keep": 'refuse to delete node_modules of these projects (comma list, glob ok; "self" works)',
1981
- "help.flag.depth": "max scan depth in levels below the target",
1982
- "help.flag.expand": "full absolute paths + extra detail in output",
1983
- "help.flag.top": "rows in the focused size list (default 10)",
1984
- "help.flag.by": "breakdown mode \u2014 'size' (alias: package), 'type', 'licenses'",
1985
- "help.flag.global": "analyze global installs (per-PM prefix scan; read-only)",
1986
- "help.flag.config": "use this config file instead of the .nmhrc lookup (cwd \u2192 home)",
1987
- "help.flag.saveBaseline": "save a metadata snapshot of this run to ~/.nmh/baselines/<name>.json",
1988
- "help.flag.compare": "diff this run against a stored baseline (totals, per-folder, package movers)",
1989
- "help.flag.history": "list stored baselines \u2014 no scan at all",
1990
- "help.flag.phantom": "stats only: imports found in sources but declared nowhere (best-effort regex audit)",
1991
- "help.flag.dead": "stats only: installed + declared but never imported (best-effort regex audit)",
1992
- "help.flag.licenses": "stats only: bucket instances by license field; flags copyleft in production deps",
1993
- "help.flag.score": "stats only: experimental composite bloat score 0-100",
1994
- "help.flag.co2": "stats only: experimental carbon estimate (storage-year + one redownload)",
1995
- "help.flag.online": "stats only: deprecated scan \u2014 offline manifests + lazy cached registry fallback",
1996
- "help.flag.graph": "stats only: dependency graph from the lockfile (npm/yarn/pnpm/bun) with BFS depth",
1997
- "help.flag.reinstall": "stats only: naive npm-ci-style estimate of the time to reinstall everything",
1998
- "help.flag.out": "treemap only: where to write the HTML file (same as --treemap <file>)",
1999
- "help.flag.defaultExclude": 'manage the persisted exclude list (comma list; special value "self")',
2000
- "help.flag.defaultKeep": 'manage the persisted keep list (comma list; special value "self")',
2001
- "help.flag.defaultMode": "set the persisted delete default (hard | soft | trash)",
2002
- "help.flag.logDir": "set the persisted recovery-log directory (logDir)",
2003
- "help.ex.bare": "wizard; the no-args menu auto-climbs to the nearest project root",
2004
- "help.ex.wizardDir": "wizard scoped to explicit targets \u2014 no auto-climb",
2005
- "help.ex.wizardRouter": "v1.2 router: stats view first, then the wizard menu",
2006
- "help.ex.multiTarget": "multi-target scan",
2007
- "help.ex.stale": "bury the stale boneyard, restorable trash",
2008
- "help.ex.why": "reverse-depend: who declares + who requires",
2009
- "help.ex.byType": "dep-field breakdown as a machine payload",
2010
- "help.ex.globalTop": "the 20 biggest global installs across PMs",
2011
- "help.ex.updateCheck": "compare installed vs registry \u2014 nothing installs",
2012
- "help.ex.configSet": "persist a default delete mode in .nmhrc",
2013
- "help.footer.safety": "Safety first: guards refuse dangerous targets (exit 3), deletes confirm unless --yes/--force, symlinks never get followed.",
2014
- "help.footer.exitCodes": "Exit codes: 0 ok \xB7 1 usage error \xB7 2 nothing found \xB7 3 guard refused \xB7 4 permission denied.",
2015
- "help.footer.docs": "Everything is documented in depth at: https://github.com/jhedev96/node-modules-hunter",
1968
+ "help.commands.title": "\u041A\u043E\u043C\u0430\u043D\u0434\u044B",
1969
+ "help.statsSub.title": "\u041F\u043E\u0434\u043A\u043E\u043C\u0430\u043D\u0434\u044B stats",
1970
+ "help.options.title": "\u041E\u043F\u0446\u0438\u0438 \u2014 {group}",
1971
+ "help.examples.title": "\u041F\u0440\u0438\u043C\u0435\u0440\u044B",
1972
+ "help.cmd.bare": "\u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u043C\u0430\u0441\u0442\u0435\u0440: \u043C\u0435\u043D\u044E \u043D\u0430 \u0441\u0442\u0440\u0435\u043B\u043A\u0430\u0445 (\u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u0441\u0451 / \u0432\u044B\u0431\u0440\u0430\u0442\u044C / \u043F\u043E\u0438\u0441\u043A / \u043A\u0430\u0440\u0442\u0430 / \u043E\u0442\u0447\u0451\u0442 / \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 / \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438)",
1973
+ "help.cmd.paths": "\u0441\u043E\u043A\u0440\u0430\u0449\u0435\u043D\u0438\u0435: \u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u044B\u0435 \u043F\u0443\u0442\u0438; \u043E\u0434\u043D\u043E\u0441\u0442\u0440\u043E\u0447\u043D\u044B\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0444\u043B\u0430\u0433\u0430\u043C\u0438 (--delete, --search, \u2026)",
1974
+ "help.cmd.wizard": "v1.2: \u043C\u0430\u0441\u0442\u0435\u0440 \u043F\u043E \u044F\u0432\u043D\u044B\u043C \u0446\u0435\u043B\u044F\u043C (--dir=./a,./b \u043E\u0442\u043A\u043B\u044E\u0447\u0430\u0435\u0442 \u0430\u0432\u0442\u043E-\u043F\u043E\u0434\u044A\u0451\u043C); -- <view> \u0441\u043F\u0435\u0440\u0432\u0430 \u043E\u0442\u043A\u0440\u044B\u0432\u0430\u0435\u0442 \u0432\u0438\u0434; \u0432 \u043C\u0435\u043D\u044E \u0442\u0435\u043F\u0435\u0440\u044C \u0435\u0441\u0442\u044C \u{1F501} \u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C nmh (v1.4)",
1975
+ "help.cmd.scan": "\u043F\u043E\u043B\u043D\u044B\u0439 \u0441\u043A\u0430\u043D \u043F\u043E \u0446\u0435\u043B\u044F\u043C (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: cwd)",
1976
+ "help.cmd.clean": "\u0441\u043A\u0430\u043D + \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u0441\u0451 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0435 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443)",
1977
+ "help.cmd.search": "\u043D\u0430\u0439\u0442\u0438 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u043F\u0430\u043A\u0435\u0442\u044B \u043F\u043E \u0438\u043C\u0435\u043D\u0438 (+ \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u0440\u0430\u0437\u043C\u0435\u0440\u044B) \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435",
1978
+ "help.cmd.map": "\u043F\u0440\u043E\u0435\u043A\u0442 \u2192 PM \u2192 \u0440\u0430\u0437\u043C\u0435\u0440 \u2192 \u0442\u043E\u043F-\u043F\u0430\u043A\u0435\u0442\u044B \u2192 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438 \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435",
1979
+ "help.cmd.stats": "\u0430\u043D\u0430\u043B\u0438\u0442\u0438\u043A\u0430 \u0440\u0430\u0437\u043C\u0435\u0440\u043E\u0432: \u043A\u043E\u044D\u0444\u0444\u0438\u0446\u0438\u0435\u043D\u0442 \u0434\u0443\u0431\u043B\u0435\u0439, \u043E\u0442\u0445\u043E\u0434\u044B, \u0442\u043E\u043F-N, \u0434\u0435\u0440\u0435\u0432\u043E \u043F\u043E \u043F\u0430\u043A\u0435\u0442\u0430\u043C (\u0430\u043B\u0438\u0430\u0441\u044B: analyze, info)",
1980
+ "help.cmd.why": "\u043E\u0431\u0440\u0430\u0442\u043D\u044B\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438: \u0433\u0434\u0435 <pkg> \u0438 \u043A\u0442\u043E \u0435\u0433\u043E \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435",
1981
+ "help.cmd.treemap": "\u043E\u0434\u043D\u043E\u0444\u0430\u0439\u043B\u043E\u0432\u044B\u0439 \u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 HTML-treemap \u2192 nmh-treemap.html",
1982
+ "help.cmd.global": "\u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 npm/pnpm/yarn/bun \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435",
1983
+ "help.cmd.config": "\u0443\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 .nmhrc \u0438\u0437 CLI: info \xB7 set \xB7 add \xB7 remove \xB7 unset",
1984
+ "help.cmd.update": "v1.4: \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u0444\u0430\u043A\u0442\u044B \u0438 \u0441\u043F\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043F\u0435\u0440\u0435\u0434 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u043E\u0439 \u2014 --check [tag] / --info \u0442\u043E\u043B\u044C\u043A\u043E \u0441\u0440\u0430\u0432\u043D\u0435\u043D\u0438\u0435; --tag \u0447\u0438\u0442\u0430\u0435\u0442 dist-tag (\u0434\u043B\u044F \u0434\u0430\u0443\u043D\u0433\u0440\u0435\u0439\u0434\u0430 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u041D\u0415\u0422); -y \u0443\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u0442, -n \u043E\u0442\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F, --force \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0430\u0435\u0442 \u0432\u043E\u043F\u0440\u043E\u0441",
1985
+ "help.cmd.version": "\u0431\u0430\u043D\u043D\u0435\u0440: \u0432\u0435\u0440\u0441\u0438\u044F \u0443\u0442\u0438\u043B\u0438\u0442\u044B, node+abi, \u041E\u0421/\u0430\u0440\u0445/\u044F\u0434\u0440\u043E, tty (\u0430\u043B\u0438\u0430\u0441: -v / --version)",
1986
+ "help.cmd.help": "\u044D\u0442\u0430 \u0441\u043F\u0440\u0430\u0432\u043A\u0430 (\u0430\u043B\u0438\u0430\u0441: -h / --help)",
1987
+ "help.statsSub.byType": "\u0440\u0430\u0437\u0431\u0438\u0432\u043A\u0430 \u043F\u043E \u043F\u043E\u043B\u044E \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438 (dep/dev/optional/peer/transitive)",
1988
+ "help.statsSub.licenses": "\u0433\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u043A\u0430 \u043B\u0438\u0446\u0435\u043D\u0437\u0438\u0439 (+ \u26A0 copyleft \u0432 production-\u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u044F\u0445)",
1989
+ "help.statsSub.score": "\u044D\u043A\u0441\u043F\u0435\u0440\u0438\u043C\u0435\u043D\u0442\u0430\u043B\u044C\u043D\u043E: \u0438\u043D\u0442\u0435\u0433\u0440\u0430\u043B\u044C\u043D\u0430\u044F \u043E\u0446\u0435\u043D\u043A\u0430 \u0440\u0430\u0437\u0434\u0443\u0442\u043E\u0441\u0442\u0438 0-100 / \u0433\u0440\u0443\u0431\u0430\u044F \u043E\u0446\u0435\u043D\u043A\u0430 CO2",
1990
+ "help.statsSub.graph": "\u0433\u0440\u0430\u0444 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439 \u0438\u0437 lockfile \u2014 npm/yarn/pnpm/bun, \u0431\u0435\u0437 \u0434\u043E\u043F. \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439",
1991
+ "help.statsSub.reinstall": "\u043D\u0430\u0438\u0432\u043D\u0430\u044F \u043E\u0446\u0435\u043D\u043A\u0430 \u0432 \u0441\u0442\u0438\u043B\u0435 npm-ci: \xAB\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0437\u0430\u0439\u043C\u0451\u0442 \u043F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 \u0432\u0441\u0435\u0433\u043E\xBB",
1992
+ "help.group.actions": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F",
1993
+ "help.group.stale": "\u041E\u0445\u043E\u0442\u0430 \u043D\u0430 \u0441\u0442\u0430\u0440\u044C\u0451 \u0438 \u0444\u043E\u0440\u043C\u0430 \u0432\u044B\u0432\u043E\u0434\u0430 (v1.1)",
1994
+ "help.group.scoping": "\u041E\u0431\u043B\u0430\u0441\u0442\u044C \u0438 \u0444\u0438\u043B\u044C\u0442\u0440\u044B",
1995
+ "help.group.stats": "\u041D\u0430\u0431\u043E\u0440 stats",
1996
+ "help.group.config": "\u0421\u0435\u043C\u0435\u0439\u0441\u0442\u0432\u043E config",
1997
+ "help.flag.delete": "\u0443\u0434\u0430\u043B\u044F\u0442\u044C \u043D\u0430\u0439\u0434\u0435\u043D\u043D\u044B\u0435 \u043F\u0430\u043F\u043A\u0438: hard | trash (\u0430\u043B\u0438\u0430\u0441 soft) \u2014 \u0431\u0435\u0437 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F = \u0432\u044B\u0431\u0440\u0430\u0442\u044C \u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u043E",
1998
+ "help.flag.trash": "v1.1: \u0447\u044C\u044F \u043A\u043E\u0440\u0437\u0438\u043D\u0430 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442 \u0436\u0435\u0440\u0442\u0432 \u2014 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u044B\u0439 \u0431\u044D\u043A\u0435\u043D\u0434 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E) \u0438\u043B\u0438 \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043C\u0430\u044F ~/.nmh/trash",
1999
+ "help.flag.dryRun": "\u043F\u0440\u0435\u0432\u044C\u044E \u0442\u043E\u0433\u043E, \u0447\u0442\u043E \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043B\u0435\u043D\u043E \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0442\u0440\u043E\u0433\u0430\u0435\u0442\u0441\u044F",
2000
+ "help.flag.yes": "\u043E\u0442\u0432\u0435\u0447\u0430\u0442\u044C \xAB\u0434\u0430\xBB \u043D\u0430 \u0432\u0441\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B (\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E \u0434\u043B\u044F \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0439 \u0431\u0435\u0437 TTY)",
2001
+ "help.flag.force": "\u043F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u0432\u0441\u0435 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F (\u043F\u043E\u0434\u0440\u0430\u0437\u0443\u043C\u0435\u0432\u0430\u0435\u0442 --yes)",
2002
+ "help.flag.search": "\u0438\u0441\u043A\u0430\u0442\u044C \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u043F\u0430\u043A\u0435\u0442\u044B (\u043F\u043E\u0434\u0441\u0442\u0440\u043E\u043A\u0430, glob \u0438\u043B\u0438 /regex/) \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435",
2003
+ "help.flag.map": "\u043A\u0430\u0440\u0442\u0430 \u043F\u0440\u043E\u0435\u043A\u0442\u043E\u0432: PM, \u0440\u0430\u0437\u043C\u0435\u0440, \u0442\u043E\u043F-\u043F\u0430\u043A\u0435\u0442\u044B, \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438 \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435",
2004
+ "help.flag.depend": "\u0442\u043E\u043B\u044C\u043A\u043E map: \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438; \u0441\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435\u043C \u2014 \u043A\u0442\u043E \u0438\u0445 \u0437\u0430\u044F\u0432\u043B\u044F\u0435\u0442",
2005
+ "help.flag.tree": "\u0442\u043E\u043B\u044C\u043A\u043E map/stats: \u043F\u0430\u043A\u0435\u0442\u044B \u043A\u0430\u0436\u0434\u043E\u0433\u043E \u043F\u0440\u043E\u0435\u043A\u0442\u0430 (\u0434\u0435\u0440\u0435\u0432\u043E, \u0441 \u0440\u0430\u0437\u043C\u0435\u0440\u0430\u043C\u0438)",
2006
+ "help.flag.why": "\u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435: \u043E\u0431\u044A\u044F\u0441\u043D\u0438\u0442\u044C \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0439 \u043F\u0430\u043A\u0435\u0442 \u2014 \u044D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440\u044B \u0438 \u0442\u0440\u0435\u0431\u0443\u044E\u0449\u0438\u0435",
2007
+ "help.flag.stats": "\u043E\u0442\u0447\u0451\u0442 stats: \u043E\u0431\u0437\u043E\u0440 + \u0434\u0443\u0431\u043B\u0438 + \u043E\u0442\u0445\u043E\u0434\u044B + \u0442\u043E\u043F \u0440\u0430\u0437\u043C\u0435\u0440\u043E\u0432 \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435",
2008
+ "help.flag.treemap": "\u044D\u043A\u0441\u043F\u043E\u0440\u0442 treemap: \u043E\u0434\u043D\u043E\u0444\u0430\u0439\u043B\u043E\u0432\u044B\u0439 HTML (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E nmh-treemap.html; --out \u2014 \u0430\u043B\u0438\u0430\u0441)",
2009
+ "help.flag.dir": "\u0446\u0435\u043B\u0435\u0432\u044B\u0435 \u043F\u0430\u043F\u043A\u0438, \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E \u0438\u043B\u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0430\u043C\u0438; \u0434\u043E\u043F\u0443\u0441\u043A\u0430\u044E\u0442\u0441\u044F globs \u0438 ~",
2010
+ "help.flag.size": "\u0444\u043E\u0440\u043C\u0430 \u0432\u044B\u0432\u043E\u0434\u0430: 'total' (\u0442\u043E\u043B\u044C\u043A\u043E \u0438\u0442\u043E\u0433) \u0438\u043B\u0438 'each' (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: \u0442\u0430\u0431\u043B\u0438\u0446\u0430 \u043F\u043E \u043F\u0430\u043F\u043A\u0430\u043C)",
2011
+ "help.flag.saveReport": "\u0442\u0430\u043A\u0436\u0435 \u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u043F\u0435\u0447\u0430\u0442\u043D\u044B\u0439 \u043E\u0442\u0447\u0451\u0442 \u0432 \u0444\u0430\u0439\u043B (.json/.md/.txt; --report <file> \u2014 \u0430\u043B\u0438\u0430\u0441)",
2012
+ "help.flag.wizard": "v1.2: \u043E\u0442\u043A\u0440\u044B\u0442\u044C \u043C\u0430\u0441\u0442\u0435\u0440 \u044F\u0432\u043D\u043E \u2014 \u043A\u0430\u043A \u0433\u043E\u043B\u044B\u0439 `nmh`, \u043D\u043E \u0432 \u043F\u0430\u0439\u043F\u0435 \u043E\u0442\u043A\u0430\u0437 \u0441 \u043F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430\u043C\u0438 \u0432\u043C\u0435\u0441\u0442\u043E \u0441\u043A\u0430\u043D\u0430",
2013
+ "help.flag.updateFamily": "v1.2: \u0432\u0438\u0434\u044B \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F \u043F\u0440\u043E\u0442\u0438\u0432 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 \u0441 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u044F \u2014 \u0441\u043C. \u0441\u0442\u0440\u043E\u043A\u0443 `nmh update` \u0432\u044B\u0448\u0435",
2014
+ "help.flag.tag": "\u0447\u0438\u0442\u0430\u0442\u044C \u043A\u043E\u043D\u043A\u0440\u0435\u0442\u043D\u044B\u0439 dist-tag npm \u2014 nmh update --tag beta; --check <tag> \u0441\u0440\u0430\u0432\u043D\u0438\u0432\u0430\u0435\u0442 \u0441 \u043D\u0438\u043C (v1.4)",
2015
+ "help.flag.updateTag": "\u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0439 dist-tag \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F (updateTag \u0432 .nmhrc) \u2014 \u0447\u0442\u043E `nmh update` / `--check` \u0447\u0438\u0442\u0430\u044E\u0442 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E (v1.4)",
2016
+ "help.flag.updateCheck": "\u043F\u043E\u0434\u0433\u043B\u044F\u0434\u0435\u0442\u044C \u0432 npm \u043D\u043E\u0432\u044B\u0439 \u0440\u0435\u043B\u0438\u0437 (\u043D\u0435\u0431\u043B\u043E\u043A\u0438\u0440\u0443\u044E\u0449\u0435, \u043A\u044D\u0448 24 \u0447; \u043C\u043E\u0436\u043D\u043E \u0438 \u0432 .nmhrc)",
2017
+ "help.flag.stale": "\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u043B\u0438\u0448\u044C \u043F\u0440\u043E\u0435\u043A\u0442\u044B \u0441 \u043F\u0440\u043E\u0441\u0442\u043E\u0435\u043C >= <\u0434\u043D\u0435\u0439>; \u043B\u0435\u0441\u0442\u043D\u0438\u0446\u0430 = git commit \u2192 \u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442 \u2192 mtime \u043F\u0430\u043F\u043A\u0438; \u0431\u0435\u0437 \u0443\u043B\u0438\u043A = \u043E\u0442\u0431\u0440\u043E\u0448\u0435\u043D",
2018
+ "help.flag.fastSize": "\u0438\u0437\u043C\u0435\u0440\u044F\u0442\u044C \u043E\u0434\u043D\u0438\u043C `du -sk` \u043D\u0430 \u0437\u0430\u043F\u0438\u0441\u044C (\u0433\u0440\u0430\u043D\u0443\u043B\u044F\u0446\u0438\u044F KiB) \u0432\u043C\u0435\u0441\u0442\u043E \u043E\u0431\u0445\u043E\u0434\u0430 \u043A\u0430\u0436\u0434\u043E\u0433\u043E \u0444\u0430\u0439\u043B\u0430",
2019
+ "help.flag.sort": "\u043F\u043E\u0440\u044F\u0434\u043E\u043A \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432: size (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E, \u0443\u0431\u044B\u0432.) | path | idle (\u0441\u0442\u0430\u0440\u0435\u0439\u0448\u0438\u0439 \u043F\u0440\u043E\u0435\u043A\u0442 \u043F\u0435\u0440\u0432\u044B\u043C) | mtime (\u043D\u043E\u0432\u0435\u0439\u0448\u0438\u0439 \u043F\u0435\u0440\u0432\u044B\u043C)",
2020
+ "help.flag.noSkip": "\u043D\u0435 \u043F\u0440\u044F\u0442\u0430\u0442\u044C \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u044B\u0439 \u0448\u0443\u043C (.Trash*, Library/, *.app) \u043F\u0440\u0438 \u043E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D\u0438\u0438 \u2014 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: \u0441\u043A\u0440\u044B\u0442",
2021
+ "help.flag.animate": "\u0436\u0438\u0432\u043E\u0439 \u0441\u0447\u0451\u0442\u0447\u0438\u043A \u0440\u0430\u0437\u043C\u0435\u0440\u0430 \u043F\u0440\u0438 \u0438\u0437\u043C\u0435\u0440\u0435\u043D\u0438\u0438: auto = \u0442\u043E\u043B\u044C\u043A\u043E \u043D\u0430 \u043D\u0430\u0441\u0442\u043E\u044F\u0449\u0435\u043C TTY",
2022
+ "help.flag.json": "\u043C\u0430\u0448\u0438\u043D\u043E\u0447\u0438\u0442\u0430\u0435\u043C\u044B\u0439 \u0432\u044B\u0432\u043E\u0434 (\u043C\u043E\u0436\u043D\u043E \u0432 jq); \u043A\u043B\u044E\u0447\u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043E\u0431\u0430\u0432\u043B\u044F\u044E\u0442\u0441\u044F \u2014 \u043A\u043B\u044E\u0447\u0438 v1.0 \u0437\u0430\u043C\u043E\u0440\u043E\u0436\u0435\u043D\u044B",
2023
+ "help.flag.quiet": "\u043C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0432\u044B\u0432\u043E\u0434 \u2014 \u043A\u0440\u0430\u0441\u0438\u0432\u044B\u0435 \u0442\u0430\u0431\u043B\u0438\u0446\u044B/\u0437\u0430\u043C\u0435\u0442\u043A\u0438 \u043C\u043E\u043B\u0447\u0430\u0442, --json-\u0432\u044B\u0432\u043E\u0434 \u0432\u0441\u0451 \u0440\u0430\u0432\u043D\u043E \u043F\u0435\u0447\u0430\u0442\u0430\u0435\u0442\u0441\u044F",
2024
+ "help.flag.verbose": "\u043E\u0442\u043B\u0430\u0434\u043E\u0447\u043D\u0430\u044F \u0431\u043E\u043B\u0442\u043E\u0432\u043D\u044F \u0432 stderr",
2025
+ "help.flag.noColor": "\u043E\u0442\u043A\u043B\u044E\u0447\u0438\u0442\u044C ANSI-\u0446\u0432\u0435\u0442\u0430 (auto: \u0446\u0432\u0435\u0442\u0430 \u0442\u043E\u043B\u044C\u043A\u043E \u043D\u0430 \u043D\u0430\u0441\u0442\u043E\u044F\u0449\u0435\u043C TTY \u0438\u043B\u0438 \u0441 --color / FORCE_COLOR)",
2026
+ "help.flag.color": "\u0444\u043E\u0440\u0441\u0438\u0440\u043E\u0432\u0430\u0442\u044C ANSI-\u0446\u0432\u0435\u0442\u0430 \u0434\u0430\u0436\u0435 \u0432 \u043F\u0430\u0439\u043F\u0435 (\u0441\u0438\u043B\u044C\u043D\u0435\u0435, \u0447\u0435\u043C config color:false)",
2027
+ "help.flag.language": "\u044F\u0437\u044B\u043A \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430: en | id | zh | ru | es \u2014 \u0442\u0430\u043A\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 .nmhrc `language` \u0438 NMH_LANG; \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043C\u043E\u043B\u0447\u0430 \u043E\u0442\u043A\u0430\u0442\u044B\u0432\u0430\u044E\u0442\u0441\u044F \u043A en",
2028
+ "help.flag.recursive": "\u0437\u0430\u0433\u043B\u044F\u043D\u0443\u0442\u044C \u0438 \u0412\u041D\u0423\u0422\u0420\u042C \u043D\u0430\u0439\u0434\u0435\u043D\u043D\u044B\u0445 node_modules (\u0432\u043B\u043E\u0436\u0435\u043D\u043D\u044B\u0439 \u0430\u0443\u0434\u0438\u0442; \u0438\u0442\u043E\u0433\u0438 \u0441\u0447\u0438\u0442\u0430\u044E\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u043E \u0432\u0435\u0440\u0445\u043D\u0435\u043C\u0443 \u0443\u0440\u043E\u0432\u043D\u044E)",
2029
+ "help.flag.pm": "\u0444\u0438\u043B\u044C\u0442\u0440 \u043F\u043E \u043E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D\u043D\u043E\u043C\u0443 PM: npm|pnpm|yarn|bun|vp \u2014 \u0431\u0435\u0437 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u044F\u0435\u0442 \u043E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D\u043D\u043E\u0435",
2030
+ "help.flag.exclude": "\u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043F\u0443\u0442\u0438 \u0438\u0437 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432 (\u0441\u043F\u0438\u0441\u043E\u043A globs \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E, \u043D\u0430\u043F\u0440. **/e2e/**)",
2031
+ "help.flag.keep": '\u043E\u0442\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C\u0441\u044F \u0443\u0434\u0430\u043B\u044F\u0442\u044C node_modules \u044D\u0442\u0438\u0445 \u043F\u0440\u043E\u0435\u043A\u0442\u043E\u0432 (\u0441\u043F\u0438\u0441\u043E\u043A \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E, glob \u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C; \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 "self")',
2032
+ "help.flag.depth": "\u043C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0433\u043B\u0443\u0431\u0438\u043D\u0430 \u0441\u043A\u0430\u043D\u0430 \u0432 \u0443\u0440\u043E\u0432\u043D\u044F\u0445 \u043D\u0438\u0436\u0435 \u0446\u0435\u043B\u0438",
2033
+ "help.flag.expand": "\u043F\u043E\u043B\u043D\u044B\u0435 \u0430\u0431\u0441\u043E\u043B\u044E\u0442\u043D\u044B\u0435 \u043F\u0443\u0442\u0438 + \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0434\u0435\u0442\u0430\u043B\u0438 \u0432 \u0432\u044B\u0432\u043E\u0434\u0435",
2034
+ "help.flag.top": "\u0441\u0442\u0440\u043E\u043A \u0432 \u0441\u0444\u043E\u043A\u0443\u0441\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u043C \u0441\u043F\u0438\u0441\u043A\u0435 \u0440\u0430\u0437\u043C\u0435\u0440\u043E\u0432 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 10)",
2035
+ "help.flag.by": "\u0440\u0435\u0436\u0438\u043C \u0440\u0430\u0437\u0431\u0438\u0432\u043A\u0438 \u2014 'size' (\u0430\u043B\u0438\u0430\u0441: package), 'type', 'licenses'",
2036
+ "help.flag.global": "\u0430\u043D\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 (\u0441\u043A\u0430\u043D \u043F\u0440\u0435\u0444\u0438\u043A\u0441\u043E\u0432 \u043F\u043E PM; \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435)",
2037
+ "help.flag.config": "\u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u044D\u0442\u043E\u0442 \u0444\u0430\u0439\u043B \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432\u043C\u0435\u0441\u0442\u043E \u043F\u043E\u0438\u0441\u043A\u0430 .nmhrc (cwd \u2192 home)",
2038
+ "help.flag.saveBaseline": "\u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u043C\u0435\u0442\u0430\u0441\u043D\u0438\u043C\u043E\u043A \u044D\u0442\u043E\u0433\u043E \u0437\u0430\u043F\u0443\u0441\u043A\u0430 \u0432 ~/.nmh/baselines/<name>.json",
2039
+ "help.flag.compare": "\u0441\u0440\u0430\u0432\u043D\u0438\u0442\u044C \u044D\u0442\u043E\u0442 \u0437\u0430\u043F\u0443\u0441\u043A \u0441 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u043E\u0439 \u0431\u0430\u0437\u043E\u0439 (\u0438\u0442\u043E\u0433\u0438, \u043F\u043E \u043F\u0430\u043F\u043A\u0430\u043C, \u043F\u0435\u0440\u0435\u043C\u0435\u0449\u0435\u043D\u0438\u044F \u043F\u0430\u043A\u0435\u0442\u043E\u0432)",
2040
+ "help.flag.history": "\u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u0438\u0442\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0435 \u0431\u0430\u0437\u044B \u2014 \u0441\u043A\u0430\u043D\u0430 \u043D\u0435\u0442 \u0432\u043E\u0432\u0441\u0435",
2041
+ "help.flag.phantom": "\u0442\u043E\u043B\u044C\u043A\u043E stats: \u0438\u043C\u043F\u043E\u0440\u0442\u044B \u0432 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0430\u0445, \u043D\u0438\u0433\u0434\u0435 \u043D\u0435 \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 (\u0430\u0443\u0434\u0438\u0442 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u044F\u043A\u0430\u043C\u0438, \u043A\u0430\u043A \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u0441\u044F)",
2042
+ "help.flag.dead": "\u0442\u043E\u043B\u044C\u043A\u043E stats: \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E + \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043E, \u043D\u043E \u043D\u0438\u043A\u043E\u0433\u0434\u0430 \u043D\u0435 \u0438\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044F (\u0430\u0443\u0434\u0438\u0442 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u044F\u043A\u0430\u043C\u0438, \u043A\u0430\u043A \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u0441\u044F)",
2043
+ "help.flag.licenses": "\u0442\u043E\u043B\u044C\u043A\u043E stats: \u0433\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u043A\u0430 \u044D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440\u043E\u0432 \u043F\u043E \u043F\u043E\u043B\u044E \u043B\u0438\u0446\u0435\u043D\u0437\u0438\u0438; \u043F\u043E\u043C\u0435\u0447\u0430\u0435\u0442 copyleft \u0432 production-\u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u044F\u0445",
2044
+ "help.flag.score": "\u0442\u043E\u043B\u044C\u043A\u043E stats: \u044D\u043A\u0441\u043F\u0435\u0440\u0438\u043C\u0435\u043D\u0442\u0430\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0442\u0435\u0433\u0440\u0430\u043B\u044C\u043D\u0430\u044F \u043E\u0446\u0435\u043D\u043A\u0430 \u0440\u0430\u0437\u0434\u0443\u0442\u043E\u0441\u0442\u0438 0-100",
2045
+ "help.flag.co2": "\u0442\u043E\u043B\u044C\u043A\u043E stats: \u044D\u043A\u0441\u043F\u0435\u0440\u0438\u043C\u0435\u043D\u0442\u0430\u043B\u044C\u043D\u0430\u044F \u0443\u0433\u043B\u0435\u0440\u043E\u0434\u043D\u0430\u044F \u043E\u0446\u0435\u043D\u043A\u0430 (\u0433\u043E\u0434 \u0445\u0440\u0430\u043D\u0435\u043D\u0438\u044F + \u043E\u0434\u043D\u0430 \u043F\u0435\u0440\u0435\u043A\u0430\u0447\u043A\u0430)",
2046
+ "help.flag.online": "\u0442\u043E\u043B\u044C\u043A\u043E stats: \u0441\u043A\u0430\u043D \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0445 \u2014 \u043E\u0444\u043B\u0430\u0439\u043D-\u043C\u0430\u043D\u0438\u0444\u0435\u0441\u0442\u044B + \u043B\u0435\u043D\u0438\u0432\u044B\u0439 \u043A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0444\u043E\u043B\u0431\u044D\u043A registry",
2047
+ "help.flag.graph": "\u0442\u043E\u043B\u044C\u043A\u043E stats: \u0433\u0440\u0430\u0444 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439 \u0438\u0437 lockfile (npm/yarn/pnpm/bun) \u0441 \u0433\u043B\u0443\u0431\u0438\u043D\u043E\u0439 BFS",
2048
+ "help.flag.reinstall": "\u0442\u043E\u043B\u044C\u043A\u043E stats: \u043D\u0430\u0438\u0432\u043D\u0430\u044F \u043E\u0446\u0435\u043D\u043A\u0430 \u0432 \u0441\u0442\u0438\u043B\u0435 npm-ci \u0432\u0440\u0435\u043C\u0435\u043D\u0438 \u043F\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 \u0432\u0441\u0435\u0433\u043E",
2049
+ "help.flag.out": "\u0442\u043E\u043B\u044C\u043A\u043E treemap: \u043A\u0443\u0434\u0430 \u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C HTML-\u0444\u0430\u0439\u043B (\u0442\u043E \u0436\u0435, \u0447\u0442\u043E --treemap <file>)",
2050
+ "help.flag.defaultExclude": '\u0443\u043F\u0440\u0430\u0432\u043B\u044F\u0442\u044C \u043F\u043E\u0441\u0442\u043E\u044F\u043D\u043D\u044B\u043C \u0441\u043F\u0438\u0441\u043A\u043E\u043C exclude (\u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E; \u0441\u043F\u0435\u0446-\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 "self")',
2051
+ "help.flag.defaultKeep": '\u0443\u043F\u0440\u0430\u0432\u043B\u044F\u0442\u044C \u043F\u043E\u0441\u0442\u043E\u044F\u043D\u043D\u044B\u043C \u0441\u043F\u0438\u0441\u043A\u043E\u043C keep (\u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E; \u0441\u043F\u0435\u0446-\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 "self")',
2052
+ "help.flag.defaultMode": "\u0437\u0430\u0434\u0430\u0442\u044C \u043F\u043E\u0441\u0442\u043E\u044F\u043D\u043D\u044B\u0439 \u0440\u0435\u0436\u0438\u043C \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E (hard | soft | trash)",
2053
+ "help.flag.logDir": "\u0437\u0430\u0434\u0430\u0442\u044C \u043F\u043E\u0441\u0442\u043E\u044F\u043D\u043D\u044B\u0439 \u043A\u0430\u0442\u0430\u043B\u043E\u0433 \u0436\u0443\u0440\u043D\u0430\u043B\u0430 \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F (logDir)",
2054
+ "help.ex.bare": "\u043C\u0430\u0441\u0442\u0435\u0440; \u043C\u0435\u043D\u044E \u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432 \u0441\u0430\u043C\u043E \u043F\u043E\u0434\u043D\u0438\u043C\u0430\u0435\u0442\u0441\u044F \u043A \u0431\u043B\u0438\u0436\u0430\u0439\u0448\u0435\u043C\u0443 \u043A\u043E\u0440\u043D\u044E \u043F\u0440\u043E\u0435\u043A\u0442\u0430",
2055
+ "help.ex.wizardDir": "\u043C\u0430\u0441\u0442\u0435\u0440 \u043F\u043E \u044F\u0432\u043D\u044B\u043C \u0446\u0435\u043B\u044F\u043C \u2014 \u0431\u0435\u0437 \u0430\u0432\u0442\u043E-\u043F\u043E\u0434\u044A\u0451\u043C\u0430",
2056
+ "help.ex.wizardRouter": "\u0440\u043E\u0443\u0442\u0435\u0440 v1.2: \u0441\u043F\u0435\u0440\u0432\u0430 \u0432\u0438\u0434 stats, \u0437\u0430\u0442\u0435\u043C \u043C\u0435\u043D\u044E \u043C\u0430\u0441\u0442\u0435\u0440\u0430",
2057
+ "help.ex.multiTarget": "\u0441\u043A\u0430\u043D \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u0438\u0445 \u0446\u0435\u043B\u0435\u0439",
2058
+ "help.ex.stale": "\u043F\u043E\u0445\u043E\u0440\u043E\u043D\u0438\u0442\u044C \u0441\u0442\u0430\u0440\u044C\u0451, \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043C\u0430\u044F \u043A\u043E\u0440\u0437\u0438\u043D\u0430",
2059
+ "help.ex.why": "\u043E\u0431\u0440\u0430\u0442\u043D\u044B\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438: \u043A\u0442\u043E \u0437\u0430\u044F\u0432\u043B\u044F\u0435\u0442 + \u043A\u0442\u043E \u0442\u0440\u0435\u0431\u0443\u0435\u0442",
2060
+ "help.ex.byType": "\u0440\u0430\u0437\u0431\u0438\u0432\u043A\u0430 \u043F\u043E \u043F\u043E\u043B\u044E \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438 \u043A\u0430\u043A \u043C\u0430\u0448\u0438\u043D\u043E\u0447\u0438\u0442\u0430\u0435\u043C\u044B\u0439 \u0432\u044B\u0432\u043E\u0434",
2061
+ "help.ex.globalTop": "20 \u043A\u0440\u0443\u043F\u043D\u0435\u0439\u0448\u0438\u0445 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0445 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043E\u043A \u043F\u043E \u0432\u0441\u0435\u043C PM",
2062
+ "help.ex.updateCheck": "\u0441\u0440\u0430\u0432\u043D\u0438\u0442\u044C \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u043E\u0435 \u0441 registry \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u0442\u0441\u044F",
2063
+ "help.ex.configSet": "\u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0440\u0435\u0436\u0438\u043C \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u0432 .nmhrc",
2064
+ "help.footer.safety": "\u0411\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0441\u0442\u044C \u043F\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043E: \u0431\u0430\u0440\u044C\u0435\u0440\u044B \u043E\u0442\u043A\u0430\u0437\u044B\u0432\u0430\u044E\u0442 \u043E\u043F\u0430\u0441\u043D\u044B\u043C \u0446\u0435\u043B\u044F\u043C (\u0432\u044B\u0445\u043E\u0434 3), \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u0442\u0440\u0435\u0431\u0443\u044E\u0442 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F \u0431\u0435\u0437 --yes/--force, \u0441\u0438\u043C\u043B\u0438\u043D\u043A\u0438 \u043D\u0438\u043A\u043E\u0433\u0434\u0430 \u043D\u0435 \u043F\u0440\u0435\u0441\u043B\u0435\u0434\u0443\u044E\u0442\u0441\u044F.",
2065
+ "help.footer.exitCodes": "\u041A\u043E\u0434\u044B \u0432\u044B\u0445\u043E\u0434\u0430: 0 \u043E\u043A \xB7 1 \u043E\u0448\u0438\u0431\u043A\u0430 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \xB7 2 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \xB7 3 \u043E\u0442\u043A\u0430\u0437 \u0431\u0430\u0440\u044C\u0435\u0440\u0430 \xB7 4 \u043D\u0435\u0442 \u043F\u0440\u0430\u0432.",
2066
+ "help.footer.docs": "\u0412\u0441\u0451 \u043F\u043E\u0434\u0440\u043E\u0431\u043D\u043E \u0437\u0430\u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u043E \u0437\u0434\u0435\u0441\u044C: https://github.com/jhedev96/node-modules-hunter",
2016
2067
  // ── cli.ts guards & usage errors ────────────────────────────────────────
2017
- "cli.err.configNeedsPath": "--config needs a file path \u2014 nmh --config <file> \u2026",
2018
- "cli.err.languageNeedsValue": "--language needs a value \u2014 nmh --language id (en | id | zh | ru | es)",
2019
- "cli.err.invalidLanguage": "invalid --language: {value} (expected en | id | zh | ru | es)",
2020
- "cli.warn.futureFlag": "{flag} lands in a later version (v0.2+) \u2014 ignored for now",
2021
- "cli.warn.sizeTopN": "--size <n> (top-N list) lands in a later version \u2014 listing every folder for now",
2022
- "cli.err.invalidSize": "invalid --size: {value} (expected 'total' or 'each')",
2023
- "cli.err.sizeNeedsValue": "--size needs a value \u2014 use --size=total or --size=each (a bare --size doesn't select a mode)",
2024
- "cli.err.sizeTwice": "--size given more than once \u2014 pass a single value (total | each)",
2025
- "cli.err.staleNeedsValue": "--stale needs a value \u2014 use --stale=<days> (e.g. --stale=90)",
2026
- "cli.err.staleTwice": "--stale given more than once \u2014 pass a single value (days)",
2027
- "cli.err.invalidStale": "invalid --stale: {value} (expected a positive whole number of days)",
2028
- "cli.err.sortNeedsValue": "--sort needs a value \u2014 use --sort=size | path | idle | mtime",
2029
- "cli.err.sortTwice": "--sort given more than once \u2014 pass a single key",
2030
- "cli.err.invalidSort": "invalid --sort: {key} (expected size | path | idle | mtime)",
2031
- "cli.err.trashNeedsValue": "--trash needs a value \u2014 use --trash=system or --trash=nmh",
2032
- "cli.err.trashTwice": "--trash given more than once \u2014 pass a single mode",
2033
- "cli.err.invalidTrash": "invalid --trash: {mode} (expected system | nmh)",
2034
- "cli.err.invalidDelete": "invalid --delete: {value} (expected 'hard' | 'soft' | 'trash')",
2035
- "cli.verbose.deleteModeFromRc": "delete mode from .nmhrc: {mode}",
2036
- "cli.err.invalidPm": "invalid --pm: {value} (expected npm | pnpm | yarn | bun | vp)",
2037
- "cli.err.depthNeedsValue": "--depth needs a non-negative integer \u2014 use --depth=<n> (e.g. --depth=2)",
2038
- "cli.err.invalidDepth": "invalid --depth: {value} (expected a non-negative integer)",
2039
- "cli.err.saveReportNeedsValue": "--save-report needs a file path (.json/.md/.txt)",
2040
- "cli.err.reportNeedsValue": "--report needs a file path (.json/.md/.txt)",
2041
- "cli.err.invalidReportExt": "unknown report format: {file} (expected .json/.md/.txt)",
2042
- "cli.err.baselineNeedsName": "--save-baseline needs a name \u2014 nmh stats --save-baseline <name>",
2043
- "cli.err.compareNeedsName": "--compare needs a name \u2014 nmh stats --compare <name>",
2044
- "cli.err.invalidBaseline": "invalid baseline name: '{name}' (expected letters/digits/._-, max 64)",
2045
- "cli.err.unknownCommand": "unknown command '{cmd}' \u2014 run `nmh help` for the command list (paths are passed to `nmh scan` or `--dir`)",
2046
- "cli.err.pmBare": "--pm without a value only lists detected PMs \u2014 give a family (npm|pnpm|yarn|bun|vp) to filter a delete op or the --global analysis",
2047
- "cli.err.reportNotDelete": "--save-report rides along with scan \u2014 delete/clean runs are not scan reports",
2048
- "cli.warn.trashOnly": "--trash only matters for delete/clean runs \u2014 ignored for scans and read-only commands",
2049
- "cli.err.rootRefusal": "refusing a delete op over the filesystem root \u2014 point --dir at the project directory you want cleaned",
2050
- "cli.err.checkOnlyUpdate": "--check only works with the update command \u2014 nmh update --check",
2051
- "cli.err.infoOnlyUpdate": "--info only works with the update command \u2014 nmh update --info",
2052
- "cli.err.updateArgs": "update takes no arguments \u2014 plain `nmh update` (add --json for the payload)",
2053
- "cli.err.checkInfoExclusive": "--check and --info are two different read-only views \u2014 pick one (nmh update --check | --info)",
2054
- "cli.err.routerOrphan": "the `--` router belongs to the wizard \u2014 nmh wizard -- stats|map|search|why|treemap \u2026",
2055
- "cli.err.unknownWizardView": "unknown wizard view: {view} \u2014 the router opens a read-only view: stats (analyze, info) | map | search | why | treemap",
2056
- "cli.err.wizardPositional": "wizard takes no positional targets \u2014 scope it with --dir=./repo1,./repo2 (or `nmh wizard -- <view> \u2026`)",
2057
- "cli.err.wizardDelete": "--delete does not belong to the wizard \u2014 the menu asks for the mode itself",
2058
- "cli.err.wizardNeedsTTY": "the wizard needs a TTY (it is an arrow-key menu) \u2014 use nmh scan / --dir / the plain commands instead; bare `nmh` in a pipe stays a read-only scan",
2059
- "cli.err.configOp": "config needs an op \u2014 nmh config info | set | add | remove | unset (take a look: nmh config info)",
2060
- "cli.err.configPositional": "config {op} takes no positional args \u2014 use flags (--default-exclude \u2026, --depth \u2026)",
2061
- "cli.err.configDelete": "--delete does not belong to nmh config \u2014 it manages the .nmhrc file, that is all",
2062
- "cli.err.statsFlagsOnly": "--phantom/--dead/--licenses/--score/--co2/--online/--graph/--reinstall only work with the stats command \u2014 nmh stats --reinstall",
2063
- "cli.err.searchReadOnly": "--search is read-only \u2014 combine it with scan, not with delete/clean",
2064
- "cli.err.searchNeedsPattern": "search needs a pattern \u2014 nmh search <pattern> [dirs]",
2065
- "cli.err.whyReadOnly": "--why is read-only \u2014 combine it with scan, not with delete/clean",
2066
- "cli.err.whyNeedsPkg": "why needs a package name \u2014 nmh why <pkg> [dirs]",
2067
- "cli.err.whyConflict": "--why ({why}) conflicts with the why subcommand's package ({pkg}) \u2014 pick one",
2068
- "cli.err.whyFlagNeedsPkg": "--why needs a package name \u2014 nmh why <pkg> [dirs]",
2069
- "cli.err.treemapReadOnly": "--treemap is read-only \u2014 combine it with scan, not with delete/clean",
2070
- "cli.err.reportNotTreemap": "--save-report does not work with treemap \u2014 the HTML file IS the report (nmh treemap --out <file>)",
2071
- "cli.err.outNeedsValue": "--out needs a file path \u2014 nmh treemap --out report.html",
2072
- "cli.err.outOnlyTreemap": "--out only works with the treemap command \u2014 nmh treemap --out file.html",
2073
- "cli.err.invalidBy": "invalid --by: {value} (expected 'package' | 'size' | 'type' | 'licenses')",
2074
- "cli.err.dependOnlyMap": "--depend only works with the map command \u2014 nmh map <dirs> --depend [pkg]",
2075
- "cli.err.treeMapStats": "--tree works with map or stats, --depend is map-only \u2014 nmh map <dirs> --depend [pkg]",
2076
- "cli.err.mapReadOnly": "--map is read-only \u2014 combine it with scan, not with delete/clean",
2077
- "cli.err.baselineOnlyStats": "--save-baseline/--compare/--history only work with the stats command \u2014 nmh stats --save-baseline <name>",
2078
- "cli.err.statsReadOnly": "--stats is read-only \u2014 combine it with scan, not with delete/clean",
2079
- "cli.err.globalShapeFlags": "--tree/--top/--by/--graph/--reinstall shape per-project stats \u2014 global mode has its own table",
2080
- "cli.err.globalNoDir": "--global analyzes the PM global prefixes \u2014 no [dir] needed",
2081
- "cli.err.invalidTop": "invalid --top: {value} (expected a positive integer)",
2082
- "cli.err.topByStats": "--top/--by only work with the stats command",
2083
- "cli.err.globalOnlyStats": "--global only works with the stats command \u2014 nmh stats -g",
2084
- "cli.err.trashNotHard": "--trash applies to trash mode \u2014 hard delete is permanent by design, there is no trash to choose",
2085
- "cli.err.deleteNeedsTty": "--delete without a value needs an interactive terminal \u2014 pass hard | soft | trash (soft = trash)",
2068
+ "cli.err.configNeedsPath": "--config \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043F\u0443\u0442\u044C \u043A \u0444\u0430\u0439\u043B\u0443 \u2014 nmh --config <file> \u2026",
2069
+ "cli.err.languageNeedsValue": "--language \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 nmh --language id (en | id | zh | ru | es)",
2070
+ "cli.err.invalidLanguage": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --language: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C en | id | zh | ru | es)",
2071
+ "cli.warn.futureFlag": "{flag} \u043F\u043E\u044F\u0432\u0438\u0442\u0441\u044F \u0432 \u0431\u043E\u043B\u0435\u0435 \u043F\u043E\u0437\u0434\u043D\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 (v0.2+) \u2014 \u043F\u043E\u043A\u0430 \u0438\u0433\u043D\u043E\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044F",
2072
+ "cli.warn.sizeTopN": "--size <n> (\u0442\u043E\u043F-N \u0441\u043F\u0438\u0441\u043E\u043A) \u043F\u043E\u044F\u0432\u0438\u0442\u0441\u044F \u0432 \u0431\u043E\u043B\u0435\u0435 \u043F\u043E\u0437\u0434\u043D\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u2014 \u043F\u043E\u043A\u0430 \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u044F\u0435\u043C \u043A\u0430\u0436\u0434\u0443\u044E \u043F\u0430\u043F\u043A\u0443",
2073
+ "cli.err.invalidSize": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --size: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C 'total' \u0438\u043B\u0438 'each')",
2074
+ "cli.err.sizeNeedsValue": "--size \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 --size=total \u0438\u043B\u0438 --size=each (\u0433\u043E\u043B\u044B\u0439 --size \u0440\u0435\u0436\u0438\u043C \u043D\u0435 \u0432\u044B\u0431\u0438\u0440\u0430\u0435\u0442)",
2075
+ "cli.err.sizeTwice": "--size \u0443\u043A\u0430\u0437\u0430\u043D \u0431\u043E\u043B\u0435\u0435 \u0440\u0430\u0437\u0430 \u2014 \u043F\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 \u043E\u0434\u043D\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 (total | each)",
2076
+ "cli.err.staleNeedsValue": "--stale \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 --stale=<\u0434\u043D\u0435\u0439> (\u043D\u0430\u043F\u0440. --stale=90)",
2077
+ "cli.err.staleTwice": "--stale \u0443\u043A\u0430\u0437\u0430\u043D \u0431\u043E\u043B\u0435\u0435 \u0440\u0430\u0437\u0430 \u2014 \u043F\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 \u043E\u0434\u043D\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 (\u0434\u043D\u0438)",
2078
+ "cli.err.invalidStale": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --stale: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u043E\u043B\u043E\u0436\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0446\u0435\u043B\u043E\u0435 \u0447\u0438\u0441\u043B\u043E \u0434\u043D\u0435\u0439)",
2079
+ "cli.err.sortNeedsValue": "--sort \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 --sort=size | path | idle | mtime",
2080
+ "cli.err.sortTwice": "--sort \u0443\u043A\u0430\u0437\u0430\u043D \u0431\u043E\u043B\u0435\u0435 \u0440\u0430\u0437\u0430 \u2014 \u043F\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 \u043E\u0434\u0438\u043D \u043A\u043B\u044E\u0447",
2081
+ "cli.err.invalidSort": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --sort: {key} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C size | path | idle | mtime)",
2082
+ "cli.err.trashNeedsValue": "--trash \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 --trash=system \u0438\u043B\u0438 --trash=nmh",
2083
+ "cli.err.trashTwice": "--trash \u0443\u043A\u0430\u0437\u0430\u043D \u0431\u043E\u043B\u0435\u0435 \u0440\u0430\u0437\u0430 \u2014 \u043F\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 \u043E\u0434\u0438\u043D \u0440\u0435\u0436\u0438\u043C",
2084
+ "cli.err.invalidTrash": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --trash: {mode} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C system | nmh)",
2085
+ "cli.err.invalidDelete": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --delete: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C 'hard' | 'soft' | 'trash')",
2086
+ "cli.verbose.deleteModeFromRc": "\u0440\u0435\u0436\u0438\u043C \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u0438\u0437 .nmhrc: {mode}",
2087
+ "cli.err.invalidPm": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --pm: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C npm | pnpm | yarn | bun | vp)",
2088
+ "cli.err.depthNeedsValue": "--depth \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043D\u0435\u043E\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0446\u0435\u043B\u043E\u0435 \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 --depth=<n> (\u043D\u0430\u043F\u0440. --depth=2)",
2089
+ "cli.err.invalidDepth": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --depth: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C \u043D\u0435\u043E\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0446\u0435\u043B\u043E\u0435)",
2090
+ "cli.err.saveReportNeedsValue": "--save-report \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043F\u0443\u0442\u044C \u043A \u0444\u0430\u0439\u043B\u0443 (.json/.md/.txt)",
2091
+ "cli.err.reportNeedsValue": "--report \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043F\u0443\u0442\u044C \u043A \u0444\u0430\u0439\u043B\u0443 (.json/.md/.txt)",
2092
+ "cli.err.invalidReportExt": "\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442 \u043E\u0442\u0447\u0451\u0442\u0430: {file} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C .json/.md/.txt)",
2093
+ "cli.err.baselineNeedsName": "--save-baseline \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u043C\u044F \u2014 nmh stats --save-baseline <name>",
2094
+ "cli.err.compareNeedsName": "--compare \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u043C\u044F \u2014 nmh stats --compare <name>",
2095
+ "cli.err.invalidBaseline": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0438\u043C\u044F \u0431\u0430\u0437\u044B: '{name}' (\u0431\u0443\u043A\u0432\u044B/\u0446\u0438\u0444\u0440\u044B/._-, \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C 64)",
2096
+ "cli.err.unknownCommand": "\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430\u044F \u043A\u043E\u043C\u0430\u043D\u0434\u0430 '{cmd}' \u2014 \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 `nmh help` \u0434\u043B\u044F \u0441\u043F\u0438\u0441\u043A\u0430 \u043A\u043E\u043C\u0430\u043D\u0434 (\u043F\u0443\u0442\u0438 \u043F\u0435\u0440\u0435\u0434\u0430\u044E\u0442\u0441\u044F \u0432 `nmh scan` \u0438\u043B\u0438 `--dir`)",
2097
+ "cli.err.pmBare": "--pm \u0431\u0435\u0437 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043B\u0438\u0448\u044C \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u044F\u0435\u0442 \u043E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D\u043D\u044B\u0435 PM \u2014 \u0443\u043A\u0430\u0436\u0438\u0442\u0435 \u0441\u0435\u043C\u0435\u0439\u0441\u0442\u0432\u043E (npm|pnpm|yarn|bun|vp), \u0447\u0442\u043E\u0431\u044B \u0444\u0438\u043B\u044C\u0442\u0440\u043E\u0432\u0430\u0442\u044C \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u0438\u043B\u0438 \u0430\u043D\u0430\u043B\u0438\u0437 --global",
2098
+ "cli.err.reportNotDelete": "--save-report \u0445\u043E\u0434\u0438\u0442 \u0432 \u043A\u043E\u043C\u043F\u043B\u0435\u043A\u0442\u0435 \u0441\u043E scan \u2014 \u0437\u0430\u043F\u0443\u0441\u043A\u0438 delete/clean \u043D\u0435 \u044F\u0432\u043B\u044F\u044E\u0442\u0441\u044F \u043E\u0442\u0447\u0451\u0442\u0430\u043C\u0438 \u0441\u043A\u0430\u043D\u0430",
2099
+ "cli.warn.trashOnly": "--trash \u0432\u0430\u0436\u0435\u043D \u043B\u0438\u0448\u044C \u0434\u043B\u044F \u0437\u0430\u043F\u0443\u0441\u043A\u043E\u0432 delete/clean \u2014 \u0432 \u0441\u043A\u0430\u043D\u0430\u0445 \u0438 \u043A\u043E\u043C\u0430\u043D\u0434\u0430\u0445 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u044F \u0438\u0433\u043D\u043E\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044F",
2100
+ "cli.err.rootRefusal": "\u043E\u0442\u043A\u0430\u0437 \u043E\u0442 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u043F\u043E\u0432\u0435\u0440\u0445 \u043A\u043E\u0440\u043D\u044F \u0444\u0430\u0439\u043B\u043E\u0432\u043E\u0439 \u0441\u0438\u0441\u0442\u0435\u043C\u044B \u2014 \u043D\u0430\u043F\u0440\u0430\u0432\u044C\u0442\u0435 --dir \u043D\u0430 \u043A\u0430\u0442\u0430\u043B\u043E\u0433 \u043F\u0440\u043E\u0435\u043A\u0442\u0430, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0445\u043E\u0442\u0438\u0442\u0435 \u043F\u043E\u0447\u0438\u0441\u0442\u0438\u0442\u044C",
2101
+ "cli.err.checkOnlyUpdate": "--check \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 update \u2014 nmh update --check",
2102
+ "cli.err.infoOnlyUpdate": "--info \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 update \u2014 nmh update --info",
2103
+ "cli.err.tagNeedsValue": "--tag \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u043C\u044F dist-tag \u2014 nmh update --tag beta (--check \u0431\u0435\u0437 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u0447\u0438\u0442\u0430\u0435\u0442 --tag / .nmhrc / latest)",
2104
+ "cli.err.invalidTag": '\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 dist-tag "{value}" \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0431\u0443\u043A\u0432\u044B, \u0446\u0438\u0444\u0440\u044B, \u0442\u043E\u0447\u043A\u0430, \u0434\u0435\u0444\u0438\u0441, \u043F\u043E\u0434\u0447\u0451\u0440\u043A\u0438\u0432\u0430\u043D\u0438\u0435',
2105
+ "cli.err.tagOnlyUpdate": "--tag \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 update \u2014 nmh update --tag beta",
2106
+ "cli.err.updateArgs": "update \u043D\u0435 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432 \u2014 \u043F\u0440\u043E\u0441\u0442\u043E `nmh update` (\u0434\u043E\u0431\u0430\u0432\u044C\u0442\u0435 --json \u0434\u043B\u044F \u043C\u0430\u0448\u0438\u043D\u043E\u0447\u0438\u0442\u0430\u0435\u043C\u043E\u0433\u043E \u0432\u044B\u0432\u043E\u0434\u0430)",
2107
+ "cli.err.checkInfoExclusive": "--check \u0438 --info \u2014 \u0434\u0432\u0430 \u0440\u0430\u0437\u043D\u044B\u0445 \u0432\u0438\u0434\u0430 \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F \u2014 \u0432\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043E\u0434\u0438\u043D (nmh update --check | --info)",
2108
+ "cli.err.routerOrphan": "\u0440\u043E\u0443\u0442\u0435\u0440 `--` \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0438\u0442 \u043C\u0430\u0441\u0442\u0435\u0440\u0443 \u2014 nmh wizard -- stats|map|search|why|treemap \u2026",
2109
+ "cli.err.unknownWizardView": "\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u0432\u0438\u0434 \u043C\u0430\u0441\u0442\u0435\u0440\u0430: {view} \u2014 \u0440\u043E\u0443\u0442\u0435\u0440 \u043E\u0442\u043A\u0440\u044B\u0432\u0430\u0435\u0442 \u0432\u0438\u0434 \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F: stats (analyze, info) | map | search | why | treemap",
2110
+ "cli.err.wizardPositional": "\u043C\u0430\u0441\u0442\u0435\u0440 \u043D\u0435 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442 \u043F\u043E\u0437\u0438\u0446\u0438\u043E\u043D\u043D\u044B\u0445 \u0446\u0435\u043B\u0435\u0439 \u2014 \u043E\u0433\u0440\u0430\u043D\u0438\u0447\u044C\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 --dir=./repo1,./repo2 (\u0438\u043B\u0438 `nmh wizard -- <view> \u2026`)",
2111
+ "cli.err.wizardDelete": "--delete \u043D\u0435 \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0438\u0442 \u043C\u0430\u0441\u0442\u0435\u0440\u0443 \u2014 \u043C\u0435\u043D\u044E \u0441\u0430\u043C\u043E \u0441\u043F\u0440\u043E\u0441\u0438\u0442 \u0440\u0435\u0436\u0438\u043C",
2112
+ "cli.err.wizardNeedsTTY": "\u043C\u0430\u0441\u0442\u0435\u0440\u0443 \u043D\u0443\u0436\u0435\u043D TTY (\u044D\u0442\u043E \u043C\u0435\u043D\u044E \u043D\u0430 \u0441\u0442\u0440\u0435\u043B\u043A\u0430\u0445) \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 nmh scan / --dir / \u043E\u0431\u044B\u0447\u043D\u044B\u0435 \u043A\u043E\u043C\u0430\u043D\u0434\u044B; \u0433\u043E\u043B\u044B\u0439 `nmh` \u0432 \u043F\u0430\u0439\u043F\u0435 \u043E\u0441\u0442\u0430\u0451\u0442\u0441\u044F \u0441\u043A\u0430\u043D\u043E\u043C \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F",
2113
+ "cli.err.configOp": "config \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u2014 nmh config info | set | add | remove | unset (\u0432\u0437\u0433\u043B\u044F\u043D\u0438\u0442\u0435: nmh config info)",
2114
+ "cli.err.configPositional": "config {op} \u043D\u0435 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442 \u043F\u043E\u0437\u0438\u0446\u0438\u043E\u043D\u043D\u044B\u0445 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432 \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u0444\u043B\u0430\u0433\u0438 (--default-exclude \u2026, --depth \u2026)",
2115
+ "cli.err.configDelete": "--delete \u043D\u0435 \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0438\u0442 nmh config \u2014 \u0442\u043E\u0442 \u0443\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u0442 \u0444\u0430\u0439\u043B\u043E\u043C .nmhrc, \u0438 \u0442\u043E\u043B\u044C\u043A\u043E",
2116
+ "cli.err.statsFlagsOnly": "--phantom/--dead/--licenses/--score/--co2/--online/--graph/--reinstall \u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 stats \u2014 nmh stats --reinstall",
2117
+ "cli.err.searchReadOnly": "--search \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F \u2014 \u0441\u043E\u0447\u0435\u0442\u0430\u0439\u0442\u0435 \u0441\u043E scan, \u0430 \u043D\u0435 \u0441 delete/clean",
2118
+ "cli.err.searchNeedsPattern": "search \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0448\u0430\u0431\u043B\u043E\u043D \u2014 nmh search <pattern> [dirs]",
2119
+ "cli.err.whyReadOnly": "--why \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F \u2014 \u0441\u043E\u0447\u0435\u0442\u0430\u0439\u0442\u0435 \u0441\u043E scan, \u0430 \u043D\u0435 \u0441 delete/clean",
2120
+ "cli.err.whyNeedsPkg": "why \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u043C\u044F \u043F\u0430\u043A\u0435\u0442\u0430 \u2014 nmh why <pkg> [dirs]",
2121
+ "cli.err.whyConflict": "--why ({why}) \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u0443\u0435\u0442 \u0441 \u043F\u0430\u043A\u0435\u0442\u043E\u043C \u043F\u043E\u0434\u043A\u043E\u043C\u0430\u043D\u0434\u044B why ({pkg}) \u2014 \u0432\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043E\u0434\u043D\u043E",
2122
+ "cli.err.whyFlagNeedsPkg": "--why \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u043C\u044F \u043F\u0430\u043A\u0435\u0442\u0430 \u2014 nmh why <pkg> [dirs]",
2123
+ "cli.err.treemapReadOnly": "--treemap \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F \u2014 \u0441\u043E\u0447\u0435\u0442\u0430\u0439\u0442\u0435 \u0441\u043E scan, \u0430 \u043D\u0435 \u0441 delete/clean",
2124
+ "cli.err.reportNotTreemap": "--save-report \u0441 treemap \u043D\u0435 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u2014 HTML-\u0444\u0430\u0439\u043B \u0438 \u0415\u0421\u0422\u042C \u043E\u0442\u0447\u0451\u0442 (nmh treemap --out <file>)",
2125
+ "cli.err.outNeedsValue": "--out \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043F\u0443\u0442\u044C \u043A \u0444\u0430\u0439\u043B\u0443 \u2014 nmh treemap --out report.html",
2126
+ "cli.err.outOnlyTreemap": "--out \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 treemap \u2014 nmh treemap --out file.html",
2127
+ "cli.err.invalidBy": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --by: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C 'package' | 'size' | 'type' | 'licenses')",
2128
+ "cli.err.dependOnlyMap": "--depend \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 map \u2014 nmh map <dirs> --depend [pkg]",
2129
+ "cli.err.treeMapStats": "--tree \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u0441 map \u0438\u043B\u0438 stats, --depend \u0442\u043E\u043B\u044C\u043A\u043E \u0441 map \u2014 nmh map <dirs> --depend [pkg]",
2130
+ "cli.err.mapReadOnly": "--map \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F \u2014 \u0441\u043E\u0447\u0435\u0442\u0430\u0439\u0442\u0435 \u0441\u043E scan, \u0430 \u043D\u0435 \u0441 delete/clean",
2131
+ "cli.err.baselineOnlyStats": "--save-baseline/--compare/--history \u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 stats \u2014 nmh stats --save-baseline <name>",
2132
+ "cli.err.statsReadOnly": "--stats \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F \u2014 \u0441\u043E\u0447\u0435\u0442\u0430\u0439\u0442\u0435 \u0441\u043E scan, \u0430 \u043D\u0435 \u0441 delete/clean",
2133
+ "cli.err.globalShapeFlags": "--tree/--top/--by/--graph/--reinstall \u0444\u043E\u0440\u043C\u0438\u0440\u0443\u044E\u0442 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u043F\u043E \u043F\u0440\u043E\u0435\u043A\u0442\u0430\u043C \u2014 \u0443 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u0440\u0435\u0436\u0438\u043C\u0430 \u0441\u0432\u043E\u044F \u0442\u0430\u0431\u043B\u0438\u0446\u0430",
2134
+ "cli.err.globalNoDir": "--global \u0430\u043D\u0430\u043B\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0435 \u043F\u0440\u0435\u0444\u0438\u043A\u0441\u044B PM \u2014 [dir] \u043D\u0435 \u043D\u0443\u0436\u0435\u043D",
2135
+ "cli.err.invalidTop": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --top: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u043E\u043B\u043E\u0436\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0446\u0435\u043B\u043E\u0435)",
2136
+ "cli.err.topByStats": "--top/--by \u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 stats",
2137
+ "cli.err.globalOnlyStats": "--global \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043B\u0438\u0448\u044C \u0441 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439 stats \u2014 nmh stats -g",
2138
+ "cli.err.trashNotHard": "--trash \u043E\u0442\u043D\u043E\u0441\u0438\u0442\u0441\u044F \u043A \u0440\u0435\u0436\u0438\u043C\u0443 \u043A\u043E\u0440\u0437\u0438\u043D\u044B \u2014 \u0436\u0451\u0441\u0442\u043A\u043E\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u043F\u043E \u0434\u0438\u0437\u0430\u0439\u043D\u0443 \u0431\u0435\u0437\u0432\u043E\u0437\u0432\u0440\u0430\u0442\u043D\u043E, \u0432\u044B\u0431\u0438\u0440\u0430\u0442\u044C \u043A\u043E\u0440\u0437\u0438\u043D\u0443 \u043D\u0435 \u0438\u0437 \u0447\u0435\u0433\u043E",
2139
+ "cli.err.deleteNeedsTty": "--delete \u0431\u0435\u0437 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0433\u043E \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0430 \u2014 \u043F\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 hard | soft | trash (soft = trash)",
2086
2140
  "cli.verbose.configSource": "config: {file}",
2087
- "cli.verbose.configFamilySkip": "config: read-phase lookup skipped for the config family",
2141
+ "cli.verbose.configFamilySkip": "config: \u0434\u043B\u044F \u0441\u0435\u043C\u0435\u0439\u0441\u0442\u0432\u0430 config \u043F\u043E\u0438\u0441\u043A \u0432 \u0444\u0430\u0437\u0435 \u0447\u0442\u0435\u043D\u0438\u044F \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D",
2088
2142
  // ── config family ───────────────────────────────────────────────────────
2089
- "config.err.notJson": "invalid config: {file} is not valid JSON ({detail})",
2090
- "config.err.notJsonWritable": "invalid config: {file} is not valid JSON ({detail}) \u2014 fix it before nmh config writes",
2091
- "config.err.notObject": "invalid config: {file} must contain a JSON object",
2092
- "config.err.invalidMode": "invalid config: {file}: defaultMode must be 'hard' | 'soft' | 'trash' (got {value})",
2093
- "config.err.invalidDepth": "invalid config: {file}: depth must be a non-negative integer (got {value})",
2094
- "config.err.invalidList": "invalid config: {file}: {key} must be an array of non-empty strings",
2095
- "config.err.notBoolean": "invalid config: {file}: {key} must be true or false (got {value})",
2096
- "config.err.invalidLanguage": "invalid config: {file}: language must be one of en | id | zh | ru | es (got {value})",
2097
- "config.err.invalidLogDir": "invalid config: {file}: logDir must be a non-empty string",
2098
- "config.err.unreadable": "config unreadable: {file} ({code})",
2099
- "config.err.notFound": "config file not found: {file}",
2100
- "config.warn.unknownKey": '{file}: unknown config key "{key}" \u2014 ignored',
2101
- "config.err.depthNeedsValue": "--depth needs a non-negative integer \u2014 nmh config set --depth 2",
2102
- "config.err.invalidDepthValue": "invalid --depth value: {value} (expected a non-negative integer)",
2103
- "config.err.invalidModeValue": "invalid --default-mode: {value} (expected hard | soft | trash)",
2104
- "config.err.invalidLanguageValue": "invalid --language value: {value} (expected en | id | zh | ru | es)",
2105
- "config.err.boolNeedsValue": "{label} needs true or false \u2014 e.g. nmh config set --animate=false",
2106
- "config.err.setListNeedsValue": "config set --{flag} needs the list value \u2014 e.g. --{flag}=.npm,.nvm",
2107
- "config.err.addListNeedsValue": "config add --{flag} needs items to append \u2014 e.g. --{flag}=.cache,self",
2108
- "config.err.logDirNeedsValue": "--log-dir needs a non-empty directory path",
2109
- "config.err.setNeedsKey": "config set needs at least one key \u2014 nmh config set --depth 2 | --default-mode trash | --default-exclude .npm,self | \u2026",
2110
- "config.err.listOpsOnly": "config {op} works on list keys \u2014 use --default-exclude or --default-keep",
2111
- "config.err.unsetNeedsKey": "config unset needs a key \u2014 e.g. nmh config unset --default-exclude (or --depth)",
2112
- "config.err.infoReadOnly": "nmh config info is read-only \u2014 key flags belong to set/add/remove",
2113
- "config.info.activeFile": "active file",
2114
- "config.info.noFile": "none \u2014 defaults in effect (create one: nmh config set \u2026)",
2115
- "config.info.items": "{n} item(s): {list}",
2116
- "config.info.manageHint": "manage: nmh config set \xB7 add \xB7 remove \xB7 unset (lists: --default-exclude / --default-keep)",
2117
- "config.info.selfHint": 'special value "self" in exclude/keep = protect the folder nmh runs from (scan-level guard)',
2118
- "config.info.removed": "(removed from file)"
2143
+ "config.err.notJson": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file} \u2014 \u043D\u0435 \u0432\u0430\u043B\u0438\u0434\u043D\u044B\u0439 JSON ({detail})",
2144
+ "config.err.notJsonWritable": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file} \u2014 \u043D\u0435 \u0432\u0430\u043B\u0438\u0434\u043D\u044B\u0439 JSON ({detail}) \u2014 \u0438\u0441\u043F\u0440\u0430\u0432\u044C\u0442\u0435 \u0434\u043E \u0437\u0430\u043F\u0438\u0441\u0438 \u0447\u0435\u0440\u0435\u0437 nmh config",
2145
+ "config.err.notObject": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file} \u0434\u043E\u043B\u0436\u0435\u043D \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442\u044C JSON-\u043E\u0431\u044A\u0435\u043A\u0442",
2146
+ "config.err.invalidMode": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file}: defaultMode \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C 'hard' | 'soft' | 'trash' (\u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E {value})",
2147
+ "config.err.invalidDepth": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file}: depth \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435\u043E\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u043C \u0446\u0435\u043B\u044B\u043C (\u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E {value})",
2148
+ "config.err.invalidList": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file}: {key} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043C\u0430\u0441\u0441\u0438\u0432\u043E\u043C \u043D\u0435\u043F\u0443\u0441\u0442\u044B\u0445 \u0441\u0442\u0440\u043E\u043A",
2149
+ "config.err.notBoolean": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file}: {key} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C true \u0438\u043B\u0438 false (\u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E {value})",
2150
+ "config.err.invalidLanguage": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file}: language \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043E\u0434\u043D\u0438\u043C \u0438\u0437 en | id | zh | ru | es (\u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E {value})",
2151
+ "config.err.invalidLogDir": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file}: logDir \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435\u043F\u0443\u0441\u0442\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u043E\u0439",
2152
+ "config.err.invalidUpdateTag": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433: {file}: updateTag \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0438\u043C\u0435\u043D\u0435\u043C dist-tag \u2014 \u0431\u0443\u043A\u0432\u044B, \u0446\u0438\u0444\u0440\u044B, \u0442\u043E\u0447\u043A\u0430, \u0434\u0435\u0444\u0438\u0441, \u043F\u043E\u0434\u0447\u0451\u0440\u043A\u0438\u0432\u0430\u043D\u0438\u0435 (\u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E {value})",
2153
+ "config.err.unreadable": "\u043A\u043E\u043D\u0444\u0438\u0433 \u043D\u0435\u0447\u0438\u0442\u0430\u0435\u043C: {file} ({code})",
2154
+ "config.err.notFound": "\u0444\u0430\u0439\u043B \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: {file}",
2155
+ "config.warn.unknownKey": '{file}: \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u043A\u043B\u044E\u0447 \u043A\u043E\u043D\u0444\u0438\u0433\u0430 "{key}" \u2014 \u0438\u0433\u043D\u043E\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044F',
2156
+ "config.err.depthNeedsValue": "--depth \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043D\u0435\u043E\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0446\u0435\u043B\u043E\u0435 \u2014 nmh config set --depth 2",
2157
+ "config.err.invalidDepthValue": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 --depth: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C \u043D\u0435\u043E\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0446\u0435\u043B\u043E\u0435)",
2158
+ "config.err.invalidModeValue": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 --default-mode: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C hard | soft | trash)",
2159
+ "config.err.invalidLanguageValue": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 --language: {value} (\u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C en | id | zh | ru | es)",
2160
+ "config.err.invalidUpdateTagValue": "\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 --update-tag: {value} (\u0431\u0443\u043A\u0432\u044B, \u0446\u0438\u0444\u0440\u044B, \u0442\u043E\u0447\u043A\u0430, \u0434\u0435\u0444\u0438\u0441, \u043F\u043E\u0434\u0447\u0451\u0440\u043A\u0438\u0432\u0430\u043D\u0438\u0435)",
2161
+ "config.err.boolNeedsValue": "{label} \u0442\u0440\u0435\u0431\u0443\u0435\u0442 true \u0438\u043B\u0438 false \u2014 \u043D\u0430\u043F\u0440. nmh config set --animate=false",
2162
+ "config.err.setListNeedsValue": "config set --{flag} \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0441\u043F\u0438\u0441\u043A\u0430 \u2014 \u043D\u0430\u043F\u0440. --{flag}=.npm,.nvm",
2163
+ "config.err.addListNeedsValue": "config add --{flag} \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B \u0434\u043B\u044F \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F \u2014 \u043D\u0430\u043F\u0440. --{flag}=.cache,self",
2164
+ "config.err.logDirNeedsValue": "--log-dir \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043D\u0435\u043F\u0443\u0441\u0442\u043E\u0439 \u043F\u0443\u0442\u044C \u043A \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0443",
2165
+ "config.err.setNeedsKey": "config set \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D \u043A\u043B\u044E\u0447 \u2014 nmh config set --depth 2 | --default-mode trash | --default-exclude .npm,self | \u2026",
2166
+ "config.err.listOpsOnly": "config {op} \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u0441 \u043A\u043B\u044E\u0447\u0430\u043C\u0438-\u0441\u043F\u0438\u0441\u043A\u0430\u043C\u0438 \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 --default-exclude \u0438\u043B\u0438 --default-keep",
2167
+ "config.err.unsetNeedsKey": "config unset \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043A\u043B\u044E\u0447 \u2014 \u043D\u0430\u043F\u0440. nmh config unset --default-exclude (\u0438\u043B\u0438 --depth)",
2168
+ "config.err.infoReadOnly": "nmh config info \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0447\u0442\u0435\u043D\u0438\u044F \u2014 \u0444\u043B\u0430\u0433\u0438-\u043A\u043B\u044E\u0447\u0438 \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0430\u0442 set/add/remove",
2169
+ "config.info.activeFile": "\u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u0444\u0430\u0439\u043B",
2170
+ "config.info.noFile": "\u043D\u0435\u0442 \u2014 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044E\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E (\u0441\u043E\u0437\u0434\u0430\u0439\u0442\u0435: nmh config set \u2026)",
2171
+ "config.info.items": "\u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432: {n}: {list}",
2172
+ "config.info.manageHint": "\u0443\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435: nmh config set \xB7 add \xB7 remove \xB7 unset (\u0441\u043F\u0438\u0441\u043A\u0438: --default-exclude / --default-keep)",
2173
+ "config.info.selfHint": '\u0441\u043F\u0435\u0446-\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 "self" \u0432 exclude/keep = \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044C \u043F\u0430\u043F\u043A\u0443, \u0438\u0437 \u043A\u043E\u0442\u043E\u0440\u043E\u0439 \u0437\u0430\u043F\u0443\u0449\u0435\u043D nmh (\u0431\u0430\u0440\u044C\u0435\u0440 \u0443\u0440\u043E\u0432\u043D\u044F \u0441\u043A\u0430\u043D\u0430)',
2174
+ "config.info.removed": "(\u0443\u0434\u0430\u043B\u0435\u043D\u043E \u0438\u0437 \u0444\u0430\u0439\u043B\u0430)"
2119
2175
  };
2120
2176
  var ru_default = ru;
2121
2177
 
@@ -2302,6 +2358,7 @@ var es = {
2302
2358
  "wizard.menu.map": "\u{1F5FA}\uFE0F Mapear dependencias \u2014 proyecto \u2192 PM \u2192 deps declaradas",
2303
2359
  "wizard.menu.stats": "\u{1F4CA} Informe detallado \u2014 la lectura completa de stats",
2304
2360
  "wizard.menu.settings": "\u2699\uFE0F Ajustes e integraci\xF3n (vista de solo lectura)",
2361
+ "wizard.menu.update": "\u{1F501} Actualizar nmh (consulta el registro, pregunta primero)",
2305
2362
  "wizard.menu.quit": "\u23F9 Salir de nmh",
2306
2363
  "wizard.outro.bye": "adi\xF3s \u{1F44B} \u2014 no se elimin\xF3 nada",
2307
2364
  "wizard.search.message": "Buscar paquetes instalados \u2014 \xBFqu\xE9 patr\xF3n?",
@@ -2356,6 +2413,11 @@ var es = {
2356
2413
  "update.err.failed": "\u26A0 fall\xF3 la actualizaci\xF3n: {detail}",
2357
2414
  "update.err.manualHint": " prueba manual: npm install -g node-modules-hunter@{latest}",
2358
2415
  "update.done": "\u2713 actualizado {current} \u2192 {latest} (npm install -g node-modules-hunter)",
2416
+ "update.info.tags": "dist-tags {tags}",
2417
+ "update.check.onTag": "(dist-tag: {tag})",
2418
+ "update.confirm.downgrade": '\xBFBajar nmh {current} \u2192 {target} desde el dist-tag "{tag}"?',
2419
+ "update.err.tagUnknown": 'dist-tag "{tag}" no encontrado \u2014 disponibles: {tags}',
2420
+ "update.err.invalidTag": 'dist-tag "{value}" inv\xE1lido \u2014 usa letras, d\xEDgitos, punto, guion, guion bajo',
2359
2421
  // ── commands/global.ts ──────────────────────────────────────────────────
2360
2422
  "global.spin.probe": "sondeando prefijos globales\u2026",
2361
2423
  "global.spin.progress": "global {pm} \u2014 {done}/{total} paquetes",
@@ -2421,9 +2483,9 @@ var es = {
2421
2483
  "help.statsSub.title": "Subcomandos de stats",
2422
2484
  "help.options.title": "Opciones \u2014 {group}",
2423
2485
  "help.examples.title": "Ejemplos",
2424
- "help.cmd.bare": "asistente interactivo: men\xFA con flechas (eliminar todo / elegir / search / map / informe / ajustes)",
2486
+ "help.cmd.bare": "asistente interactivo: men\xFA con flechas (eliminar todo / elegir / search / map / informe / actualizar / ajustes)",
2425
2487
  "help.cmd.paths": "atajo: escanea las rutas dadas; acciones de una l\xEDnea v\xEDa flags (--delete, --search, \u2026)",
2426
- "help.cmd.wizard": "v1.2: asistente sobre objetivos expl\xEDcitos (--dir=./a,./b salta el auto-climb); -- <vista> abre primero la vista",
2488
+ "help.cmd.wizard": "v1.2: asistente sobre objetivos expl\xEDcitos (--dir=./a,./b salta el auto-climb); -- <vista> abre primero la vista; el men\xFA ahora incluye \u{1F501} Actualizar nmh (v1.4)",
2427
2489
  "help.cmd.scan": "escaneo completo de todos los objetivos (por defecto: cwd)",
2428
2490
  "help.cmd.clean": "escanea + elimina todo lo seguro (trash por defecto)",
2429
2491
  "help.cmd.search": "busca paquetes instalados por nombre (+ versi\xF3n y tama\xF1o) \u2014 solo lectura",
@@ -2433,7 +2495,7 @@ var es = {
2433
2495
  "help.cmd.treemap": "treemap HTML interactivo de un solo archivo \u2192 nmh-treemap.html",
2434
2496
  "help.cmd.global": "instalaciones globales de npm/pnpm/yarn/bun \u2014 solo lectura",
2435
2497
  "help.cmd.config": "gestiona .nmhrc desde el CLI: info \xB7 set \xB7 add \xB7 remove \xB7 unset",
2436
- "help.cmd.update": "v1.2: muestra datos y pregunta antes de instalar \u2014 --check / --info solo comparan; -y instala, -n rechaza, --force salta la pregunta",
2498
+ "help.cmd.update": "v1.4: muestra datos y pregunta antes de instalar \u2014 --check [tag] / --info solo comparan; --tag lee un dist-tag (el downgrade confirma con NO por defecto); -y instala, -n rechaza, --force salta la pregunta",
2437
2499
  "help.cmd.version": "banner: versi\xF3n de la herramienta, node+abi, SO/arquitectura/kernel, tty (alias: -v / --version)",
2438
2500
  "help.cmd.help": "esta ayuda (alias: -h / --help)",
2439
2501
  "help.statsSub.byType": "desglose por campo de dependencia (dep/dev/optional/peer/transitive)",
@@ -2463,6 +2525,8 @@ var es = {
2463
2525
  "help.flag.saveReport": "escribe tambi\xE9n el informe impreso a un archivo (.json/.md/.txt; --report <archivo> es alias)",
2464
2526
  "help.flag.wizard": "v1.2: abre el asistente expl\xEDcitamente \u2014 igual que `nmh` simple, pero una pipe rechaza con direcci\xF3n en vez de escanear",
2465
2527
  "help.flag.updateFamily": "v1.2: vistas de solo lectura vs instalaci\xF3n aprobada \u2014 ver la l\xEDnea de `nmh update` arriba",
2528
+ "help.flag.tag": "lee un dist-tag npm espec\xEDfico \u2014 nmh update --tag beta; --check <tag> compara contra \xE9l (v1.4)",
2529
+ "help.flag.updateTag": "dist-tag de actualizaci\xF3n persistido (updateTag en .nmhrc) \u2014 lo que `nmh update` / `--check` leen por defecto (v1.4)",
2466
2530
  "help.flag.updateCheck": "consulta npm por versiones m\xE1s nuevas (sin bloqueo, cach\xE9 de 24 h; tambi\xE9n en .nmhrc)",
2467
2531
  "help.flag.stale": "solo proyectos inactivos >= <d\xEDas>; escalera = git commit \u2192 manifiesto \u2192 mtime de carpeta; sin prueba = descartado",
2468
2532
  "help.flag.fastSize": "mide con un `du -sk` por entrada (granularidad KiB) en vez de recorrer cada archivo",
@@ -2474,6 +2538,7 @@ var es = {
2474
2538
  "help.flag.verbose": "charla de depuraci\xF3n en stderr",
2475
2539
  "help.flag.noColor": "apaga el color ANSI (auto: color solo en TTY real o con --color / FORCE_COLOR)",
2476
2540
  "help.flag.color": "fuerza el color ANSI incluso en pipes (gana sobre config color:false)",
2541
+ "help.flag.language": "idioma de la UI: en | id | zh | ru | es \u2014 tambi\xE9n v\xEDa .nmhrc `language` y NMH_LANG; los valores desconocidos vuelven a en en silencio",
2477
2542
  "help.flag.recursive": "mira tambi\xE9n DENTRO de los node_modules encontrados (auditor\xEDa anidada; el total sigue siendo de nivel superior)",
2478
2543
  "help.flag.pm": "filtra por PM detectado: npm|pnpm|yarn|bun|vp \u2014 sin valor lista los detectados",
2479
2544
  "help.flag.exclude": "excluye rutas de los resultados (lista de globs separada por comas, p. ej. **/e2e/**)",
@@ -2549,6 +2614,9 @@ var es = {
2549
2614
  "cli.err.rootRefusal": "se rechaza la operaci\xF3n de delete sobre la ra\xEDz del sistema de archivos \u2014 apunta --dir al directorio del proyecto que quieres limpiar",
2550
2615
  "cli.err.checkOnlyUpdate": "--check es solo para el comando update \u2014 nmh update --check",
2551
2616
  "cli.err.infoOnlyUpdate": "--info es solo para el comando update \u2014 nmh update --info",
2617
+ "cli.err.tagNeedsValue": "--tag necesita un nombre de dist-tag \u2014 nmh update --tag beta (--check sin valor lee --tag / .nmhrc / latest)",
2618
+ "cli.err.invalidTag": 'dist-tag "{value}" inv\xE1lido \u2014 usa letras, d\xEDgitos, punto, guion, guion bajo',
2619
+ "cli.err.tagOnlyUpdate": "--tag es solo para el comando update \u2014 nmh update --tag beta",
2552
2620
  "cli.err.updateArgs": "update no acepta argumentos \u2014 `nmh update` simple (a\xF1ade --json para el payload)",
2553
2621
  "cli.err.checkInfoExclusive": "--check y --info son dos vistas de solo lectura distintas \u2014 elige una (nmh update --check | --info)",
2554
2622
  "cli.err.routerOrphan": "el `--` del router es del asistente \u2014 nmh wizard -- stats|map|search|why|treemap \u2026",
@@ -2595,6 +2663,7 @@ var es = {
2595
2663
  "config.err.notBoolean": "config inv\xE1lido: {file}: {key} debe ser true o false (recibido {value})",
2596
2664
  "config.err.invalidLanguage": "config inv\xE1lido: {file}: language debe ser uno de en | id | zh | ru | es (recibido {value})",
2597
2665
  "config.err.invalidLogDir": "config inv\xE1lido: {file}: logDir debe ser una cadena no vac\xEDa",
2666
+ "config.err.invalidUpdateTag": "config inv\xE1lido: {file}: updateTag debe ser un nombre de dist-tag \u2014 letras, d\xEDgitos, punto, guion, guion bajo (recibido {value})",
2598
2667
  "config.err.unreadable": "config ilegible: {file} ({code})",
2599
2668
  "config.err.notFound": "archivo de config no encontrado: {file}",
2600
2669
  "config.warn.unknownKey": "{file}: clave de config desconocida \xAB{key}\xBB \u2014 ignorada",
@@ -2602,6 +2671,7 @@ var es = {
2602
2671
  "config.err.invalidDepthValue": "valor de --depth inv\xE1lido: {value} (debe ser un entero no negativo)",
2603
2672
  "config.err.invalidModeValue": "valor de --default-mode inv\xE1lido: {value} (debe ser hard | soft | trash)",
2604
2673
  "config.err.invalidLanguageValue": "valor de --language inv\xE1lido: {value} (debe ser en | id | zh | ru | es)",
2674
+ "config.err.invalidUpdateTagValue": "valor de --update-tag inv\xE1lido: {value} (letras, d\xEDgitos, punto, guion, guion bajo)",
2605
2675
  "config.err.boolNeedsValue": "{label} necesita true o false \u2014 p. ej. nmh config set --animate=false",
2606
2676
  "config.err.setListNeedsValue": "config set --{flag} necesita el valor de la lista \u2014 p. ej. --{flag}=.npm,.nvm",
2607
2677
  "config.err.addListNeedsValue": "config add --{flag} necesita un elemento que a\xF1adir \u2014 p. ej. --{flag}=.cache,self",
@@ -2820,8 +2890,9 @@ var GROUPS = () => [
2820
2890
  { usage: "--size <mode>", desc: t("help.flag.size") },
2821
2891
  { usage: "--save-report <file>", desc: t("help.flag.saveReport") },
2822
2892
  { usage: "--wizard", desc: t("help.flag.wizard") },
2823
- { usage: "update: --check \xB7 --info \xB7 -y \xB7 -n \xB7 -f", desc: t("help.flag.updateFamily") },
2824
- { usage: "--update-check", desc: t("help.flag.updateCheck") }
2893
+ { usage: "update: --check [tag] \xB7 --tag <name> \xB7 --info \xB7 -y \xB7 -n \xB7 -f", desc: t("help.flag.updateFamily") },
2894
+ { usage: "--update-check", desc: t("help.flag.updateCheck") },
2895
+ { usage: "--tag <name>", desc: t("help.flag.tag") }
2825
2896
  ]
2826
2897
  },
2827
2898
  {
@@ -2836,7 +2907,9 @@ var GROUPS = () => [
2836
2907
  { usage: "-q, --quiet", desc: t("help.flag.quiet") },
2837
2908
  { usage: "--verbose", desc: t("help.flag.verbose") },
2838
2909
  { usage: "--no-color", desc: t("help.flag.noColor") },
2839
- { usage: "--color", desc: t("help.flag.color") }
2910
+ { usage: "--color", desc: t("help.flag.color") },
2911
+ { usage: "--language <lang>", desc: t("help.flag.language") },
2912
+ { usage: "--update-tag <name>", desc: t("help.flag.updateTag") }
2840
2913
  ]
2841
2914
  },
2842
2915
  {
@@ -2966,6 +3039,9 @@ var ConfigError = class extends Error {
2966
3039
  };
2967
3040
  var FILE_NAMES = [".nmhrc", ".nmhrc.json"];
2968
3041
  var VALID_MODES = /* @__PURE__ */ new Set(["hard", "soft", "trash"]);
3042
+ function isValidDistTag(tag) {
3043
+ return tag.length > 0 && tag.length <= 64 && /^[a-z0-9]([a-z0-9._-]*[a-z0-9])?$/i.test(tag);
3044
+ }
2969
3045
  function parseConfigBody(body, file) {
2970
3046
  let raw2;
2971
3047
  try {
@@ -3018,6 +3094,12 @@ function parseConfigBody(body, file) {
3018
3094
  }
3019
3095
  values.logDir = expandTilde(value);
3020
3096
  break;
3097
+ case "updateTag":
3098
+ if (typeof value !== "string" || !isValidDistTag(value)) {
3099
+ throw new ConfigError(t("config.err.invalidUpdateTag", { file, value: JSON.stringify(value) }));
3100
+ }
3101
+ values.updateTag = value;
3102
+ break;
3021
3103
  default:
3022
3104
  warn(t("config.warn.unknownKey", { file, key }));
3023
3105
  }
@@ -5107,7 +5189,7 @@ function registryUrl() {
5107
5189
  }
5108
5190
  function isNewer(current2, latest) {
5109
5191
  const triple = (v) => {
5110
- const match = /^(\d+)\.(\d+)\.(\d+)(.*)$/.exec(v.trim());
5192
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:-?([^+]*))?(?:\+.*)?$/.exec(v.trim());
5111
5193
  return match === null ? null : [Number(match[1]), Number(match[2]), Number(match[3]), match[4] ?? ""];
5112
5194
  };
5113
5195
  const now = triple(current2);
@@ -5117,7 +5199,26 @@ function isNewer(current2, latest) {
5117
5199
  if (next[i] > now[i]) return true;
5118
5200
  if (next[i] < now[i]) return false;
5119
5201
  }
5120
- return false;
5202
+ const curPre = now[3] === "" ? [] : now[3].split(".");
5203
+ const nextPre = next[3] === "" ? [] : next[3].split(".");
5204
+ if (curPre.length === 0 && nextPre.length === 0) return false;
5205
+ if (curPre.length === 0) return false;
5206
+ if (nextPre.length === 0) return true;
5207
+ for (let i = 0; i < Math.min(curPre.length, nextPre.length); i += 1) {
5208
+ const a = curPre[i];
5209
+ const b = nextPre[i];
5210
+ const numA = /^\d+$/.test(a);
5211
+ const numB = /^\d+$/.test(b);
5212
+ if (numA && numB) {
5213
+ const diff = Number(b) - Number(a);
5214
+ if (diff !== 0) return diff > 0;
5215
+ } else if (numA !== numB) {
5216
+ return !numB;
5217
+ } else if (a !== b) {
5218
+ return b > a;
5219
+ }
5220
+ }
5221
+ return nextPre.length > curPre.length;
5121
5222
  }
5122
5223
  function updateNote(latest, current2) {
5123
5224
  return t("update.note", { current: current2, latest });
@@ -5292,6 +5393,32 @@ async function isNpmGlobal() {
5292
5393
  const ls = await runNpm(["ls", "-g", "node-modules-hunter", "--depth=0"], 6e4);
5293
5394
  return ls.code === 0 && ls.stdout.includes("node-modules-hunter");
5294
5395
  }
5396
+ async function distTagsMap(allowSpawn) {
5397
+ const collect = (raw2) => {
5398
+ if (raw2 === null || typeof raw2 !== "object" || Array.isArray(raw2)) return null;
5399
+ const out = {};
5400
+ for (const [name, version] of Object.entries(raw2)) {
5401
+ if (typeof version === "string" && VERSION_SHAPE.test(version)) out[name] = version;
5402
+ }
5403
+ return Object.keys(out).length > 0 ? out : null;
5404
+ };
5405
+ const seam = process.env.NMH_UPDATE_DIST_TAGS_JSON;
5406
+ if (typeof seam === "string" && seam.length > 0) {
5407
+ try {
5408
+ return collect(JSON.parse(await fs13.readFile(seam, "utf8")));
5409
+ } catch {
5410
+ return null;
5411
+ }
5412
+ }
5413
+ if (!allowSpawn) return null;
5414
+ const view = await runNpm(["view", "node-modules-hunter", "dist-tags", "--json"], 6e4);
5415
+ if (view.code !== 0) return null;
5416
+ try {
5417
+ return collect(JSON.parse(view.stdout));
5418
+ } catch {
5419
+ return null;
5420
+ }
5421
+ }
5295
5422
  async function installLatest(version) {
5296
5423
  const installCommand = `npm install -g node-modules-hunter@${version}`;
5297
5424
  const fake = process.env.NMH_UPDATE_FAKE_INSTALL;
@@ -5312,7 +5439,7 @@ async function installLatest(version) {
5312
5439
  }
5313
5440
  return { ok: true, detail: installCommand };
5314
5441
  }
5315
- function renderInfo(current2, manifest, updateAvailable, global) {
5442
+ function renderInfo(current2, manifest, updateAvailable, global, distTags) {
5316
5443
  const d = manifest.detail;
5317
5444
  const rows = [
5318
5445
  t("update.info.installed", { value: current2 }),
@@ -5321,6 +5448,10 @@ function renderInfo(current2, manifest, updateAvailable, global) {
5321
5448
  value: updateAvailable ? t("update.info.available") + (global ? "" : t("update.info.availableNonGlobal")) : t("update.info.none")
5322
5449
  })
5323
5450
  ];
5451
+ if (distTags !== null) {
5452
+ const tags = Object.entries(distTags).map(([name, version]) => `${name}=${version}`).join(", ");
5453
+ rows.push(t("update.info.tags", { tags }));
5454
+ }
5324
5455
  if (d.description !== void 0) rows.push(t("update.info.summary", { value: d.description }));
5325
5456
  if (d.tarball !== void 0) {
5326
5457
  const size = d.unpackedSize === void 0 ? "" : t("update.info.sizeSuffix", { size: d.unpackedSize, files: d.fileCount === void 0 ? "" : `, ${d.fileCount}` });
@@ -5333,6 +5464,12 @@ function renderInfo(current2, manifest, updateAvailable, global) {
5333
5464
  }
5334
5465
  async function runUpdate(request) {
5335
5466
  const current2 = toolVersion();
5467
+ const tag = request.tag ?? "latest";
5468
+ if (!isValidDistTag(tag)) {
5469
+ const message = t("update.err.invalidTag", { value: tag });
5470
+ errorLog(request.json ? message : `\u26A0 ${message}`);
5471
+ return 1;
5472
+ }
5336
5473
  const manifest = await latestManifest();
5337
5474
  if (manifest === null) {
5338
5475
  const message = t("update.err.noRegistry");
@@ -5340,25 +5477,46 @@ async function runUpdate(request) {
5340
5477
  else errorLog(`\u26A0 ${message}`);
5341
5478
  return 1;
5342
5479
  }
5480
+ const hermetic = typeof process.env.NMH_UPDATE_LATEST_JSON === "string" && process.env.NMH_UPDATE_LATEST_JSON.length > 0;
5481
+ const distTags = await distTagsMap(!hermetic);
5482
+ let target;
5483
+ if (tag === "latest") {
5484
+ target = distTags?.latest ?? manifest.version;
5485
+ } else if (distTags !== null && typeof distTags[tag] === "string") {
5486
+ target = distTags[tag];
5487
+ } else if (distTags === null) {
5488
+ const message = t("update.err.noRegistry");
5489
+ if (request.json) errorLog(message);
5490
+ else errorLog(`\u26A0 ${message}`);
5491
+ return 1;
5492
+ } else {
5493
+ const tags = Object.keys(distTags).join(", ");
5494
+ const message = t("update.err.tagUnknown", { tag, tags });
5495
+ if (request.json) errorLog(message);
5496
+ else errorLog(`\u26A0 ${message}`);
5497
+ return 1;
5498
+ }
5343
5499
  const latest = manifest.version;
5344
5500
  const global = await isNpmGlobal();
5345
5501
  const method = global ? "npm-global" : "manual";
5346
- const updateAvailable = isNewer(current2, latest);
5347
- const result = (updated) => ({ current: current2, latest, updated, method, updateAvailable });
5502
+ const direction = isNewer(current2, target) ? "upgrade" : isNewer(target, current2) ? "downgrade" : "current";
5503
+ const updateAvailable = direction === "upgrade";
5504
+ const result = (updated) => ({ current: current2, latest, updated, method, updateAvailable, tag, target, direction });
5348
5505
  if (request.mode === "info") {
5349
- if (request.json) payload(JSON.stringify({ ...result(false), detail: manifest.detail }, null, 2));
5350
- else log([t("update.info.title"), ...renderInfo(current2, manifest, updateAvailable, global)].join("\n"));
5506
+ if (request.json) payload(JSON.stringify({ ...result(false), distTags: distTags ?? void 0, detail: manifest.detail }, null, 2));
5507
+ else log([t("update.info.title"), ...renderInfo(current2, manifest, updateAvailable, global, distTags)].join("\n"));
5351
5508
  return 0;
5352
5509
  }
5353
5510
  if (request.mode === "check") {
5511
+ const onTag = tag === "latest" ? "" : ` ${t("update.check.onTag", { tag })}`;
5354
5512
  if (request.json) payload(JSON.stringify(result(false), null, 2));
5355
- else if (updateAvailable) log(t("update.check.available", { current: current2, latest }));
5356
- else log(t("update.check.latest", { current: current2, latest }));
5513
+ else if (updateAvailable) log(t("update.check.available", { current: current2, latest: target }) + onTag);
5514
+ else log(t("update.check.latest", { current: current2, latest: target }) + onTag);
5357
5515
  return 0;
5358
5516
  }
5359
- if (!updateAvailable) {
5517
+ if (direction === "current") {
5360
5518
  if (request.json) payload(JSON.stringify(result(false), null, 2));
5361
- else log(t("update.latestNoInstall", { current: current2, latest }));
5519
+ else log(t("update.latestNoInstall", { current: current2, latest: target }));
5362
5520
  return 0;
5363
5521
  }
5364
5522
  if (!global) {
@@ -5377,24 +5535,24 @@ async function runUpdate(request) {
5377
5535
  return 1;
5378
5536
  }
5379
5537
  const admitted = await confirm({
5380
- message: t("update.confirm", { current: current2, latest }),
5381
- initialValue: true
5538
+ message: direction === "downgrade" ? t("update.confirm.downgrade", { current: current2, target, tag }) : t("update.confirm", { current: current2, latest: target }),
5539
+ initialValue: direction !== "downgrade"
5382
5540
  });
5383
5541
  install = admitted === true;
5384
5542
  }
5385
5543
  if (!install) {
5386
5544
  if (request.json) payload(JSON.stringify(result(false), null, 2));
5387
- else log(t("update.declined", { current: current2, latest }));
5545
+ else log(t("update.declined", { current: current2, latest: target }));
5388
5546
  return 0;
5389
5547
  }
5390
- const installation = await installLatest(latest);
5548
+ const installation = await installLatest(target);
5391
5549
  if (!installation.ok) {
5392
5550
  errorLog(t("update.err.failed", { detail: installation.detail }));
5393
- errorLog(t("update.err.manualHint", { latest }));
5551
+ errorLog(t("update.err.manualHint", { latest: target }));
5394
5552
  return 1;
5395
5553
  }
5396
5554
  if (request.json) payload(JSON.stringify(result(true), null, 2));
5397
- else log(t("update.done", { current: current2, latest }));
5555
+ else log(t("update.done", { current: current2, latest: target }));
5398
5556
  return 0;
5399
5557
  }
5400
5558
 
@@ -5403,7 +5561,7 @@ import fs14 from "fs/promises";
5403
5561
  import path14 from "path";
5404
5562
  import { homedir as homedir7 } from "os";
5405
5563
  var VALID_MODES2 = /* @__PURE__ */ new Set(["hard", "soft", "trash"]);
5406
- var KNOWN_KEYS = ["defaultMode", "depth", "exclude", "keep", "color", "animate", "updateCheck", "logDir", "language"];
5564
+ var KNOWN_KEYS = ["defaultMode", "depth", "exclude", "keep", "color", "animate", "updateCheck", "logDir", "language", "updateTag"];
5407
5565
  var KEY_TO_FLAG = {
5408
5566
  defaultMode: "default-mode",
5409
5567
  depth: "depth",
@@ -5413,7 +5571,8 @@ var KEY_TO_FLAG = {
5413
5571
  animate: "animate",
5414
5572
  updateCheck: "update-check",
5415
5573
  logDir: "log-dir",
5416
- language: "language"
5574
+ language: "language",
5575
+ updateTag: "update-tag"
5417
5576
  };
5418
5577
  var LIST_KEYS = {
5419
5578
  "default-exclude": "exclude",
@@ -5477,6 +5636,13 @@ function parseLanguage(raw2) {
5477
5636
  }
5478
5637
  return value.trim().toLowerCase();
5479
5638
  }
5639
+ function parseUpdateTag(raw2) {
5640
+ const value = scalar(raw2).value;
5641
+ if (typeof value !== "string" || !isValidDistTag(value.trim())) {
5642
+ throw new ConfigError(t("config.err.invalidUpdateTagValue", { value: JSON.stringify(value ?? null) }));
5643
+ }
5644
+ return value.trim();
5645
+ }
5480
5646
  function parseBool(raw2, label) {
5481
5647
  const given = flagBool(raw2);
5482
5648
  if (given.value === null) {
@@ -5516,6 +5682,7 @@ function assemble(request) {
5516
5682
  if (scalar(request.depth).given) mutation.scalars.depth = parseDepth(request.depth);
5517
5683
  if (scalar(request.defaultMode).given) mutation.scalars.defaultMode = parseMode(request.defaultMode);
5518
5684
  if (scalar(request.language).given) mutation.scalars.language = parseLanguage(request.language);
5685
+ if (scalar(request.updateTag).given) mutation.scalars.updateTag = parseUpdateTag(request.updateTag);
5519
5686
  if (scalar(request.logDir).given) {
5520
5687
  const value = scalar(request.logDir).value;
5521
5688
  if (typeof value !== "string" || value.length === 0) throw new ConfigError(t("config.err.logDirNeedsValue"));
@@ -5546,7 +5713,7 @@ function assemble(request) {
5546
5713
  }
5547
5714
  if (defaultExclude.given) mutation.unsetKeys.push("exclude");
5548
5715
  if (defaultKeep.given) mutation.unsetKeys.push("keep");
5549
- for (const key of ["defaultMode", "logDir", "depth", "animate", "color", "updateCheck", "language"]) {
5716
+ for (const key of ["defaultMode", "logDir", "depth", "animate", "color", "updateCheck", "language", "updateTag"]) {
5550
5717
  if (request[key] !== void 0) mutation.unsetKeys.push(key);
5551
5718
  }
5552
5719
  if (mutation.unsetKeys.length === 0) {
@@ -5617,7 +5784,8 @@ var INFO_DEFAULTS = {
5617
5784
  animate: "(auto: TTY only)",
5618
5785
  updateCheck: "off",
5619
5786
  logDir: "~/.nmh",
5620
- language: "en"
5787
+ language: "en",
5788
+ updateTag: "latest"
5621
5789
  };
5622
5790
  function renderInfo2(source, values) {
5623
5791
  const row = (key, value) => ` ${colors.dim(key.padEnd(12, " "))}${value}`;
@@ -7773,6 +7941,12 @@ async function runFallbackScan(cwd, options) {
7773
7941
  async function runInteractiveWizard(cwd, options) {
7774
7942
  const explicit = options.targets !== void 0 && options.targets.length > 0;
7775
7943
  if (options.banner !== false) log(renderFullBanner());
7944
+ if (options.settings === void 0 || options.settings.values.updateCheck === void 0) {
7945
+ void checkForUpdate().then((notice) => {
7946
+ if (notice !== null) note(notice);
7947
+ }).catch(() => {
7948
+ });
7949
+ }
7776
7950
  const scope = explicit ? { root: cwd, from: cwd, climbed: false, scouted: false } : await resolveWizardScope(cwd);
7777
7951
  if (scope.climbed) {
7778
7952
  log(colors.dim(t("wizard.info.scopedUp", { root: scope.root })));
@@ -7799,6 +7973,7 @@ async function runInteractiveWizard(cwd, options) {
7799
7973
  { value: "search", label: t("wizard.menu.search") },
7800
7974
  { value: "map", label: t("wizard.menu.map") },
7801
7975
  { value: "stats", label: t("wizard.menu.stats") },
7976
+ { value: "update", label: t("wizard.menu.update") },
7802
7977
  { value: "settings", label: t("wizard.menu.settings") },
7803
7978
  { value: "quit", label: t("wizard.menu.quit") }
7804
7979
  ]
@@ -7831,6 +8006,10 @@ async function runInteractiveWizard(cwd, options) {
7831
8006
  case "stats":
7832
8007
  await runStats({ targets: wizardTargets(options), cwd: scope.root, maxDepth: WIZARD_DEPTH });
7833
8008
  break;
8009
+ case "update": {
8010
+ await runUpdate({ json: false, mode: "default", answer: "none", force: false });
8011
+ break;
8012
+ }
7834
8013
  case "settings":
7835
8014
  log(renderSettings(options.settings, scope));
7836
8015
  break;
@@ -8174,13 +8353,15 @@ cli.option("--reinstall", "stats only: naive npm-ci-style estimate of the time t
8174
8353
  cli.option("--treemap [file]", "treemap export: single-file HTML (vanilla JS, no deps); default nmh-treemap.html in cwd");
8175
8354
  cli.option("--out <file>", "treemap only: where to write the HTML file (same as --treemap <file>)");
8176
8355
  cli.option("--update-check", "opt-in: peek npm for a newer release (non-blocking, 24 h cache; also settable in .nmhrc)");
8177
- cli.option("--check", "update only: compare installed vs registry and exit \u2014 never installs");
8356
+ cli.option("--check [tag]", "update only: compare installed vs registry dist-tag and exit \u2014 never installs (bare = latest/rc)");
8357
+ cli.option("--tag <name>", "update only: read this npm dist-tag instead of latest (also --check <tag>)");
8178
8358
  cli.option("--info", "update only: full registry detail (npm view style) \u2014 never installs");
8179
8359
  cli.option("-n, --no", "update only: decline the update on the command line (nothing installs)");
8180
8360
  cli.option("--wizard", "open the interactive wizard explicitly (same as the bare `nmh`); needs a TTY");
8181
8361
  cli.option("--default-exclude <globs>", 'config family: manage the persisted exclude list (comma list; special value "self")');
8182
8362
  cli.option("--default-keep <pkgs>", 'config family: manage the persisted keep list (comma list; special value "self")');
8183
8363
  cli.option("--default-mode <mode>", "config family: set the persisted defaultMode (hard | soft | trash)");
8364
+ cli.option("--update-tag <name>", "config family: set the persisted update dist-tag (updateTag)");
8184
8365
  cli.option("--log-dir <dir>", "config family: set the persisted recovery-log directory (logDir)");
8185
8366
  cli.option("--language <lang>", "UI language: en | id | zh | ru | es (also in .nmhrc / NMH_LANG; v1.3)");
8186
8367
  var PM_FAMILIES = /* @__PURE__ */ new Set(["npm", "pnpm", "yarn", "bun", "vp"]);
@@ -8510,20 +8691,39 @@ async function runCli(userArgs) {
8510
8691
  errorLog(t("cli.err.infoOnlyUpdate"));
8511
8692
  return 1;
8512
8693
  }
8694
+ if (flags.tag !== void 0 && subcommand !== "update") {
8695
+ errorLog(t("cli.err.tagOnlyUpdate"));
8696
+ return 1;
8697
+ }
8513
8698
  if (subcommand === "update") {
8514
8699
  if (deleted.given || rest.length > 0) {
8515
8700
  errorLog(t("cli.err.updateArgs"));
8516
8701
  return 1;
8517
8702
  }
8518
- if (flags.check === true && flags.info === true) {
8703
+ if (flags.check !== void 0 && flags.check !== false && flags.info === true) {
8519
8704
  errorLog(t("cli.err.checkInfoExclusive"));
8520
8705
  return 1;
8521
8706
  }
8707
+ if (flags.tag === true) {
8708
+ errorLog(t("cli.err.tagNeedsValue"));
8709
+ return 1;
8710
+ }
8711
+ const flagTag = typeof flags.tag === "string" ? flags.tag.trim() : void 0;
8712
+ const checkTag = typeof flags.check === "string" ? flags.check.trim() : void 0;
8713
+ for (const candidate of [flagTag, checkTag]) {
8714
+ if (candidate !== void 0 && !isValidDistTag(candidate)) {
8715
+ errorLog(t("cli.err.invalidTag", { value: candidate }));
8716
+ return 1;
8717
+ }
8718
+ }
8719
+ const checkGiven = flags.check !== void 0 && flags.check !== false;
8720
+ const tag = flagTag ?? checkTag ?? config.updateTag ?? "latest";
8522
8721
  return runUpdate({
8523
8722
  json,
8524
- mode: flags.check === true ? "check" : flags.info === true ? "info" : "default",
8723
+ mode: checkGiven ? "check" : flags.info === true ? "info" : "default",
8525
8724
  answer: flags.yes === true ? "yes" : flags.no === true ? "no" : "none",
8526
- force: flags.force === true
8725
+ force: flags.force === true,
8726
+ tag
8527
8727
  });
8528
8728
  }
8529
8729
  const wizardIntent = subcommand === "wizard" || flags.wizard === true;
@@ -8598,7 +8798,8 @@ async function runCli(userArgs) {
8598
8798
  animate: animateGiven ? flags.animate : void 0,
8599
8799
  color: colorGiven ? flags.color : void 0,
8600
8800
  updateCheck: flags.updateCheck,
8601
- language: flags.language
8801
+ language: flags.language,
8802
+ updateTag: flags.updateTag
8602
8803
  });
8603
8804
  }
8604
8805
  const searchPattern = typeof flags.search === "string" && flags.search.length > 0 ? flags.search : subcommand === "search" ? rest[0] ?? null : null;