@ncukondo/reference-manager 0.30.1 → 0.32.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 (46) hide show
  1. package/README.md +20 -0
  2. package/dist/chunks/{SearchableMultiSelect-SOvTpKAU.js → SearchableMultiSelect-jAKQd_B0.js} +2 -2
  3. package/dist/chunks/{SearchableMultiSelect-SOvTpKAU.js.map → SearchableMultiSelect-jAKQd_B0.js.map} +1 -1
  4. package/dist/chunks/{action-menu-DCZcb0HB.js → action-menu-DLEwSKrj.js} +3 -3
  5. package/dist/chunks/{action-menu-DCZcb0HB.js.map → action-menu-DLEwSKrj.js.map} +1 -1
  6. package/dist/chunks/{checker-CxSG7cdw.js → checker-kVM4S67y.js} +4 -4
  7. package/dist/chunks/{checker-CxSG7cdw.js.map → checker-kVM4S67y.js.map} +1 -1
  8. package/dist/chunks/{crossref-client-CN2pRi3R.js → crossref-client-DcJ42Qt6.js} +2 -2
  9. package/dist/chunks/{crossref-client-CN2pRi3R.js.map → crossref-client-DcJ42Qt6.js.map} +1 -1
  10. package/dist/chunks/{fix-interaction-C3OrF3yU.js → fix-interaction-DWUzp9Ri.js} +5 -5
  11. package/dist/chunks/{fix-interaction-C3OrF3yU.js.map → fix-interaction-DWUzp9Ri.js.map} +1 -1
  12. package/dist/chunks/{index-C_mW5LMY.js → index-B4-i4PrU.js} +3 -3
  13. package/dist/chunks/{index-C_mW5LMY.js.map → index-B4-i4PrU.js.map} +1 -1
  14. package/dist/chunks/{index-BZMfDG4M.js → index-B8iEozpf.js} +3 -3
  15. package/dist/chunks/index-B8iEozpf.js.map +1 -0
  16. package/dist/chunks/{index-CA9y5wSm.js → index-BuQm8A5F.js} +4 -4
  17. package/dist/chunks/{index-CA9y5wSm.js.map → index-BuQm8A5F.js.map} +1 -1
  18. package/dist/chunks/{index-4w0pu_0o.js → index-CmkN2-2A.js} +438 -85
  19. package/dist/chunks/index-CmkN2-2A.js.map +1 -0
  20. package/dist/chunks/{pubmed-client-MF5gA6Os.js → pubmed-client-Bhzz4Gg5.js} +2 -2
  21. package/dist/chunks/{pubmed-client-MF5gA6Os.js.map → pubmed-client-Bhzz4Gg5.js.map} +1 -1
  22. package/dist/chunks/{reference-select-Bm-05R0u.js → reference-select-B9b9Ez7Q.js} +3 -3
  23. package/dist/chunks/{reference-select-Bm-05R0u.js.map → reference-select-B9b9Ez7Q.js.map} +1 -1
  24. package/dist/chunks/{style-select-kfWjEg1X.js → style-select-aXByJLOo.js} +3 -3
  25. package/dist/chunks/{style-select-kfWjEg1X.js.map → style-select-aXByJLOo.js.map} +1 -1
  26. package/dist/cli/commands/install/install.d.ts +11 -0
  27. package/dist/cli/commands/install/install.d.ts.map +1 -0
  28. package/dist/cli/commands/show.d.ts +16 -0
  29. package/dist/cli/commands/show.d.ts.map +1 -0
  30. package/dist/cli/index.d.ts.map +1 -1
  31. package/dist/cli.js +2 -2
  32. package/dist/features/format/show-normalizer.d.ts +43 -0
  33. package/dist/features/format/show-normalizer.d.ts.map +1 -0
  34. package/dist/features/format/show-pretty.d.ts +8 -0
  35. package/dist/features/format/show-pretty.d.ts.map +1 -0
  36. package/dist/features/install/index.d.ts +6 -0
  37. package/dist/features/install/index.d.ts.map +1 -0
  38. package/dist/features/install/write-skills.d.ts +21 -0
  39. package/dist/features/install/write-skills.d.ts.map +1 -0
  40. package/dist/mcp/tools/index.d.ts.map +1 -1
  41. package/dist/mcp/tools/show.d.ts +23 -0
  42. package/dist/mcp/tools/show.d.ts.map +1 -0
  43. package/dist/server.js +1 -1
  44. package/package.json +1 -1
  45. package/dist/chunks/index-4w0pu_0o.js.map +0 -1
  46. package/dist/chunks/index-BZMfDG4M.js.map +0 -1
@@ -1,11 +1,12 @@
1
1
  import { Command, Option } from "commander";
2
- import { n as normalizePathForOutput, d as deleteDirectoryIfEmpty, p as parseFilename, i as isReservedRole, e as ensureDirectory, a as addAttachment, R as RESERVED_ROLES, b as generateFilename, c as findFulltextFiles, h as findFulltextFile, j as extensionToFormat, k as fulltextAttach, l as fulltextDiscover, m as fulltextFetch, o as fulltextConvert, q as fulltextGet, r as getExtension, s as getDefaultExportFromCjs, B as BUILTIN_STYLES, t as packageJson, u as getFulltextAttachmentTypes, v as startServerWithFileWatcher, w as BUILTIN_CONVERTER_NAMES, x as BUILTIN_CONVERTER_INFO } from "./index-C_mW5LMY.js";
2
+ import { n as normalizePathForOutput, d as deleteDirectoryIfEmpty, p as parseFilename, i as isReservedRole, e as ensureDirectory, a as addAttachment, R as RESERVED_ROLES, b as generateFilename, c as findFulltextFiles, h as findFulltextFile, j as extensionToFormat, k as fulltextAttach, l as fulltextDiscover, m as fulltextFetch, o as fulltextConvert, q as fulltextGet, r as getExtension, s as getDefaultExportFromCjs, B as BUILTIN_STYLES, t as packageJson, u as getFulltextAttachmentTypes, v as startServerWithFileWatcher, w as BUILTIN_CONVERTER_NAMES, x as BUILTIN_CONVERTER_INFO } from "./index-B4-i4PrU.js";
3
3
  import { i as isEqual, M as MANAGED_CUSTOM_FIELDS, w as writeFileAtomic, L as Library, h as CslItemSchema, p as pickDefined, a as sortOrderSchema, z as paginationOptionsSchema, F as FileWatcher, b as sortFieldSchema, y as searchSortFieldSchema } from "./file-watcher-CWHg1yol.js";
4
4
  import * as fs from "node:fs";
5
- import { promises, readFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
5
+ import { promises, readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, unlinkSync, rmSync, symlinkSync } from "node:fs";
6
6
  import * as os from "node:os";
7
+ import { homedir } from "node:os";
7
8
  import * as path from "node:path";
8
- import path__default, { join, basename, dirname } from "node:path";
9
+ import path__default, { join, basename, dirname, relative } from "node:path";
9
10
  import { readFile, unlink, stat, readdir, rename } from "node:fs/promises";
10
11
  import { o as openWithSystemApp, l as loadConfig, e as getDefaultCurrentDirConfigFilename, h as getDefaultUserConfigPath } from "./loader-BG2eomDC.js";
11
12
  import { spawn, spawnSync } from "node:child_process";
@@ -613,11 +614,11 @@ function inferFromFilename(filename) {
613
614
  if (!parsed) {
614
615
  return { filename, role: "other", label: filename };
615
616
  }
616
- const { role, label } = parsed;
617
+ const { role, label: label2 } = parsed;
617
618
  if (isReservedRole(role)) {
618
- return label ? { filename, role, label } : { filename, role };
619
+ return label2 ? { filename, role, label: label2 } : { filename, role };
619
620
  }
620
- const basename2 = label ? `${role}-${label}` : role;
621
+ const basename2 = label2 ? `${role}-${label2}` : role;
621
622
  return { filename, role: "other", label: basename2 };
622
623
  }
623
624
  async function getFilesOnDisk(dirPath) {
@@ -656,11 +657,11 @@ function buildUpdatedFiles(metadataFiles, newFiles, missingFiles, shouldApplyNew
656
657
  for (const newFile of newFiles) {
657
658
  const override = roleOverrides?.[newFile.filename];
658
659
  const role = override?.role ?? newFile.role;
659
- const label = override ? override.label : newFile.label;
660
+ const label2 = override ? override.label : newFile.label;
660
661
  const attachmentFile = {
661
662
  filename: newFile.filename,
662
663
  role,
663
- ...label && { label }
664
+ ...label2 && { label: label2 }
664
665
  };
665
666
  updatedFiles.push(attachmentFile);
666
667
  }
@@ -893,15 +894,15 @@ class OperationsLibrary {
893
894
  }
894
895
  // High-level operations
895
896
  async search(options) {
896
- const { searchReferences } = await import("./index-C_mW5LMY.js").then((n) => n.H);
897
+ const { searchReferences } = await import("./index-B4-i4PrU.js").then((n) => n.H);
897
898
  return searchReferences(this.library, options);
898
899
  }
899
900
  async list(options) {
900
- const { listReferences } = await import("./index-C_mW5LMY.js").then((n) => n.G);
901
+ const { listReferences } = await import("./index-B4-i4PrU.js").then((n) => n.G);
901
902
  return listReferences(this.library, options ?? {});
902
903
  }
903
904
  async cite(options) {
904
- const { citeReferences } = await import("./index-C_mW5LMY.js").then((n) => n.F);
905
+ const { citeReferences } = await import("./index-B4-i4PrU.js").then((n) => n.F);
905
906
  const defaultStyle = options.defaultStyle ?? this.citationConfig?.defaultStyle;
906
907
  const cslDirectory = options.cslDirectory ?? this.citationConfig?.cslDirectory;
907
908
  const mergedOptions = {
@@ -912,36 +913,36 @@ class OperationsLibrary {
912
913
  return citeReferences(this.library, mergedOptions);
913
914
  }
914
915
  async import(inputs, options) {
915
- const { addReferences } = await import("./index-C_mW5LMY.js").then((n) => n.D);
916
+ const { addReferences } = await import("./index-B4-i4PrU.js").then((n) => n.D);
916
917
  return addReferences(inputs, this.library, options ?? {});
917
918
  }
918
919
  async check(options) {
919
- const { checkReferences } = await import("./index-C_mW5LMY.js").then((n) => n.E);
920
+ const { checkReferences } = await import("./index-B4-i4PrU.js").then((n) => n.E);
920
921
  return checkReferences(this.library, options);
921
922
  }
922
923
  // Attachment operations
923
924
  async attachAdd(options) {
924
- const { addAttachment: addAttachment2 } = await import("./index-BZMfDG4M.js");
925
+ const { addAttachment: addAttachment2 } = await import("./index-B8iEozpf.js");
925
926
  return addAttachment2(this.library, options);
926
927
  }
927
928
  async attachList(options) {
928
- const { listAttachments: listAttachments2 } = await import("./index-BZMfDG4M.js");
929
+ const { listAttachments: listAttachments2 } = await import("./index-B8iEozpf.js");
929
930
  return listAttachments2(this.library, options);
930
931
  }
931
932
  async attachGet(options) {
932
- const { getAttachment: getAttachment2 } = await import("./index-BZMfDG4M.js");
933
+ const { getAttachment: getAttachment2 } = await import("./index-B8iEozpf.js");
933
934
  return getAttachment2(this.library, options);
934
935
  }
935
936
  async attachDetach(options) {
936
- const { detachAttachment: detachAttachment2 } = await import("./index-BZMfDG4M.js");
937
+ const { detachAttachment: detachAttachment2 } = await import("./index-B8iEozpf.js");
937
938
  return detachAttachment2(this.library, options);
938
939
  }
939
940
  async attachSync(options) {
940
- const { syncAttachments: syncAttachments2 } = await import("./index-BZMfDG4M.js");
941
+ const { syncAttachments: syncAttachments2 } = await import("./index-B8iEozpf.js");
941
942
  return syncAttachments2(this.library, options);
942
943
  }
943
944
  async attachOpen(options) {
944
- const { openAttachment: openAttachment2 } = await import("./index-BZMfDG4M.js");
945
+ const { openAttachment: openAttachment2 } = await import("./index-B8iEozpf.js");
945
946
  return openAttachment2(this.library, options);
946
947
  }
947
948
  }
@@ -1804,9 +1805,9 @@ function formatSyncPreview(result) {
1804
1805
  function getAttachExitCode(result) {
1805
1806
  return result.success ? 0 : 1;
1806
1807
  }
1807
- async function executeInteractiveSelect$2(context, config2) {
1808
+ async function executeInteractiveSelect$3(context, config2) {
1808
1809
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
1809
- const { selectReferencesOrExit } = await import("./reference-select-Bm-05R0u.js");
1810
+ const { selectReferencesOrExit } = await import("./reference-select-B9b9Ez7Q.js");
1810
1811
  const allReferences = await context.library.getAll();
1811
1812
  const identifiers = await withAlternateScreen2(
1812
1813
  () => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -1818,7 +1819,7 @@ async function resolveIdentifier(identifierArg, context, config2) {
1818
1819
  return identifierArg;
1819
1820
  }
1820
1821
  if (isTTY()) {
1821
- return executeInteractiveSelect$2(context, config2);
1822
+ return executeInteractiveSelect$3(context, config2);
1822
1823
  }
1823
1824
  const stdinId = await readIdentifierFromStdin();
1824
1825
  if (!stdinId) {
@@ -2413,8 +2414,8 @@ function countFindingTypes(result) {
2413
2414
  function formatCheckTextOutput(result) {
2414
2415
  const lines = [];
2415
2416
  for (const r of result.results) {
2416
- const label = getStatusLabel(r);
2417
- lines.push(`${label} ${r.id}`);
2417
+ const label2 = getStatusLabel(r);
2418
+ lines.push(`${label2} ${r.id}`);
2418
2419
  for (const finding of r.findings) {
2419
2420
  lines.push(...formatFindingDetails(finding, r.id));
2420
2421
  }
@@ -2431,9 +2432,9 @@ function formatCheckTextOutput(result) {
2431
2432
  ["versionChanged", "version changed"]
2432
2433
  ];
2433
2434
  const knownKeys = new Set(summaryItems.map(([key]) => key));
2434
- for (const [key, label] of summaryItems) {
2435
+ for (const [key, label2] of summaryItems) {
2435
2436
  const count = fc[key] ?? 0;
2436
- if (count > 0) parts.push(`${count} ${label}`);
2437
+ if (count > 0) parts.push(`${count} ${label2}`);
2437
2438
  }
2438
2439
  for (const [key, count] of Object.entries(fc)) {
2439
2440
  if (!knownKeys.has(key) && count > 0) parts.push(`${count} ${key}`);
@@ -2471,7 +2472,7 @@ async function handleCheckAction(identifiers, options, globalOpts) {
2471
2472
  const jsonOptions = buildJsonOptionsFromRefs(options, outputFormat, result, allRefs);
2472
2473
  outputCheckResult(result, outputFormat, jsonOptions);
2473
2474
  if (options.fix && result.summary.warnings > 0 && allRefs) {
2474
- const { runFixInteraction } = await import("./fix-interaction-C3OrF3yU.js");
2475
+ const { runFixInteraction } = await import("./fix-interaction-DWUzp9Ri.js");
2475
2476
  const findItem = (id2) => allRefs.find((item) => item.id === id2);
2476
2477
  const fixResult = await runFixInteraction(result.results, context.library, findItem);
2477
2478
  const removedSuffix = fixResult.removed.length > 0 ? `, ${fixResult.removed.length} removed` : "";
@@ -2539,7 +2540,7 @@ function outputCheckError(error, format2) {
2539
2540
  }
2540
2541
  async function selectReferencesInteractively(context, config2) {
2541
2542
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
2542
- const { selectReferenceItemsOrExit } = await import("./reference-select-Bm-05R0u.js");
2543
+ const { selectReferenceItemsOrExit } = await import("./reference-select-B9b9Ez7Q.js");
2543
2544
  const allReferences = await context.library.getAll();
2544
2545
  if (allReferences.length === 0) {
2545
2546
  process.stderr.write("No references in library.\n");
@@ -2607,8 +2608,8 @@ function getCiteExitCode(result) {
2607
2608
  }
2608
2609
  async function executeInteractiveCite(options, context, config2) {
2609
2610
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
2610
- const { runCiteFlow } = await import("./index-CA9y5wSm.js");
2611
- const { buildStyleChoices, listCustomStyles } = await import("./style-select-kfWjEg1X.js");
2611
+ const { runCiteFlow } = await import("./index-BuQm8A5F.js");
2612
+ const { buildStyleChoices, listCustomStyles } = await import("./style-select-aXByJLOo.js");
2612
2613
  const { search } = await import("./file-watcher-CWHg1yol.js").then((n) => n.B);
2613
2614
  const { tokenize } = await import("./file-watcher-CWHg1yol.js").then((n) => n.A);
2614
2615
  const { checkTTY } = await import("./tty-BMyaEOhX.js");
@@ -7291,7 +7292,7 @@ function formatEditOutput(result) {
7291
7292
  }
7292
7293
  async function executeInteractiveEdit(options, context, config2) {
7293
7294
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
7294
- const { selectReferencesOrExit } = await import("./reference-select-Bm-05R0u.js");
7295
+ const { selectReferencesOrExit } = await import("./reference-select-B9b9Ez7Q.js");
7295
7296
  const allReferences = await context.library.getAll();
7296
7297
  const identifiers = await withAlternateScreen2(
7297
7298
  () => selectReferencesOrExit(allReferences, { multiSelect: true }, config2.cli.tui)
@@ -10865,9 +10866,9 @@ function formatFulltextConvertOutput(result) {
10865
10866
  function getFulltextExitCode(result) {
10866
10867
  return result.success ? 0 : 1;
10867
10868
  }
10868
- async function executeInteractiveSelect$1(context, config2, multiSelect = false) {
10869
+ async function executeInteractiveSelect$2(context, config2, multiSelect = false) {
10869
10870
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
10870
- const { selectReferencesOrExit } = await import("./reference-select-Bm-05R0u.js");
10871
+ const { selectReferencesOrExit } = await import("./reference-select-B9b9Ez7Q.js");
10871
10872
  const allReferences = await context.library.getAll();
10872
10873
  const identifiers = await withAlternateScreen2(
10873
10874
  () => selectReferencesOrExit(allReferences, { multiSelect }, config2.cli.tui)
@@ -10904,7 +10905,7 @@ async function handleFulltextAttachAction(identifierArg, filePathArg, options, g
10904
10905
  setExitCode(ExitCode.ERROR);
10905
10906
  return;
10906
10907
  }
10907
- identifier = (await executeInteractiveSelect$1(context, config2))[0];
10908
+ identifier = (await executeInteractiveSelect$2(context, config2))[0];
10908
10909
  }
10909
10910
  const { type: type2, filePath } = parseFulltextAttachTypeAndPath(filePathArg, options);
10910
10911
  const stdinContent = !filePath && type2 ? await readStdinBuffer() : void 0;
@@ -10990,7 +10991,7 @@ async function resolveGetIdentifiers(identifierArgs, context, config2) {
10990
10991
  return identifierArgs;
10991
10992
  }
10992
10993
  if (isTTY()) {
10993
- return executeInteractiveSelect$1(context, config2, true);
10994
+ return executeInteractiveSelect$2(context, config2, true);
10994
10995
  }
10995
10996
  const stdinIds = await readIdentifiersFromStdin();
10996
10997
  if (stdinIds.length === 0) {
@@ -11071,7 +11072,7 @@ async function handleFulltextDetachAction(identifierArg, options, globalOpts) {
11071
11072
  if (identifierArg) {
11072
11073
  identifier = identifierArg;
11073
11074
  } else if (isTTY()) {
11074
- identifier = (await executeInteractiveSelect$1(context, config2))[0];
11075
+ identifier = (await executeInteractiveSelect$2(context, config2))[0];
11075
11076
  } else {
11076
11077
  const stdinId = await readIdentifierFromStdin();
11077
11078
  if (!stdinId) {
@@ -11111,7 +11112,7 @@ async function handleFulltextOpenAction(identifierArg, options, globalOpts) {
11111
11112
  if (identifierArg) {
11112
11113
  identifier = identifierArg;
11113
11114
  } else if (isTTY()) {
11114
- identifier = (await executeInteractiveSelect$1(context, config2))[0];
11115
+ identifier = (await executeInteractiveSelect$2(context, config2))[0];
11115
11116
  } else {
11116
11117
  const stdinId = await readIdentifierFromStdin();
11117
11118
  if (!stdinId) {
@@ -11151,7 +11152,7 @@ async function handleFulltextDiscoverAction(identifierArg, options, globalOpts)
11151
11152
  if (identifierArg) {
11152
11153
  identifier = identifierArg;
11153
11154
  } else if (isTTY()) {
11154
- identifier = (await executeInteractiveSelect$1(context, config2))[0];
11155
+ identifier = (await executeInteractiveSelect$2(context, config2))[0];
11155
11156
  } else {
11156
11157
  const stdinId = await readIdentifierFromStdin();
11157
11158
  if (!stdinId) {
@@ -11191,7 +11192,7 @@ async function handleFulltextFetchAction(identifierArg, options, globalOpts) {
11191
11192
  if (identifierArg) {
11192
11193
  identifier = identifierArg;
11193
11194
  } else if (isTTY()) {
11194
- identifier = (await executeInteractiveSelect$1(context, config2))[0];
11195
+ identifier = (await executeInteractiveSelect$2(context, config2))[0];
11195
11196
  } else {
11196
11197
  const stdinId = await readIdentifierFromStdin();
11197
11198
  if (!stdinId) {
@@ -11231,7 +11232,7 @@ async function handleFulltextConvertAction(identifierArg, options, globalOpts) {
11231
11232
  if (identifierArg) {
11232
11233
  identifier = identifierArg;
11233
11234
  } else if (isTTY()) {
11234
- identifier = (await executeInteractiveSelect$1(context, config2))[0];
11235
+ identifier = (await executeInteractiveSelect$2(context, config2))[0];
11235
11236
  } else {
11236
11237
  const stdinId = await readIdentifierFromStdin();
11237
11238
  if (!stdinId) {
@@ -11290,6 +11291,79 @@ const fulltext = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
11290
11291
  handleFulltextGetAction,
11291
11292
  handleFulltextOpenAction
11292
11293
  }, Symbol.toStringTag, { value: "Module" }));
11294
+ const skillMd = '---\nname: ref\ndescription: Manage academic references in CSL-JSON format. Add papers by DOI/PMID/ISBN/arXiv, search and list references, generate citations, manage full-text PDFs, and check for retractions.\nallowed-tools:\n - Bash\n - Read\n - Write\n - Edit\n - Glob\n - Grep\n---\n\n# ref — Reference Manager\n\nA CLI tool for managing academic references using CSL-JSON as the single source of truth.\n\n## Quick Reference\n\n| Task | Command |\n|------|---------|\n| Add by DOI | `ref add 10.1234/example` |\n| Add by PMID | `ref add 12345678` |\n| Add by ISBN | `ref add 978-0-123456-78-9` |\n| Add by arXiv | `ref add 2301.12345` |\n| Add from BibTeX | `ref add references.bib` |\n| Add from RIS | `ref add references.ris` |\n| Search | `ref search "query"` |\n| List all | `ref list` |\n| Show details | `ref show <id>` |\n| Generate citation | `ref cite <id>` |\n| Export | `ref export <id> --output bibtex` |\n| Attach full-text | `ref fulltext attach <id> paper.pdf` |\n| Fetch full-text | `ref fulltext fetch <id>` |\n| Check retractions | `ref check <id>` |\n| Remove | `ref remove <id>` |\n| Update fields | `ref update <id> --set "title=New Title"` |\n| Configure | `ref config set <key> <value>` |\n\n## Search Syntax\n\n- Simple text: `ref search "machine learning"`\n- By author: `ref search "author:Smith"`\n- By year: `ref search "year:2024"`\n- By type: `ref search "type:article-journal"`\n- By tag: `ref search "tag:review"`\n- Combined: `ref search "author:Smith year:2024"`\n- Case-sensitive: prefix with `C/` (e.g., `ref search "C/RNA"`)\n\n## Output Formats\n\nMost commands support `--output` or `--json` flags:\n\n- `--json` — JSON output for programmatic use\n- `--output bibtex` — BibTeX format\n- `--output yaml` — YAML format\n\n## Full Help\n\nRun `ref --help` for all commands and options.\nRun `ref <command> --help` for command-specific help.\n';
11295
+ const fulltextMd = '---\nname: ref/fulltext\ndescription: Guide for managing full-text PDFs and Markdown files. Covers fetching, attaching, converting, and organizing full-text content.\n---\n\n# Full-Text Management\n\nGuide for working with full-text files (PDFs and Markdown) using `ref`.\n\n## Attach Files\n\n```bash\n# Attach a PDF\nref fulltext attach <id> paper.pdf\n\n# Attach Markdown\nref fulltext attach <id> paper.md\n```\n\n## Fetch Open Access\n\n```bash\n# Auto-discover and download OA full text\nref fulltext fetch <id>\n\n# Fetch with auto-attach on add\nref add 10.1234/example --fetch-fulltext\n```\n\n## Convert Formats\n\n```bash\n# Convert PDF to Markdown (requires external converter)\nref fulltext convert <id>\n\n# Supported converters: marker, docling, mineru, pymupdf\n# Configure custom converter:\nref config set fulltext.pdfConverter.command "marker"\nref config set fulltext.pdfConverter.args "{input} --output {output_dir}"\n```\n\n## Retrieve Full Text\n\n```bash\n# Get file path\nref fulltext get <id>\n\n# Get Markdown content to stdout\nref fulltext get <id> --stdout\n\n# Prefer specific format\nref fulltext get <id> --markdown\nref fulltext get <id> --pdf\n\n# Open in default system viewer\nref fulltext open <id>\n```\n\n## Check Availability\n\n```bash\n# Discover OA sources without downloading\nref fulltext discover <id>\n```\n\n## Detach\n\n```bash\n# Remove full-text association (file remains on disk)\nref fulltext detach <id>\n```\n\n## Tips\n\n- Use `ref fulltext get <id> --stdout` to pipe content to other tools\n- Full-text files are stored in the attachments directory (see `ref config get attachments.directory`)\n- Use `ref show <id>` to see full-text status alongside metadata\n- Markdown is preferred for AI-readable content; use `ref fulltext convert` after attaching PDF\n';
11296
+ const manuscriptWritingMd = "---\nname: ref/manuscript-writing\ndescription: Workflow for managing references while writing academic manuscripts. Covers citation generation, bibliography export, and reference verification.\n---\n\n# Manuscript Writing Workflow\n\nGuide for managing references during academic manuscript writing with `ref`.\n\n## 1. Find and Cite\n\n```bash\n# Search your library\nref search \"Smith 2024\"\n\n# Generate an inline citation\nref cite <id>\n\n# Generate citation in specific style\nref cite <id> --style apa\nref cite <id> --style vancouver\n\n# Get Pandoc/LaTeX citation key\nref cite <id> --key\n```\n\n## 2. Build Bibliography\n\n```bash\n# Export all cited references as BibTeX\nref export <id1> <id2> <id3> --output bibtex > references.bib\n\n# Export by search query\nref search \"tag:cited\" --output bibtex > references.bib\n\n# Export all references\nref export --all --output bibtex > library.bib\n```\n\n## 3. Add New References During Writing\n\n```bash\n# Quick add by DOI from a paper you're reading\nref add 10.1234/example\n\n# Add from clipboard BibTeX (pipe from stdin)\necho '<bibtex>' | ref add -\n\n# Add and immediately get citation key\nref add 10.1234/example --json | jq -r '.added[0].id'\n```\n\n## 4. Verify Before Submission\n\n```bash\n# Check all cited references for retractions\nref check <id1> <id2> <id3>\n\n# Verify metadata accuracy\nref check <id> --metadata\n\n# Show full details for final review\nref show <id>\n```\n\n## 5. Full-Text Management\n\n```bash\n# Attach supplementary files\nref fulltext attach <id> paper.pdf\nref fulltext attach <id> supplement.pdf\n\n# Get full-text path for reading\nref fulltext get <id>\n\n# Open in default viewer\nref fulltext open <id>\n```\n\n## Tips\n\n- Use `ref cite <id> --key` to get `@AuthorYear` keys for Pandoc\n- Use `ref show <id> --output yaml` for quick metadata overview\n- Use `ref url <id>` to get DOI/PubMed URLs for linking\n- Tag references with `ref update <id> --set \"tags=cited\"` to track what's in the manuscript\n";
11297
+ const systematicReviewMd = '---\nname: ref/systematic-review\ndescription: Workflow for conducting systematic literature reviews using reference-manager. Covers search strategy, screening, and evidence synthesis.\n---\n\n# Systematic Review Workflow\n\nGuide for conducting systematic literature reviews with `ref`.\n\n## 1. Build Search Set\n\nAdd references from multiple sources:\n\n```bash\n# From DOIs (e.g., exported from database search)\nref add 10.1234/study1 10.1234/study2 10.1234/study3\n\n# From BibTeX exported by PubMed/Scopus/Web of Science\nref add pubmed-results.bib\nref add scopus-results.ris\n\n# By PMID list\nref add 12345678 23456789 34567890\n```\n\n## 2. Tag and Organize\n\nUse tags to track screening stages:\n\n```bash\n# Tag references for screening\nref update <id> --set "tags=screening"\n\n# After title/abstract screening\nref update <id> --set "tags=included"\nref update <id> --set "tags=excluded"\n\n# After full-text review\nref update <id> --set "tags=final-included"\n```\n\n## 3. Full-Text Collection\n\n```bash\n# Auto-fetch open access full texts\nref fulltext fetch <id>\n\n# Attach manually obtained PDFs\nref fulltext attach <id> path/to/paper.pdf\n\n# Convert PDF to Markdown for text analysis\nref fulltext convert <id>\n```\n\n## 4. Quality Check\n\n```bash\n# Check for retractions or corrections\nref check <id>\n\n# Verify metadata against upstream sources\nref check <id> --metadata\n```\n\n## 5. Export for Analysis\n\n```bash\n# Export included studies as BibTeX\nref search "tag:final-included" --output bibtex > included.bib\n\n# Export as JSON for custom analysis\nref search "tag:final-included" --json > included.json\n```\n\n## Tips\n\n- Use `ref list --sort date-desc` to review chronologically\n- Use `ref search "tag:screening"` to find unprocessed references\n- Use `ref show <id>` to inspect full metadata before decisions\n- Duplicates are auto-detected on `ref add` — review skip messages\n';
11298
+ const SKILL_FILES = [
11299
+ ["SKILL.md", skillMd],
11300
+ ["references/systematic-review.md", systematicReviewMd],
11301
+ ["references/manuscript-writing.md", manuscriptWritingMd],
11302
+ ["references/fulltext.md", fulltextMd]
11303
+ ];
11304
+ async function writeSkills(options) {
11305
+ const { targetDir, force = false, user = false } = options;
11306
+ const baseDir = user ? homedir() : targetDir;
11307
+ const agentsDir = join(baseDir, ".agents", "skills", "ref");
11308
+ const claudeDir = join(baseDir, ".claude", "skills");
11309
+ const claudeLink = join(claudeDir, "ref");
11310
+ const written = [];
11311
+ const skipped = [];
11312
+ mkdirSync(join(agentsDir, "references"), { recursive: true });
11313
+ for (const [relativePath, content] of SKILL_FILES) {
11314
+ const filePath = join(agentsDir, relativePath);
11315
+ if (existsSync(filePath) && !force) {
11316
+ skipped.push(relativePath);
11317
+ continue;
11318
+ }
11319
+ writeFileSync(filePath, content, "utf-8");
11320
+ written.push(relativePath);
11321
+ }
11322
+ let linkCreated = false;
11323
+ mkdirSync(claudeDir, { recursive: true });
11324
+ if (force && existsSync(claudeLink)) {
11325
+ const stat2 = lstatSync(claudeLink);
11326
+ if (stat2.isSymbolicLink()) {
11327
+ unlinkSync(claudeLink);
11328
+ } else if (stat2.isDirectory()) {
11329
+ rmSync(claudeLink, { recursive: true, force: true });
11330
+ }
11331
+ }
11332
+ if (!existsSync(claudeLink)) {
11333
+ const linkTarget = relative(claudeDir, agentsDir);
11334
+ symlinkSync(linkTarget, claudeLink, "junction");
11335
+ linkCreated = true;
11336
+ }
11337
+ return { written, skipped, linkCreated };
11338
+ }
11339
+ async function executeInstallSkills(options) {
11340
+ return writeSkills({
11341
+ targetDir: process.cwd(),
11342
+ force: options.force,
11343
+ ...options.user != null && { user: options.user }
11344
+ });
11345
+ }
11346
+ function formatInstallSkillsOutput(result) {
11347
+ const lines = [];
11348
+ if (result.written.length === 0 && result.skipped.length > 0) {
11349
+ lines.push("Skills already up-to-date. Use --force to overwrite.");
11350
+ lines.push(` ${result.skipped.length} files skipped`);
11351
+ return lines.join("\n");
11352
+ }
11353
+ if (result.written.length > 0) {
11354
+ lines.push(`Installed ${result.written.length} skill files to .agents/skills/ref/`);
11355
+ for (const file of result.written) {
11356
+ lines.push(` + ${file}`);
11357
+ }
11358
+ }
11359
+ if (result.skipped.length > 0) {
11360
+ lines.push(` ${result.skipped.length} files skipped (already exist)`);
11361
+ }
11362
+ if (result.linkCreated) {
11363
+ lines.push("Created symlink: .claude/skills/ref -> .agents/skills/ref");
11364
+ }
11365
+ return lines.join("\n");
11366
+ }
11293
11367
  function buildResourceIndicators(item) {
11294
11368
  const labels = [];
11295
11369
  const attachments = item.custom?.attachments;
@@ -11310,14 +11384,14 @@ function buildResourceIndicators(item) {
11310
11384
  if (Array.isArray(tags) && tags.length > 0) labels.push("tag");
11311
11385
  return labels.join(" ");
11312
11386
  }
11313
- function formatAuthor(author) {
11387
+ function formatAuthor$1(author) {
11314
11388
  if (author.literal) return author.literal;
11315
11389
  const family = author.family || "";
11316
11390
  const givenInitial = author.given ? `${author.given.charAt(0)}.` : "";
11317
11391
  return givenInitial ? `${family}, ${givenInitial}` : family;
11318
11392
  }
11319
11393
  function formatAuthors(authors) {
11320
- return authors.map(formatAuthor).join("; ");
11394
+ return authors.map(formatAuthor$1).join("; ");
11321
11395
  }
11322
11396
  function formatSingleReference(item) {
11323
11397
  const lines = [];
@@ -23701,9 +23775,9 @@ function requireCodegen() {
23701
23775
  }
23702
23776
  }
23703
23777
  class Label extends Node {
23704
- constructor(label) {
23778
+ constructor(label2) {
23705
23779
  super();
23706
- this.label = label;
23780
+ this.label = label2;
23707
23781
  this.names = {};
23708
23782
  }
23709
23783
  render({ _n }) {
@@ -23711,14 +23785,14 @@ function requireCodegen() {
23711
23785
  }
23712
23786
  }
23713
23787
  class Break extends Node {
23714
- constructor(label) {
23788
+ constructor(label2) {
23715
23789
  super();
23716
- this.label = label;
23790
+ this.label = label2;
23717
23791
  this.names = {};
23718
23792
  }
23719
23793
  render({ _n }) {
23720
- const label = this.label ? ` ${this.label}` : "";
23721
- return `break${label};` + _n;
23794
+ const label2 = this.label ? ` ${this.label}` : "";
23795
+ return `break${label2};` + _n;
23722
23796
  }
23723
23797
  }
23724
23798
  class Throw extends Node {
@@ -24130,12 +24204,12 @@ function requireCodegen() {
24130
24204
  return this._endBlockNode(For);
24131
24205
  }
24132
24206
  // `label` statement
24133
- label(label) {
24134
- return this._leafNode(new Label(label));
24207
+ label(label2) {
24208
+ return this._leafNode(new Label(label2));
24135
24209
  }
24136
24210
  // `break` statement
24137
- break(label) {
24138
- return this._leafNode(new Break(label));
24211
+ break(label2) {
24212
+ return this._leafNode(new Break(label2));
24139
24213
  }
24140
24214
  // `return` statement
24141
24215
  return(value) {
@@ -26836,49 +26910,49 @@ function requireFastUri() {
26836
26910
  schemelessOptions.skipEscape = true;
26837
26911
  return serialize2(resolved, schemelessOptions);
26838
26912
  }
26839
- function resolveComponent(base, relative, options, skipNormalization) {
26913
+ function resolveComponent(base, relative2, options, skipNormalization) {
26840
26914
  const target = {};
26841
26915
  if (!skipNormalization) {
26842
26916
  base = parse2(serialize2(base, options), options);
26843
- relative = parse2(serialize2(relative, options), options);
26917
+ relative2 = parse2(serialize2(relative2, options), options);
26844
26918
  }
26845
26919
  options = options || {};
26846
- if (!options.tolerant && relative.scheme) {
26847
- target.scheme = relative.scheme;
26848
- target.userinfo = relative.userinfo;
26849
- target.host = relative.host;
26850
- target.port = relative.port;
26851
- target.path = removeDotSegments(relative.path || "");
26852
- target.query = relative.query;
26920
+ if (!options.tolerant && relative2.scheme) {
26921
+ target.scheme = relative2.scheme;
26922
+ target.userinfo = relative2.userinfo;
26923
+ target.host = relative2.host;
26924
+ target.port = relative2.port;
26925
+ target.path = removeDotSegments(relative2.path || "");
26926
+ target.query = relative2.query;
26853
26927
  } else {
26854
- if (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
26855
- target.userinfo = relative.userinfo;
26856
- target.host = relative.host;
26857
- target.port = relative.port;
26858
- target.path = removeDotSegments(relative.path || "");
26859
- target.query = relative.query;
26928
+ if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
26929
+ target.userinfo = relative2.userinfo;
26930
+ target.host = relative2.host;
26931
+ target.port = relative2.port;
26932
+ target.path = removeDotSegments(relative2.path || "");
26933
+ target.query = relative2.query;
26860
26934
  } else {
26861
- if (!relative.path) {
26935
+ if (!relative2.path) {
26862
26936
  target.path = base.path;
26863
- if (relative.query !== void 0) {
26864
- target.query = relative.query;
26937
+ if (relative2.query !== void 0) {
26938
+ target.query = relative2.query;
26865
26939
  } else {
26866
26940
  target.query = base.query;
26867
26941
  }
26868
26942
  } else {
26869
- if (relative.path[0] === "/") {
26870
- target.path = removeDotSegments(relative.path);
26943
+ if (relative2.path[0] === "/") {
26944
+ target.path = removeDotSegments(relative2.path);
26871
26945
  } else {
26872
26946
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
26873
- target.path = "/" + relative.path;
26947
+ target.path = "/" + relative2.path;
26874
26948
  } else if (!base.path) {
26875
- target.path = relative.path;
26949
+ target.path = relative2.path;
26876
26950
  } else {
26877
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
26951
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
26878
26952
  }
26879
26953
  target.path = removeDotSegments(target.path);
26880
26954
  }
26881
- target.query = relative.query;
26955
+ target.query = relative2.query;
26882
26956
  }
26883
26957
  target.userinfo = base.userinfo;
26884
26958
  target.host = base.host;
@@ -26886,7 +26960,7 @@ function requireFastUri() {
26886
26960
  }
26887
26961
  target.scheme = base.scheme;
26888
26962
  }
26889
- target.fragment = relative.fragment;
26963
+ target.fragment = relative2.fragment;
26890
26964
  return target;
26891
26965
  }
26892
26966
  function equal2(uriA, uriB, options) {
@@ -32269,6 +32343,121 @@ function registerSearchTool(server, getLibraryOperations, getConfig) {
32269
32343
  }
32270
32344
  );
32271
32345
  }
32346
+ function toPosixPath(p) {
32347
+ return p.split(path__default.sep).join("/");
32348
+ }
32349
+ function formatAuthor(author) {
32350
+ if (author.literal) return author.literal;
32351
+ const family = author.family || "";
32352
+ const givenInitial = author.given ? `${author.given.charAt(0)}.` : "";
32353
+ return givenInitial ? `${family}, ${givenInitial}` : family;
32354
+ }
32355
+ function resolveFulltextAndAttachments(item, attachmentsDirectory) {
32356
+ const attachments = item.custom?.attachments;
32357
+ if (!attachments) {
32358
+ return {
32359
+ fulltext: { pdf: null, markdown: null },
32360
+ attachments: []
32361
+ };
32362
+ }
32363
+ const dir = path__default.join(attachmentsDirectory, attachments.directory);
32364
+ const files = attachments.files ?? [];
32365
+ let pdfPath = null;
32366
+ let markdownPath = null;
32367
+ const nonFulltext = [];
32368
+ for (const file of files) {
32369
+ if (file.role === "fulltext") {
32370
+ if (file.filename.endsWith(".pdf")) {
32371
+ pdfPath = toPosixPath(path__default.join(dir, file.filename));
32372
+ } else if (file.filename.endsWith(".md")) {
32373
+ markdownPath = toPosixPath(path__default.join(dir, file.filename));
32374
+ }
32375
+ } else {
32376
+ nonFulltext.push({ filename: file.filename, role: file.role });
32377
+ }
32378
+ }
32379
+ return {
32380
+ fulltext: { pdf: pdfPath, markdown: markdownPath },
32381
+ attachments: nonFulltext
32382
+ };
32383
+ }
32384
+ function normalizeAuthors(item) {
32385
+ return item.author && item.author.length > 0 ? item.author.map(formatAuthor) : null;
32386
+ }
32387
+ function normalizeFileInfo(item, options) {
32388
+ if (!options?.attachmentsDirectory) {
32389
+ return { fulltext: null, attachments: null };
32390
+ }
32391
+ return resolveFulltextAndAttachments(item, options.attachmentsDirectory);
32392
+ }
32393
+ function normalizeReference(item, options) {
32394
+ const custom2 = item.custom;
32395
+ const { fulltext: fulltext2, attachments } = normalizeFileInfo(item, options);
32396
+ return {
32397
+ id: item.id,
32398
+ uuid: custom2?.uuid ?? null,
32399
+ type: item.type,
32400
+ title: item.title ?? null,
32401
+ authors: normalizeAuthors(item),
32402
+ year: item.issued?.["date-parts"]?.[0]?.[0] ?? null,
32403
+ journal: item["container-title"] ?? null,
32404
+ volume: item.volume ?? null,
32405
+ issue: item.issue ?? null,
32406
+ page: item.page ?? null,
32407
+ doi: item.DOI ?? null,
32408
+ pmid: item.PMID ?? null,
32409
+ pmcid: item.PMCID ?? null,
32410
+ url: item.URL ?? null,
32411
+ abstract: item.abstract ?? null,
32412
+ tags: custom2?.tags ?? null,
32413
+ created: custom2?.created_at ?? null,
32414
+ modified: custom2?.timestamp ?? null,
32415
+ fulltext: fulltext2,
32416
+ attachments,
32417
+ raw: item
32418
+ };
32419
+ }
32420
+ function createShowToolHandler(getLibraryOperations, getConfig) {
32421
+ return async (args) => {
32422
+ const libraryOps = getLibraryOperations();
32423
+ const config2 = getConfig();
32424
+ const id2 = args.uuid ?? args.identifier;
32425
+ const idType = args.uuid ? "uuid" : "id";
32426
+ if (!id2) {
32427
+ return {
32428
+ content: [{ type: "text", text: "Error: identifier or uuid is required" }],
32429
+ isError: true
32430
+ };
32431
+ }
32432
+ const item = await libraryOps.find(id2, { idType });
32433
+ if (!item) {
32434
+ return {
32435
+ content: [{ type: "text", text: `Reference not found: ${id2}` }],
32436
+ isError: true
32437
+ };
32438
+ }
32439
+ const attachmentsDir = config2.attachments?.directory;
32440
+ const normalizeOpts = attachmentsDir ? { attachmentsDirectory: attachmentsDir } : void 0;
32441
+ const normalized = normalizeReference(item, normalizeOpts);
32442
+ return {
32443
+ content: [{ type: "text", text: JSON.stringify(normalized, null, 2) }]
32444
+ };
32445
+ };
32446
+ }
32447
+ function registerShowTool(server, getLibraryOperations, getConfig) {
32448
+ const handler = createShowToolHandler(getLibraryOperations, getConfig);
32449
+ server.registerTool(
32450
+ "show",
32451
+ {
32452
+ description: "Show detailed information about a single reference. Returns normalized JSON with all metadata, fulltext paths, and attachments. Use identifier (citation key) or uuid to look up.",
32453
+ inputSchema: {
32454
+ identifier: z.string().optional().describe("Reference citation key (e.g., Smith2020)"),
32455
+ uuid: z.string().optional().describe("Reference UUID (alternative to identifier)")
32456
+ }
32457
+ },
32458
+ async (args) => handler(args)
32459
+ );
32460
+ }
32272
32461
  function registerAllTools(server, getLibraryOperations, getConfig) {
32273
32462
  registerSearchTool(server, getLibraryOperations, getConfig);
32274
32463
  registerListTool(server, getLibraryOperations, getConfig);
@@ -32276,6 +32465,7 @@ function registerAllTools(server, getLibraryOperations, getConfig) {
32276
32465
  registerCheckTool(server, getLibraryOperations);
32277
32466
  registerAddTool(server, getLibraryOperations);
32278
32467
  registerRemoveTool(server, getLibraryOperations);
32468
+ registerShowTool(server, getLibraryOperations, getConfig);
32279
32469
  registerFulltextAttachTool(server, getLibraryOperations, getConfig);
32280
32470
  registerFulltextGetTool(server, getLibraryOperations, getConfig);
32281
32471
  registerFulltextDetachTool(server, getLibraryOperations, getConfig);
@@ -32335,7 +32525,7 @@ async function mcpStart(options) {
32335
32525
  async function executeRemove(options, context) {
32336
32526
  const { identifier, idType = "id", fulltextDirectory, deleteFulltext = false } = options;
32337
32527
  if (context.mode === "local" && deleteFulltext && fulltextDirectory) {
32338
- const { removeReference } = await import("./index-C_mW5LMY.js").then((n) => n.A);
32528
+ const { removeReference } = await import("./index-B4-i4PrU.js").then((n) => n.A);
32339
32529
  return removeReference(context.library, {
32340
32530
  identifier,
32341
32531
  idType,
@@ -32390,7 +32580,7 @@ Continue?`;
32390
32580
  }
32391
32581
  async function executeInteractiveRemove(context, config2) {
32392
32582
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
32393
- const { selectReferenceItemsOrExit } = await import("./reference-select-Bm-05R0u.js");
32583
+ const { selectReferenceItemsOrExit } = await import("./reference-select-B9b9Ez7Q.js");
32394
32584
  const allReferences = await context.library.getAll();
32395
32585
  const selectedItems = await withAlternateScreen2(
32396
32586
  () => selectReferenceItemsOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -32615,7 +32805,7 @@ async function executeInteractiveSearch(options, context, config2) {
32615
32805
  validateInteractiveOptions(options);
32616
32806
  const { checkTTY } = await import("./tty-BMyaEOhX.js");
32617
32807
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
32618
- const { runSearchFlow } = await import("./index-CA9y5wSm.js");
32808
+ const { runSearchFlow } = await import("./index-BuQm8A5F.js");
32619
32809
  const { search } = await import("./file-watcher-CWHg1yol.js").then((n) => n.B);
32620
32810
  const { tokenize } = await import("./file-watcher-CWHg1yol.js").then((n) => n.A);
32621
32811
  checkTTY();
@@ -32634,7 +32824,7 @@ async function executeInteractiveSearch(options, context, config2) {
32634
32824
  })
32635
32825
  );
32636
32826
  if (result.selectedItems && !result.cancelled) {
32637
- const { isSideEffectAction } = await import("./action-menu-DCZcb0HB.js");
32827
+ const { isSideEffectAction } = await import("./action-menu-DLEwSKrj.js");
32638
32828
  if (isSideEffectAction(result.action)) {
32639
32829
  await executeSideEffectAction(result.action, result.selectedItems, context, config2);
32640
32830
  return { output: "", cancelled: false, action: result.action };
@@ -32836,6 +33026,142 @@ async function serverStatus(portfilePath) {
32836
33026
  }
32837
33027
  return result;
32838
33028
  }
33029
+ const LABEL_WIDTH = 11;
33030
+ function label(name) {
33031
+ return ` ${name.padEnd(LABEL_WIDTH)}`;
33032
+ }
33033
+ function formatJournalLine(ref2) {
33034
+ let line = ref2.journal ?? "";
33035
+ if (ref2.volume) {
33036
+ line += ref2.issue ? `, ${ref2.volume}(${ref2.issue})` : `, ${ref2.volume}`;
33037
+ }
33038
+ if (ref2.page) {
33039
+ line += `, ${ref2.page}`;
33040
+ }
33041
+ return line;
33042
+ }
33043
+ function formatDate(iso) {
33044
+ return iso.slice(0, 10);
33045
+ }
33046
+ function formatFulltext(lines, ref2) {
33047
+ if (!ref2.fulltext) return;
33048
+ if (!ref2.fulltext.pdf && !ref2.fulltext.markdown) {
33049
+ lines.push(`${label("Fulltext:")}-`);
33050
+ return;
33051
+ }
33052
+ lines.push(`${label("Fulltext:")}`);
33053
+ lines.push(` pdf: ${ref2.fulltext.pdf ?? "-"}`);
33054
+ lines.push(` markdown: ${ref2.fulltext.markdown ?? "-"}`);
33055
+ }
33056
+ function formatAttachments(lines, ref2) {
33057
+ if (!ref2.attachments || ref2.attachments.length === 0) return;
33058
+ const roles = /* @__PURE__ */ new Map();
33059
+ for (const a of ref2.attachments) {
33060
+ roles.set(a.role, (roles.get(a.role) ?? 0) + 1);
33061
+ }
33062
+ const parts = [...roles.entries()].map(([role, count]) => `${role} (${count} files)`);
33063
+ lines.push(`${label("Files:")}${parts.join(", ")}`);
33064
+ }
33065
+ function formatAbstract(lines, ref2) {
33066
+ if (!ref2.abstract) return;
33067
+ lines.push("");
33068
+ lines.push(`${label("Abstract:")}`);
33069
+ for (const line of ref2.abstract.split("\n")) {
33070
+ lines.push(` ${line}`);
33071
+ }
33072
+ }
33073
+ function formatShowPretty(ref2) {
33074
+ const lines = [];
33075
+ const header = ref2.title ? `[${ref2.id}] ${ref2.title}` : `[${ref2.id}]`;
33076
+ lines.push(header);
33077
+ lines.push(`${label("Type:")}${ref2.type}`);
33078
+ if (ref2.authors) {
33079
+ lines.push(`${label("Authors:")}${ref2.authors.join("; ")}`);
33080
+ }
33081
+ if (ref2.year != null) {
33082
+ lines.push(`${label("Year:")}${ref2.year}`);
33083
+ }
33084
+ if (ref2.journal) {
33085
+ lines.push(`${label("Journal:")}${formatJournalLine(ref2)}`);
33086
+ }
33087
+ if (ref2.doi) lines.push(`${label("DOI:")}${ref2.doi}`);
33088
+ if (ref2.pmid) lines.push(`${label("PMID:")}${ref2.pmid}`);
33089
+ if (ref2.pmcid) lines.push(`${label("PMCID:")}${ref2.pmcid}`);
33090
+ if (ref2.url) lines.push(`${label("URL:")}${ref2.url}`);
33091
+ lines.push(`${label("UUID:")}${ref2.uuid ?? "(no uuid)"}`);
33092
+ if (ref2.tags && ref2.tags.length > 0) {
33093
+ lines.push(`${label("Tags:")}${ref2.tags.join(", ")}`);
33094
+ }
33095
+ if (ref2.created) lines.push(`${label("Added:")}${formatDate(ref2.created)}`);
33096
+ if (ref2.modified) lines.push(`${label("Modified:")}${formatDate(ref2.modified)}`);
33097
+ formatFulltext(lines, ref2);
33098
+ formatAttachments(lines, ref2);
33099
+ formatAbstract(lines, ref2);
33100
+ return lines.join("\n");
33101
+ }
33102
+ async function executeShow(identifier, options, context) {
33103
+ const idType = options.uuid ? "uuid" : "id";
33104
+ return context.library.find(identifier, { idType });
33105
+ }
33106
+ function formatShowOutput(item, options, attachmentsDirectory) {
33107
+ const format2 = options.json ? "json" : options.output ?? "pretty";
33108
+ const normalizeOpts = attachmentsDirectory ? { attachmentsDirectory } : void 0;
33109
+ if (format2 === "json") {
33110
+ const normalized2 = normalizeReference(item, normalizeOpts);
33111
+ return JSON.stringify(normalized2, null, 2);
33112
+ }
33113
+ if (format2 === "yaml") {
33114
+ const normalized2 = normalizeReference(item, normalizeOpts);
33115
+ return stringify(normalized2);
33116
+ }
33117
+ if (format2 === "bibtex") {
33118
+ return formatBibtex([item]);
33119
+ }
33120
+ const normalized = normalizeReference(item, normalizeOpts);
33121
+ return formatShowPretty(normalized);
33122
+ }
33123
+ async function executeInteractiveSelect$1(context, config2) {
33124
+ const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
33125
+ const { selectReferencesOrExit } = await import("./reference-select-B9b9Ez7Q.js");
33126
+ const allReferences = await context.library.getAll();
33127
+ const identifiers = await withAlternateScreen2(
33128
+ () => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
33129
+ );
33130
+ return identifiers[0] ?? "";
33131
+ }
33132
+ async function handleShowAction(identifier, options, globalOpts) {
33133
+ try {
33134
+ const config2 = await loadConfigWithOverrides({ ...globalOpts, ...options });
33135
+ const context = await createExecutionContext(config2, Library.load);
33136
+ let resolvedIdentifier;
33137
+ if (identifier) {
33138
+ resolvedIdentifier = identifier;
33139
+ } else if (isTTY()) {
33140
+ resolvedIdentifier = await executeInteractiveSelect$1(context, config2);
33141
+ } else {
33142
+ const stdinId = await readIdentifierFromStdin();
33143
+ if (!stdinId) {
33144
+ exitWithError("Identifier required (non-interactive mode)");
33145
+ return;
33146
+ }
33147
+ resolvedIdentifier = stdinId;
33148
+ }
33149
+ const item = await executeShow(resolvedIdentifier, options, context);
33150
+ if (!item) {
33151
+ exitWithError(`Reference not found: ${resolvedIdentifier}`);
33152
+ return;
33153
+ }
33154
+ const output = formatShowOutput(item, options, config2.attachments.directory);
33155
+ if (output) {
33156
+ await writeOutputWithClipboard(output, false, config2.logLevel === "silent");
33157
+ }
33158
+ setExitCode(ExitCode.SUCCESS);
33159
+ } catch (error) {
33160
+ process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}
33161
+ `);
33162
+ setExitCode(ExitCode.INTERNAL_ERROR);
33163
+ }
33164
+ }
32839
33165
  function parseSetOption(input) {
32840
33166
  const match = input.match(/^([a-zA-Z][a-zA-Z0-9_.]*)([\+\-]?=)(.*)$/);
32841
33167
  if (!match) {
@@ -33045,7 +33371,7 @@ function formatUpdateOutput(result, identifier) {
33045
33371
  }
33046
33372
  async function executeInteractiveUpdate(context, config2) {
33047
33373
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
33048
- const { selectReferencesOrExit } = await import("./reference-select-Bm-05R0u.js");
33374
+ const { selectReferencesOrExit } = await import("./reference-select-B9b9Ez7Q.js");
33049
33375
  const allReferences = await context.library.getAll();
33050
33376
  const identifiers = await withAlternateScreen2(
33051
33377
  () => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -33340,7 +33666,7 @@ function getUrlExitCode(result) {
33340
33666
  }
33341
33667
  async function executeInteractiveSelect(context, config2) {
33342
33668
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
33343
- const { selectReferencesOrExit } = await import("./reference-select-Bm-05R0u.js");
33669
+ const { selectReferencesOrExit } = await import("./reference-select-B9b9Ez7Q.js");
33344
33670
  const allReferences = await context.library.getAll();
33345
33671
  const identifiers = await withAlternateScreen2(
33346
33672
  () => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -33774,6 +34100,7 @@ function createProgram() {
33774
34100
  }
33775
34101
  });
33776
34102
  registerListCommand(program);
34103
+ registerShowCommand(program);
33777
34104
  registerSearchCommand(program);
33778
34105
  registerExportCommand(program);
33779
34106
  registerAddCommand(program);
@@ -33787,6 +34114,7 @@ function createProgram() {
33787
34114
  registerAttachCommand(program);
33788
34115
  registerMcpCommand(program);
33789
34116
  registerUrlCommand(program);
34117
+ registerInstallCommand(program);
33790
34118
  registerConfigCommand(program);
33791
34119
  registerCompletionCommand(program);
33792
34120
  return program;
@@ -33815,6 +34143,12 @@ function registerListCommand(program) {
33815
34143
  await handleListAction(options, program);
33816
34144
  });
33817
34145
  }
34146
+ function registerShowCommand(program) {
34147
+ program.command("show [identifier]").description("Show detailed information about a single reference").option("--uuid", "Interpret identifier as UUID").option("-o, --output <format>", "Output format: pretty (default), json, yaml, bibtex").option("--json", "Alias for --output json").action(async (identifier, options) => {
34148
+ const globalOpts = program.opts();
34149
+ await handleShowAction(identifier, options, globalOpts);
34150
+ });
34151
+ }
33818
34152
  async function handleExportAction(ids, options, program) {
33819
34153
  try {
33820
34154
  const globalOpts = program.opts();
@@ -33945,7 +34279,7 @@ function shouldAutoFetch(cliFlag, configEnabled) {
33945
34279
  return configEnabled;
33946
34280
  }
33947
34281
  async function performAutoFetch(addedItems, context, config2) {
33948
- const { fulltextFetch: fulltextFetch2 } = await import("./index-C_mW5LMY.js").then((n) => n.z);
34282
+ const { fulltextFetch: fulltextFetch2 } = await import("./index-B4-i4PrU.js").then((n) => n.z);
33949
34283
  const fetchResults = await autoFetchFulltext(addedItems, context, {
33950
34284
  fulltextConfig: config2.fulltext,
33951
34285
  fulltextDirectory: config2.attachments.directory,
@@ -34211,6 +34545,25 @@ function registerUrlCommand(program) {
34211
34545
  await handleUrlAction(identifiers.length > 0 ? identifiers : void 0, options, globalOpts);
34212
34546
  });
34213
34547
  }
34548
+ function registerInstallCommand(program) {
34549
+ const installCmd = program.command("install").description("Install tools and integrations");
34550
+ installCmd.command("skills").description("Install Agent Skills (SKILL.md) for AI coding agents").option("-f, --force", "Overwrite existing files").option("-u, --user", "Install to user-level directory (~/.agents/skills/)").action(async (options) => {
34551
+ try {
34552
+ const result = await executeInstallSkills({
34553
+ force: options.force ?? false,
34554
+ ...options.user != null && { user: options.user }
34555
+ });
34556
+ const output = formatInstallSkillsOutput(result);
34557
+ process.stdout.write(`${output}
34558
+ `);
34559
+ setExitCode(ExitCode.SUCCESS);
34560
+ } catch (error) {
34561
+ process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}
34562
+ `);
34563
+ setExitCode(ExitCode.INTERNAL_ERROR);
34564
+ }
34565
+ });
34566
+ }
34214
34567
  async function main(argv) {
34215
34568
  const program = createProgram();
34216
34569
  if (process.env.COMP_LINE) {
@@ -34240,4 +34593,4 @@ export {
34240
34593
  restoreStdinAfterInk as r,
34241
34594
  syncAttachments as s
34242
34595
  };
34243
- //# sourceMappingURL=index-4w0pu_0o.js.map
34596
+ //# sourceMappingURL=index-CmkN2-2A.js.map