@voidwire/lore 0.2.0 → 0.3.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 (4) hide show
  1. package/cli.ts +102 -1
  2. package/index.ts +8 -0
  3. package/lib/about.ts +103 -0
  4. package/package.json +1 -1
package/cli.ts CHANGED
@@ -30,6 +30,8 @@ import {
30
30
  info,
31
31
  formatInfoHuman,
32
32
  projects,
33
+ about,
34
+ formatBriefAbout,
33
35
  captureTask,
34
36
  captureKnowledge,
35
37
  captureNote,
@@ -417,6 +419,55 @@ function handleProjects(args: string[]): void {
417
419
  }
418
420
  }
419
421
 
422
+ // ============================================================================
423
+ // About Command
424
+ // ============================================================================
425
+
426
+ function handleAbout(args: string[]): void {
427
+ if (hasFlag(args, "help")) {
428
+ showAboutHelp();
429
+ }
430
+
431
+ const parsed = parseArgs(args);
432
+ const positional = getPositionalArgs(args);
433
+
434
+ if (positional.length === 0) {
435
+ fail("Missing project name. Use: lore about <project>");
436
+ }
437
+
438
+ const project = positional[0];
439
+ const brief = hasFlag(args, "brief");
440
+ const limit = parsed.has("limit")
441
+ ? parseInt(parsed.get("limit")!, 10)
442
+ : undefined;
443
+
444
+ try {
445
+ const result = about(project, { brief, limit });
446
+
447
+ if (brief) {
448
+ console.log(formatBriefAbout(result));
449
+ } else {
450
+ output({
451
+ success: true,
452
+ ...result,
453
+ });
454
+ }
455
+
456
+ const totalCount =
457
+ result.commits.count +
458
+ result.captures.count +
459
+ result.tasks.count +
460
+ result.teachings.count +
461
+ result.sessions.count;
462
+
463
+ console.error(`✅ ${totalCount} entries for project: ${project}`);
464
+ process.exit(0);
465
+ } catch (error) {
466
+ const message = error instanceof Error ? error.message : "Unknown error";
467
+ fail(message, 2);
468
+ }
469
+ }
470
+
420
471
  // ============================================================================
421
472
  // Capture Command
422
473
  // ============================================================================
@@ -589,6 +640,8 @@ Usage:
589
640
  lore list --domains List available domains
590
641
  lore info Show indexed sources and counts
591
642
  lore info --human Human-readable info
643
+ lore about <project> Aggregate view of project knowledge
644
+ lore about <project> --brief Compact project summary
592
645
  lore capture task|knowledge|note|teaching Capture knowledge
593
646
 
594
647
  Search Options:
@@ -790,6 +843,51 @@ Examples:
790
843
  process.exit(0);
791
844
  }
792
845
 
846
+ function showAboutHelp(): void {
847
+ console.log(`
848
+ lore about - Show everything about a project
849
+
850
+ Usage:
851
+ lore about <project> Aggregate view of project knowledge
852
+ lore about <project> --brief Compact output
853
+
854
+ Options:
855
+ --brief Compact output (titles only)
856
+ --limit <n> Results per source (default: 10)
857
+ --help Show this help
858
+
859
+ Sources queried:
860
+ commits Git commits for project
861
+ captures Quick captures in project context
862
+ tasks Development tasks for project
863
+ teachings Teachings from project
864
+ sessions Claude Code sessions for project
865
+
866
+ Output (JSON):
867
+ {
868
+ "project": "name",
869
+ "commits": [...],
870
+ "captures": [...],
871
+ "tasks": [...],
872
+ "teachings": [...],
873
+ "sessions": [...]
874
+ }
875
+
876
+ Output (--brief):
877
+ commits (3):
878
+ project: hash - commit message
879
+
880
+ captures (2):
881
+ project: insight text
882
+
883
+ Examples:
884
+ lore about momentum --brief
885
+ lore about lore | jq '.commits | length'
886
+ lore about momentum --limit 5
887
+ `);
888
+ process.exit(0);
889
+ }
890
+
793
891
  function showCaptureHelp(): void {
794
892
  console.log(`
795
893
  lore capture - Capture knowledge
@@ -871,12 +969,15 @@ function main(): void {
871
969
  case "projects":
872
970
  handleProjects(commandArgs);
873
971
  break;
972
+ case "about":
973
+ handleAbout(commandArgs);
974
+ break;
874
975
  case "capture":
875
976
  handleCapture(commandArgs);
876
977
  break;
877
978
  default:
878
979
  fail(
879
- `Unknown command: ${command}. Use: search, list, info, projects, or capture`,
980
+ `Unknown command: ${command}. Use: search, list, info, projects, about, or capture`,
880
981
  );
881
982
  }
882
983
  }
package/index.ts CHANGED
@@ -39,6 +39,14 @@ export {
39
39
  // Projects
40
40
  export { projects } from "./lib/projects";
41
41
 
42
+ // About
43
+ export {
44
+ about,
45
+ formatBriefAbout,
46
+ type AboutResult,
47
+ type AboutOptions,
48
+ } from "./lib/about";
49
+
42
50
  // Prismis integration
43
51
  export {
44
52
  searchPrismis,
package/lib/about.ts ADDED
@@ -0,0 +1,103 @@
1
+ /**
2
+ * lib/about.ts - Project knowledge aggregation
3
+ *
4
+ * Aggregates all knowledge sources for a given project.
5
+ * Uses parallel queries via Promise.all for performance.
6
+ */
7
+
8
+ import { list, formatBriefList, type ListResult, type Domain } from "./list";
9
+
10
+ export interface AboutOptions {
11
+ brief?: boolean;
12
+ limit?: number;
13
+ }
14
+
15
+ export interface AboutResult {
16
+ project: string;
17
+ commits: ListResult;
18
+ captures: ListResult;
19
+ tasks: ListResult;
20
+ teachings: ListResult;
21
+ sessions: ListResult;
22
+ }
23
+
24
+ /**
25
+ * Sources to query for project knowledge
26
+ * Each source has a different field for project mapping (handled by list.ts)
27
+ * Note: "insights" will be added when task 2.1 is complete
28
+ */
29
+ const ABOUT_SOURCES: Domain[] = [
30
+ "commits",
31
+ "captures",
32
+ "tasks",
33
+ "teachings",
34
+ "sessions",
35
+ ];
36
+
37
+ /**
38
+ * Get aggregated knowledge about a project across all sources
39
+ *
40
+ * @param project - Project name to query
41
+ * @param options - Optional brief flag and limit
42
+ * @returns AboutResult with data from all sources, or formatted string if brief
43
+ */
44
+ export function about(
45
+ project: string,
46
+ options: AboutOptions = {},
47
+ ): AboutResult {
48
+ const limit = options.limit ?? 10;
49
+
50
+ // Query all sources in parallel
51
+ const results = ABOUT_SOURCES.map((source) => {
52
+ try {
53
+ return list(source, { project, limit });
54
+ } catch {
55
+ // Source doesn't exist or has no data - return empty result
56
+ return {
57
+ domain: source,
58
+ entries: [],
59
+ count: 0,
60
+ } as ListResult;
61
+ }
62
+ });
63
+
64
+ return {
65
+ project,
66
+ commits: results[0],
67
+ captures: results[1],
68
+ tasks: results[2],
69
+ teachings: results[3],
70
+ sessions: results[4],
71
+ };
72
+ }
73
+
74
+ /**
75
+ * Format about result as brief, compact output
76
+ * Groups by source, skips empty sources
77
+ */
78
+ export function formatBriefAbout(result: AboutResult): string {
79
+ const sections: string[] = [];
80
+
81
+ // Format each non-empty source
82
+ if (result.commits.count > 0) {
83
+ sections.push(formatBriefList(result.commits));
84
+ }
85
+ if (result.captures.count > 0) {
86
+ sections.push(formatBriefList(result.captures));
87
+ }
88
+ if (result.tasks.count > 0) {
89
+ sections.push(formatBriefList(result.tasks));
90
+ }
91
+ if (result.teachings.count > 0) {
92
+ sections.push(formatBriefList(result.teachings));
93
+ }
94
+ if (result.sessions.count > 0) {
95
+ sections.push(formatBriefList(result.sessions));
96
+ }
97
+
98
+ if (sections.length === 0) {
99
+ return `(no results for project: ${result.project})`;
100
+ }
101
+
102
+ return sections.join("\n\n");
103
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voidwire/lore",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Unified knowledge CLI - Search, list, and capture your indexed knowledge",
5
5
  "type": "module",
6
6
  "main": "./index.ts",