@voidwire/lore 0.3.0 → 0.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.
package/cli.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  * Usage:
11
11
  * lore search <query> Search all sources
12
12
  * lore search <source> <query> Search specific source
13
- * lore list <domain> List domain entries
13
+ * lore list <source> List source entries
14
14
  * lore capture task|knowledge|note|teaching Capture knowledge
15
15
  *
16
16
  * Exit codes:
@@ -25,7 +25,6 @@ import {
25
25
  searchAtuin,
26
26
  listSources,
27
27
  list,
28
- listDomains,
29
28
  formatBriefList,
30
29
  info,
31
30
  formatInfoHuman,
@@ -39,11 +38,11 @@ import {
39
38
  semanticSearch,
40
39
  formatBriefSearch,
41
40
  hasEmbeddings,
42
- DOMAINS,
41
+ SOURCES,
43
42
  type SearchResult,
44
43
  type ListResult,
45
44
  type ListEntry,
46
- type Domain,
45
+ type Source,
47
46
  type TaskInput,
48
47
  type KnowledgeInput,
49
48
  type NoteInput,
@@ -289,7 +288,7 @@ async function handleSearch(args: string[]): Promise<void> {
289
288
  // ============================================================================
290
289
 
291
290
  function formatHumanOutput(result: ListResult): string {
292
- const lines: string[] = [`${result.domain} (${result.count} entries):`, ""];
291
+ const lines: string[] = [`${result.source} (${result.count} entries):`, ""];
293
292
 
294
293
  for (const entry of result.entries) {
295
294
  lines.push(` ${entry.title}`);
@@ -309,21 +308,23 @@ function handleList(args: string[]): void {
309
308
  const parsed = parseArgs(args);
310
309
  const positional = getPositionalArgs(args);
311
310
 
312
- // Handle --domains flag
311
+ // Handle --domains flag (deprecated)
313
312
  if (hasFlag(args, "domains")) {
314
- output({ success: true, domains: listDomains() });
315
- console.error(`✅ ${DOMAINS.length} domains available`);
313
+ console.error("⚠️ --domains is deprecated. Use 'lore sources' instead.");
314
+ const sources = listSources();
315
+ output({ success: true, sources });
316
+ console.error(`✅ ${SOURCES.length} sources available`);
316
317
  process.exit(0);
317
318
  }
318
319
 
319
320
  if (positional.length === 0) {
320
- fail(`Missing domain. Available: ${DOMAINS.join(", ")}`);
321
+ fail(`Missing source. Available: ${SOURCES.join(", ")}`);
321
322
  }
322
323
 
323
- const domain = positional[0] as Domain;
324
+ const source = positional[0] as Source;
324
325
 
325
- if (!DOMAINS.includes(domain)) {
326
- fail(`Invalid domain: ${domain}. Available: ${DOMAINS.join(", ")}`);
326
+ if (!SOURCES.includes(source)) {
327
+ fail(`Invalid source: ${source}. Available: ${SOURCES.join(", ")}`);
327
328
  }
328
329
 
329
330
  const limit = parsed.has("limit")
@@ -334,7 +335,7 @@ function handleList(args: string[]): void {
334
335
  const brief = hasFlag(args, "brief");
335
336
 
336
337
  try {
337
- const result = list(domain, { limit, project });
338
+ const result = list(source, { limit, project });
338
339
 
339
340
  if (brief) {
340
341
  console.log(formatBriefList(result));
@@ -347,13 +348,13 @@ function handleList(args: string[]): void {
347
348
  } else {
348
349
  output({
349
350
  success: true,
350
- domain: result.domain,
351
+ source: result.source,
351
352
  entries: result.entries,
352
353
  count: result.count,
353
354
  });
354
355
  }
355
356
 
356
- console.error(`✅ ${result.count} entries in ${domain}`);
357
+ console.error(`✅ ${result.count} entries in ${source}`);
357
358
  process.exit(0);
358
359
  } catch (error) {
359
360
  const message = error instanceof Error ? error.message : "Unknown error";
@@ -468,6 +469,50 @@ function handleAbout(args: string[]): void {
468
469
  }
469
470
  }
470
471
 
472
+ // ============================================================================
473
+ // Sources Command
474
+ // ============================================================================
475
+
476
+ function handleSources(args: string[]): void {
477
+ if (hasFlag(args, "help")) {
478
+ showSourcesHelp();
479
+ }
480
+
481
+ try {
482
+ const sources = listSources();
483
+ output({
484
+ success: true,
485
+ sources,
486
+ });
487
+ console.error(`✅ ${sources.length} sources indexed`);
488
+ process.exit(0);
489
+ } catch (error) {
490
+ const message = error instanceof Error ? error.message : "Unknown error";
491
+ fail(message, 2);
492
+ }
493
+ }
494
+
495
+ function showSourcesHelp(): void {
496
+ console.log(`
497
+ lore sources - List all indexed sources with counts
498
+
499
+ Usage:
500
+ lore sources List all sources with entry counts
501
+
502
+ Options:
503
+ --help Show this help
504
+
505
+ Output:
506
+ JSON array of {source, count} objects, sorted by count descending.
507
+
508
+ Examples:
509
+ lore sources
510
+ lore sources | jq '.[0]'
511
+ lore sources | jq -r '.[] | "\\(.source): \\(.count)"'
512
+ `);
513
+ process.exit(0);
514
+ }
515
+
471
516
  // ============================================================================
472
517
  // Capture Command
473
518
  // ============================================================================
@@ -635,9 +680,8 @@ Philosophy:
635
680
  Usage:
636
681
  lore search <query> Search all sources
637
682
  lore search <source> <query> Search specific source
638
- lore search --sources List indexed sources
639
- lore list <domain> List domain entries
640
- lore list --domains List available domains
683
+ lore sources List indexed sources with counts
684
+ lore list <source> List source entries
641
685
  lore info Show indexed sources and counts
642
686
  lore info --human Human-readable info
643
687
  lore about <project> Aggregate view of project knowledge
@@ -650,7 +694,6 @@ Search Options:
650
694
  --project <name> Filter results by project
651
695
  --brief Compact output (titles only)
652
696
  --since <date> Filter by date (today, yesterday, this-week, YYYY-MM-DD)
653
- --sources List indexed sources with counts
654
697
 
655
698
  Passthrough Sources:
656
699
  prismis Semantic search via prismis daemon (requires prismis-daemon running)
@@ -660,7 +703,7 @@ List Options:
660
703
  --limit <n> Maximum entries
661
704
  --format <fmt> Output format: json (default), jsonl, human
662
705
  --brief Compact output (titles only)
663
- --domains List available domains
706
+ --project <name> Filter by project name
664
707
 
665
708
  Capture Types:
666
709
  task Log task completion
@@ -688,6 +731,7 @@ Capture Types:
688
731
  Examples:
689
732
  lore search "authentication"
690
733
  lore search blogs "typescript patterns"
734
+ lore sources
691
735
  lore list development
692
736
  lore list commits --limit 10 --format human
693
737
  lore capture knowledge --context=lore --text="Unified CLI works" --type=learning
@@ -702,7 +746,6 @@ lore search - Search indexed knowledge
702
746
  Usage:
703
747
  lore search <query> Search all sources
704
748
  lore search <source> <query> Search specific source
705
- lore search --sources List indexed sources
706
749
 
707
750
  Options:
708
751
  --exact Use FTS5 text search (bypasses semantic search)
@@ -710,7 +753,6 @@ Options:
710
753
  --project <name> Filter results by project (post-filters KNN results)
711
754
  --brief Compact output (titles only)
712
755
  --since <date> Filter by date (today, yesterday, this-week, YYYY-MM-DD)
713
- --sources List indexed sources with counts
714
756
  --help Show this help
715
757
 
716
758
  Indexed Sources:
@@ -725,6 +767,7 @@ Indexed Sources:
725
767
  readmes Project README files
726
768
  sessions Claude Code session transcripts
727
769
  tasks Logged development tasks
770
+ teachings Teaching moments
728
771
 
729
772
  Passthrough Sources:
730
773
  prismis Semantic search via prismis daemon
@@ -732,6 +775,9 @@ Passthrough Sources:
732
775
  atuin Shell history search
733
776
  (queries ~/.local/share/atuin/history.db directly)
734
777
 
778
+ See also:
779
+ lore sources List all sources with entry counts
780
+
735
781
  Examples:
736
782
  lore search "authentication"
737
783
  lore search blogs "typescript patterns"
@@ -746,21 +792,19 @@ Examples:
746
792
 
747
793
  function showListHelp(): void {
748
794
  console.log(`
749
- lore list - List domain entries
795
+ lore list - List source entries
750
796
 
751
797
  Usage:
752
- lore list <domain> List entries in domain
753
- lore list --domains List available domains
798
+ lore list <source> List entries in source
754
799
 
755
800
  Options:
756
801
  --limit <n> Maximum entries (default: all)
757
802
  --format <fmt> Output format: json (default), jsonl, human
758
803
  --project <name> Filter by project name
759
804
  --brief Compact output (titles only)
760
- --domains List available domains
761
805
  --help Show this help
762
806
 
763
- Available Domains:
807
+ Available Sources:
764
808
  blogs Blog posts
765
809
  books Books read
766
810
  captures Quick captures
@@ -773,11 +817,14 @@ Available Domains:
773
817
  movies Movies watched
774
818
  obsidian Obsidian notes
775
819
  people People/contacts
776
- personal Personal data aggregate
777
820
  podcasts Podcasts listened
778
821
  readmes Project READMEs
779
822
  sessions Claude Code sessions
780
823
  tasks Development tasks
824
+ teachings Teaching moments
825
+
826
+ See also:
827
+ lore sources List all sources with entry counts
781
828
 
782
829
  Examples:
783
830
  lore list development
@@ -963,6 +1010,9 @@ function main(): void {
963
1010
  case "list":
964
1011
  handleList(commandArgs);
965
1012
  break;
1013
+ case "sources":
1014
+ handleSources(commandArgs);
1015
+ break;
966
1016
  case "info":
967
1017
  handleInfo(commandArgs);
968
1018
  break;
@@ -977,7 +1027,7 @@ function main(): void {
977
1027
  break;
978
1028
  default:
979
1029
  fail(
980
- `Unknown command: ${command}. Use: search, list, info, projects, about, or capture`,
1030
+ `Unknown command: ${command}. Use: search, list, sources, info, projects, about, or capture`,
981
1031
  );
982
1032
  }
983
1033
  }
package/index.ts CHANGED
@@ -19,10 +19,9 @@ export {
19
19
  // List
20
20
  export {
21
21
  list,
22
- listDomains,
23
22
  formatBriefList,
24
- DOMAINS,
25
- type Domain,
23
+ SOURCES,
24
+ type Source,
26
25
  type ListOptions,
27
26
  type ListEntry,
28
27
  type ListResult,
package/lib/about.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * Uses parallel queries via Promise.all for performance.
6
6
  */
7
7
 
8
- import { list, formatBriefList, type ListResult, type Domain } from "./list";
8
+ import { list, formatBriefList, type ListResult, type Source } from "./list";
9
9
 
10
10
  export interface AboutOptions {
11
11
  brief?: boolean;
@@ -26,7 +26,7 @@ export interface AboutResult {
26
26
  * Each source has a different field for project mapping (handled by list.ts)
27
27
  * Note: "insights" will be added when task 2.1 is complete
28
28
  */
29
- const ABOUT_SOURCES: Domain[] = [
29
+ const ABOUT_SOURCES: Source[] = [
30
30
  "commits",
31
31
  "captures",
32
32
  "tasks",
@@ -48,13 +48,13 @@ export function about(
48
48
  const limit = options.limit ?? 10;
49
49
 
50
50
  // Query all sources in parallel
51
- const results = ABOUT_SOURCES.map((source) => {
51
+ const results = ABOUT_SOURCES.map((src) => {
52
52
  try {
53
- return list(source, { project, limit });
53
+ return list(src, { project, limit });
54
54
  } catch {
55
55
  // Source doesn't exist or has no data - return empty result
56
56
  return {
57
- domain: source,
57
+ source: src,
58
58
  entries: [],
59
59
  count: 0,
60
60
  } as ListResult;
package/lib/list.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * lib/list.ts - Domain listing functions
2
+ * lib/list.ts - Source listing functions
3
3
  *
4
- * Browse indexed domains without search queries.
4
+ * Browse indexed sources without search queries.
5
5
  * Uses Bun's built-in SQLite for zero external dependencies.
6
6
  */
7
7
 
@@ -9,8 +9,8 @@ import { Database } from "bun:sqlite";
9
9
  import { homedir } from "os";
10
10
  import { existsSync } from "fs";
11
11
 
12
- // Domain types - sources that can be listed
13
- export type Domain =
12
+ // Source types - data sources that can be listed
13
+ export type Source =
14
14
  | "development"
15
15
  | "tasks"
16
16
  | "events"
@@ -29,7 +29,7 @@ export type Domain =
29
29
  | "teachings"
30
30
  | "sessions";
31
31
 
32
- export const DOMAINS: Domain[] = [
32
+ export const SOURCES: Source[] = [
33
33
  "development",
34
34
  "tasks",
35
35
  "events",
@@ -49,8 +49,8 @@ export const DOMAINS: Domain[] = [
49
49
  "sessions",
50
50
  ];
51
51
 
52
- // Domains that query the 'personal' source with type filter
53
- const PERSONAL_SUBTYPES: Partial<Record<Domain, string>> = {
52
+ // Sources that query the 'personal' source with type filter
53
+ const PERSONAL_SUBTYPES: Partial<Record<Source, string>> = {
54
54
  books: "book",
55
55
  movies: "movie",
56
56
  podcasts: "podcast",
@@ -80,7 +80,7 @@ export interface ListEntry {
80
80
  }
81
81
 
82
82
  export interface ListResult {
83
- domain: Domain;
83
+ source: Source;
84
84
  entries: ListEntry[];
85
85
  count: number;
86
86
  }
@@ -160,17 +160,17 @@ function queryPersonalType(
160
160
  }
161
161
 
162
162
  /**
163
- * List all entries in a domain
163
+ * List all entries in a source
164
164
  *
165
- * @param domain - The domain to list (development, tasks, blogs, etc.)
165
+ * @param source - The source to list (development, tasks, blogs, etc.)
166
166
  * @param options - Optional limit
167
167
  * @returns ListResult with entries and count
168
- * @throws Error if database doesn't exist or domain is invalid
168
+ * @throws Error if database doesn't exist or source is invalid
169
169
  */
170
- export function list(domain: Domain, options: ListOptions = {}): ListResult {
171
- if (!DOMAINS.includes(domain)) {
170
+ export function list(source: Source, options: ListOptions = {}): ListResult {
171
+ if (!SOURCES.includes(source)) {
172
172
  throw new Error(
173
- `Invalid domain: ${domain}. Valid domains: ${DOMAINS.join(", ")}`,
173
+ `Invalid source: ${source}. Valid sources: ${SOURCES.join(", ")}`,
174
174
  );
175
175
  }
176
176
 
@@ -185,16 +185,16 @@ export function list(domain: Domain, options: ListOptions = {}): ListResult {
185
185
  try {
186
186
  let entries: ListEntry[];
187
187
 
188
- // Check if this is a personal subtype domain
189
- const personalType = PERSONAL_SUBTYPES[domain];
188
+ // Check if this is a personal subtype source
189
+ const personalType = PERSONAL_SUBTYPES[source];
190
190
  if (personalType) {
191
191
  entries = queryPersonalType(db, personalType, options.limit);
192
192
  } else {
193
- entries = queryBySource(db, domain, options.limit, options.project);
193
+ entries = queryBySource(db, source, options.limit, options.project);
194
194
  }
195
195
 
196
196
  return {
197
- domain,
197
+ source,
198
198
  entries,
199
199
  count: entries.length,
200
200
  };
@@ -204,28 +204,28 @@ export function list(domain: Domain, options: ListOptions = {}): ListResult {
204
204
  }
205
205
 
206
206
  /**
207
- * Get available domains
207
+ * Get available sources
208
208
  */
209
- export function listDomains(): Domain[] {
210
- return [...DOMAINS];
209
+ export function listSources(): Source[] {
210
+ return [...SOURCES];
211
211
  }
212
212
 
213
213
  /**
214
214
  * Extract project name from entry metadata
215
215
  */
216
- function extractProjectFromEntry(entry: ListEntry, domain: string): string {
217
- const field = PROJECT_FIELD[domain];
216
+ function extractProjectFromEntry(entry: ListEntry, source: string): string {
217
+ const field = PROJECT_FIELD[source];
218
218
  if (!field) return "unknown";
219
219
  return (entry.metadata[field] as string) || "unknown";
220
220
  }
221
221
 
222
222
  /**
223
- * Extract identifier from entry based on domain type
223
+ * Extract identifier from entry based on source type
224
224
  */
225
- function extractIdentifier(entry: ListEntry, domain: string): string {
225
+ function extractIdentifier(entry: ListEntry, source: string): string {
226
226
  const metadata = entry.metadata;
227
227
 
228
- switch (domain) {
228
+ switch (source) {
229
229
  case "commits":
230
230
  return (metadata.sha as string)?.substring(0, 7) || "";
231
231
  case "sessions":
@@ -239,8 +239,8 @@ function extractIdentifier(entry: ListEntry, domain: string): string {
239
239
  * Get the best display text for an entry
240
240
  * Commits use content (commit message), others use title
241
241
  */
242
- function getDisplayText(entry: ListEntry, domain: string): string {
243
- if (domain === "commits") {
242
+ function getDisplayText(entry: ListEntry, source: string): string {
243
+ if (source === "commits") {
244
244
  return entry.content || entry.title;
245
245
  }
246
246
  return entry.title;
@@ -251,12 +251,12 @@ function getDisplayText(entry: ListEntry, domain: string): string {
251
251
  * One line per entry: " project: identifier - title"
252
252
  */
253
253
  export function formatBriefList(result: ListResult): string {
254
- const lines = [`${result.domain} (${result.count}):`];
254
+ const lines = [`${result.source} (${result.count}):`];
255
255
 
256
256
  result.entries.forEach((entry) => {
257
- const project = extractProjectFromEntry(entry, result.domain);
258
- const identifier = extractIdentifier(entry, result.domain);
259
- const displayText = getDisplayText(entry, result.domain);
257
+ const project = extractProjectFromEntry(entry, result.source);
258
+ const identifier = extractIdentifier(entry, result.source);
259
+ const displayText = getDisplayText(entry, result.source);
260
260
 
261
261
  const line = identifier
262
262
  ? ` ${project}: ${identifier} - ${displayText}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voidwire/lore",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Unified knowledge CLI - Search, list, and capture your indexed knowledge",
5
5
  "type": "module",
6
6
  "main": "./index.ts",