@getlore/cli 0.4.0 → 0.5.1

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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Ingest Command
3
+ *
4
+ * Push content directly into Lore from the CLI.
5
+ * Accepts inline text, a file path, or piped stdin.
6
+ */
7
+ import type { Command } from 'commander';
8
+ export declare function registerIngestCommand(program: Command, defaultDataDir: string): void;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Ingest Command
3
+ *
4
+ * Push content directly into Lore from the CLI.
5
+ * Accepts inline text, a file path, or piped stdin.
6
+ */
7
+ import { readFileSync, existsSync } from 'fs';
8
+ import path from 'path';
9
+ export function registerIngestCommand(program, defaultDataDir) {
10
+ program
11
+ .command('ingest')
12
+ .description('Ingest content into the knowledge base')
13
+ .argument('[content]', 'Content to ingest (or use --file / stdin)')
14
+ .option('-f, --file <path>', 'Read content from a file')
15
+ .option('-t, --title <title>', 'Document title')
16
+ .option('-p, --project <project>', 'Project name', 'default')
17
+ .option('--type <type>', 'Source type (e.g. meeting, notes, article)')
18
+ .option('--url <url>', 'Source URL for citation linking')
19
+ .option('--name <name>', 'Human-readable source name')
20
+ .option('--tags <tags>', 'Comma-separated tags')
21
+ .option('-d, --data-dir <dir>', 'Data directory', defaultDataDir)
22
+ .action(async (contentArg, options) => {
23
+ const { handleIngest } = await import('../../mcp/handlers/ingest.js');
24
+ const dataDir = options.dataDir;
25
+ const dbPath = path.join(dataDir, 'lore.lance');
26
+ // Resolve content from argument, file, or stdin
27
+ let content;
28
+ if (options.file) {
29
+ const filePath = options.file.replace(/^~/, process.env.HOME || '~');
30
+ if (!existsSync(filePath)) {
31
+ console.error(`File not found: ${filePath}`);
32
+ process.exit(1);
33
+ }
34
+ content = readFileSync(filePath, 'utf-8');
35
+ }
36
+ else if (contentArg) {
37
+ content = contentArg;
38
+ }
39
+ else if (!process.stdin.isTTY) {
40
+ // Reading from pipe/stdin
41
+ content = readFileSync(0, 'utf-8');
42
+ }
43
+ else {
44
+ console.error('No content provided. Use one of:');
45
+ console.error(' lore ingest "Your content here"');
46
+ console.error(' lore ingest --file ./notes.md');
47
+ console.error(' echo "content" | lore ingest');
48
+ process.exit(1);
49
+ }
50
+ content = content.trim();
51
+ if (!content) {
52
+ console.error('Content is empty.');
53
+ process.exit(1);
54
+ }
55
+ // Derive title from file name or content
56
+ let title = options.title;
57
+ if (!title && options.file) {
58
+ title = path.basename(options.file, path.extname(options.file));
59
+ }
60
+ if (!title) {
61
+ // Use first line or first 60 chars
62
+ const firstLine = content.split('\n')[0].replace(/^#+\s*/, '');
63
+ title = firstLine.length > 60 ? firstLine.slice(0, 57) + '...' : firstLine;
64
+ }
65
+ const tags = options.tags ? options.tags.split(',').map((t) => t.trim()) : [];
66
+ console.log(`\nIngesting: ${title}`);
67
+ console.log(`Project: ${options.project}`);
68
+ if (options.type)
69
+ console.log(`Type: ${options.type}`);
70
+ console.log(`Content: ${content.length} chars`);
71
+ console.log('');
72
+ const result = await handleIngest(dbPath, dataDir, {
73
+ content,
74
+ title,
75
+ project: options.project,
76
+ source_type: options.type,
77
+ tags,
78
+ source_url: options.url,
79
+ source_name: options.name,
80
+ }, {
81
+ hookContext: { mode: 'cli' },
82
+ });
83
+ if (result.deduplicated) {
84
+ console.log('Already exists (identical content). Skipped.');
85
+ return;
86
+ }
87
+ if (result.success) {
88
+ console.log(`Ingested (ID: ${result.id})`);
89
+ if (result.indexed) {
90
+ console.log('Indexed and searchable.');
91
+ }
92
+ else {
93
+ console.log('Saved to disk. Run "lore sync" to index.');
94
+ }
95
+ if (result.synced) {
96
+ console.log('Pushed to git.');
97
+ }
98
+ }
99
+ else {
100
+ console.error('Ingestion failed.');
101
+ process.exit(1);
102
+ }
103
+ });
104
+ }
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ import { registerAskCommand } from './cli/commands/ask.js';
30
30
  import { registerAuthCommands } from './cli/commands/auth.js';
31
31
  import { registerSkillsCommand } from './cli/commands/skills.js';
32
32
  import { registerUpdateCommand } from './cli/commands/update.js';
33
+ import { registerIngestCommand } from './cli/commands/ingest.js';
33
34
  import { getExtensionRegistry, getLoreVersionString } from './extensions/registry.js';
34
35
  import { bridgeConfigToEnv } from './core/config.js';
35
36
  import { expandPath } from './sync/config.js';
@@ -78,6 +79,7 @@ registerAskCommand(program, DEFAULT_DATA_DIR);
78
79
  registerAuthCommands(program);
79
80
  registerSkillsCommand(program);
80
81
  registerUpdateCommand(program, DEFAULT_DATA_DIR);
82
+ registerIngestCommand(program, DEFAULT_DATA_DIR);
81
83
  // Extension system — hidden from top-level help for now
82
84
  const extensionCmd = registerExtensionCommands(program);
83
85
  extensionCmd._hidden = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getlore/cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Research knowledge repository with semantic search, citations, and project lineage tracking",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,6 +8,18 @@ user-invocable: false
8
8
 
9
9
  Lore is a research knowledge repository available via MCP. It stores documents, meeting notes, interviews, and decisions with full citations back to original sources. Use it to ground your work in evidence and preserve important context.
10
10
 
11
+ ## First-Time Setup
12
+
13
+ If Lore is not installed yet, you can set it up for the user. The process requires their input at two points.
14
+
15
+ 1. **Install**: `npm install -g @getlore/cli` (requires Node.js 18+)
16
+ 2. **Ask the user** for their **email address** and their **OpenAI** and **Anthropic API keys**
17
+ 3. **Send OTP**: Run `lore setup --openai-key <key> --anthropic-key <key> --email <email> --data-dir ~/.lore` — this sends a 6-digit code to their email and exits
18
+ 4. **Ask the user** for the **6-digit code** from their email
19
+ 5. **Complete setup**: Re-run the same command with `--code <code>` appended — this verifies and finishes setup
20
+
21
+ After setup, Lore works autonomously. No further user input is needed for searching, ingesting, or syncing.
22
+
11
23
  ## MCP Tools
12
24
 
13
25
  | Tool | Cost | Use For |
@@ -7,6 +7,18 @@ description: Search and ingest knowledge from Lore — a research repository wit
7
7
 
8
8
  Lore is a research knowledge repository available via MCP. It stores documents, meeting notes, interviews, and decisions with full citations back to original sources. Use it to ground your work in evidence and preserve important context.
9
9
 
10
+ ## First-Time Setup
11
+
12
+ If Lore is not installed yet, you can set it up for the user. The process requires their input at two points.
13
+
14
+ 1. **Install**: `npm install -g @getlore/cli` (requires Node.js 18+)
15
+ 2. **Ask the user** for their **email address** and their **OpenAI** and **Anthropic API keys**
16
+ 3. **Send OTP**: Run `lore setup --openai-key <key> --anthropic-key <key> --email <email> --data-dir ~/.lore` — this sends a 6-digit code to their email and exits
17
+ 4. **Ask the user** for the **6-digit code** from their email
18
+ 5. **Complete setup**: Re-run the same command with `--code <code>` appended — this verifies and finishes setup
19
+
20
+ After setup, Lore works autonomously. No further user input is needed for searching, ingesting, or syncing.
21
+
10
22
  ## MCP Tools
11
23
 
12
24
  | Tool | Cost | Use For |
@@ -2,6 +2,18 @@
2
2
 
3
3
  Lore is a research knowledge repository available via MCP. It stores documents, meeting notes, interviews, and decisions with full citations back to original sources. Use it to ground your work in evidence and preserve important context.
4
4
 
5
+ ## First-Time Setup
6
+
7
+ If Lore is not installed yet, you can set it up for the user. The process requires their input at two points.
8
+
9
+ 1. **Install**: `npm install -g @getlore/cli` (requires Node.js 18+)
10
+ 2. **Ask the user** for their **email address** and their **OpenAI** and **Anthropic API keys**
11
+ 3. **Send OTP**: Run `lore setup --openai-key <key> --anthropic-key <key> --email <email> --data-dir ~/.lore` — this sends a 6-digit code to their email and exits
12
+ 4. **Ask the user** for the **6-digit code** from their email
13
+ 5. **Complete setup**: Re-run the same command with `--code <code>` appended — this verifies and finishes setup
14
+
15
+ After setup, Lore works autonomously. No further user input is needed for searching, ingesting, or syncing.
16
+
5
17
  ## MCP Tools
6
18
 
7
19
  | Tool | Cost | Use For |
@@ -2,6 +2,18 @@
2
2
 
3
3
  Lore is a research knowledge repository accessible via MCP (Model Context Protocol). It stores documents with full-text search, semantic search, and citation tracking. Content is deduplicated, embedded for retrieval, and organized by project.
4
4
 
5
+ ## First-Time Setup
6
+
7
+ If Lore is not installed yet, you can set it up for the user. The process requires their input at two points.
8
+
9
+ 1. **Install**: `npm install -g @getlore/cli` (requires Node.js 18+)
10
+ 2. **Ask the user** for their **email address** and their **OpenAI** and **Anthropic API keys**
11
+ 3. **Send OTP**: Run `lore setup --openai-key <key> --anthropic-key <key> --email <email> --data-dir ~/.lore` — this sends a 6-digit code to their email and exits
12
+ 4. **Ask the user** for the **6-digit code** from their email
13
+ 5. **Complete setup**: Re-run the same command with `--code <code>` appended — this verifies and finishes setup
14
+
15
+ After setup, Lore works autonomously. No further user input is needed for searching, ingesting, or syncing.
16
+
5
17
  ## Core Concepts
6
18
 
7
19
  - **Sources**: Full documents (meeting notes, interviews, Slack threads, specs, etc.)