greptor 0.5.1 → 0.7.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 (126) hide show
  1. package/README.md +179 -85
  2. package/dist/cli/app.d.ts +3 -0
  3. package/dist/cli/app.d.ts.map +1 -0
  4. package/dist/cli/app.js +28 -0
  5. package/dist/cli/app.js.map +1 -0
  6. package/dist/cli/commands/generate/index.d.ts +2 -0
  7. package/dist/cli/commands/generate/index.d.ts.map +1 -0
  8. package/dist/cli/commands/generate/index.js +13 -0
  9. package/dist/cli/commands/generate/index.js.map +1 -0
  10. package/dist/cli/commands/generate/skills/command.d.ts +2 -0
  11. package/dist/cli/commands/generate/skills/command.d.ts.map +1 -0
  12. package/dist/cli/commands/generate/skills/command.js +134 -0
  13. package/dist/cli/commands/generate/skills/command.js.map +1 -0
  14. package/dist/cli/commands/generate/skills/generator.d.ts +8 -0
  15. package/dist/cli/commands/generate/skills/generator.d.ts.map +1 -0
  16. package/dist/cli/commands/generate/skills/generator.js +151 -0
  17. package/dist/cli/commands/generate/skills/generator.js.map +1 -0
  18. package/dist/cli/commands/generate/skills/prompt-template.d.ts +16 -0
  19. package/dist/cli/commands/generate/skills/prompt-template.d.ts.map +1 -0
  20. package/dist/cli/commands/generate/skills/prompt-template.js +247 -0
  21. package/dist/cli/commands/generate/skills/prompt-template.js.map +1 -0
  22. package/dist/cli/commands/generate/skills/types.d.ts +16 -0
  23. package/dist/cli/commands/generate/skills/types.d.ts.map +1 -0
  24. package/dist/cli/commands/generate/skills/types.js.map +1 -0
  25. package/dist/cli/commands/generate/tags/command.d.ts +2 -0
  26. package/dist/cli/commands/generate/tags/command.d.ts.map +1 -0
  27. package/dist/cli/commands/generate/tags/command.js +113 -0
  28. package/dist/cli/commands/generate/tags/command.js.map +1 -0
  29. package/dist/cli/commands/generate/tags/generator.d.ts +3 -0
  30. package/dist/cli/commands/generate/tags/generator.d.ts.map +1 -0
  31. package/dist/cli/commands/generate/tags/generator.js +44 -0
  32. package/dist/cli/commands/generate/tags/generator.js.map +1 -0
  33. package/dist/cli/commands/login.d.ts +2 -0
  34. package/dist/cli/commands/login.d.ts.map +1 -0
  35. package/dist/cli/commands/login.js +108 -0
  36. package/dist/cli/commands/login.js.map +1 -0
  37. package/dist/cli/types.d.ts +24 -0
  38. package/dist/cli/types.d.ts.map +1 -0
  39. package/dist/{storage → cli}/types.js.map +1 -1
  40. package/dist/cli/utils/auth.d.ts +5 -0
  41. package/dist/cli/utils/auth.d.ts.map +1 -0
  42. package/dist/cli/utils/auth.js +26 -0
  43. package/dist/cli/utils/auth.js.map +1 -0
  44. package/dist/index.d.ts +1 -5
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +1 -2
  47. package/dist/index.js.map +1 -1
  48. package/dist/{tag-schema/types.d.ts → lib/config.d.ts} +10 -1
  49. package/dist/lib/config.d.ts.map +1 -0
  50. package/dist/lib/config.js +69 -0
  51. package/dist/lib/config.js.map +1 -0
  52. package/dist/lib/greptor.d.ts +11 -0
  53. package/dist/lib/greptor.d.ts.map +1 -0
  54. package/dist/lib/greptor.js +88 -0
  55. package/dist/lib/greptor.js.map +1 -0
  56. package/dist/lib/index.d.ts +7 -0
  57. package/dist/lib/index.d.ts.map +1 -0
  58. package/dist/lib/index.js +4 -0
  59. package/dist/lib/index.js.map +1 -0
  60. package/dist/lib/llm/llm-factory.d.ts +7 -0
  61. package/dist/lib/llm/llm-factory.d.ts.map +1 -0
  62. package/dist/lib/llm/llm-factory.js +52 -0
  63. package/dist/lib/llm/llm-factory.js.map +1 -0
  64. package/dist/{processing → lib/processing}/processor.d.ts +11 -7
  65. package/dist/lib/processing/processor.d.ts.map +1 -0
  66. package/dist/lib/processing/processor.js +230 -0
  67. package/dist/lib/processing/processor.js.map +1 -0
  68. package/dist/{storage → lib/storage}/file-storage.d.ts +5 -2
  69. package/dist/lib/storage/file-storage.d.ts.map +1 -0
  70. package/dist/{storage → lib/storage}/file-storage.js +47 -13
  71. package/dist/lib/storage/file-storage.js.map +1 -0
  72. package/dist/lib/storage/index.d.ts.map +1 -0
  73. package/dist/lib/storage/index.js.map +1 -0
  74. package/dist/lib/storage/types.d.ts.map +1 -0
  75. package/dist/lib/storage/types.js +2 -0
  76. package/dist/lib/storage/types.js.map +1 -0
  77. package/dist/lib/types.d.ts +91 -0
  78. package/dist/lib/types.d.ts.map +1 -0
  79. package/dist/lib/types.js +2 -0
  80. package/dist/lib/types.js.map +1 -0
  81. package/dist/lib/utils/file.d.ts.map +1 -0
  82. package/dist/lib/utils/file.js.map +1 -0
  83. package/package.json +26 -2
  84. package/dist/greptor.d.ts +0 -7
  85. package/dist/greptor.d.ts.map +0 -1
  86. package/dist/greptor.js +0 -99
  87. package/dist/greptor.js.map +0 -1
  88. package/dist/processing/processor.d.ts.map +0 -1
  89. package/dist/processing/processor.js +0 -260
  90. package/dist/processing/processor.js.map +0 -1
  91. package/dist/skills/skill-generator.d.ts +0 -16
  92. package/dist/skills/skill-generator.d.ts.map +0 -1
  93. package/dist/skills/skill-generator.js +0 -347
  94. package/dist/skills/skill-generator.js.map +0 -1
  95. package/dist/storage/file-storage.d.ts.map +0 -1
  96. package/dist/storage/file-storage.js.map +0 -1
  97. package/dist/storage/index.d.ts.map +0 -1
  98. package/dist/storage/index.js.map +0 -1
  99. package/dist/storage/types.d.ts.map +0 -1
  100. package/dist/tag-schema/generate.d.ts +0 -4
  101. package/dist/tag-schema/generate.d.ts.map +0 -1
  102. package/dist/tag-schema/generate.js +0 -44
  103. package/dist/tag-schema/generate.js.map +0 -1
  104. package/dist/tag-schema/initialize.d.ts +0 -5
  105. package/dist/tag-schema/initialize.d.ts.map +0 -1
  106. package/dist/tag-schema/initialize.js +0 -28
  107. package/dist/tag-schema/initialize.js.map +0 -1
  108. package/dist/tag-schema/types.d.ts.map +0 -1
  109. package/dist/tag-schema/types.js +0 -22
  110. package/dist/tag-schema/types.js.map +0 -1
  111. package/dist/types.d.ts +0 -95
  112. package/dist/types.d.ts.map +0 -1
  113. package/dist/types.js.map +0 -1
  114. package/dist/utils/file.d.ts.map +0 -1
  115. package/dist/utils/file.js.map +0 -1
  116. package/dist/utils/hash.d.ts +0 -2
  117. package/dist/utils/hash.d.ts.map +0 -1
  118. package/dist/utils/hash.js +0 -5
  119. package/dist/utils/hash.js.map +0 -1
  120. /package/dist/{storage → cli/commands/generate/skills}/types.js +0 -0
  121. /package/dist/{types.js → cli/types.js} +0 -0
  122. /package/dist/{storage → lib/storage}/index.d.ts +0 -0
  123. /package/dist/{storage → lib/storage}/index.js +0 -0
  124. /package/dist/{storage → lib/storage}/types.d.ts +0 -0
  125. /package/dist/{utils → lib/utils}/file.d.ts +0 -0
  126. /package/dist/{utils → lib/utils}/file.js +0 -0
package/README.md CHANGED
@@ -34,23 +34,71 @@ bun add greptor
34
34
 
35
35
  ### Step 2: Initialize
36
36
 
37
- Create a Greptor instance with your base directory, topic, and AI SDK language model.
37
+ Create a Greptor instance with your base path, topic, and model config.
38
38
 
39
39
  ```typescript
40
40
  import { createGreptor } from 'greptor';
41
- import { openai } from "@ai-sdk/openai";
42
41
 
43
42
  // Create Greptor instance
44
43
  const greptor = await createGreptor({
45
- baseDir: './projects/investing',
44
+ basePath: './projects/investing/content',
46
45
  topic: 'Investing, stock market, financial, and macroeconomics',
47
- model: openai("gpt-5-mini"),
46
+ tagSchema: YOUR_TAG_SCHEMA, // Required. See "Tag Schemas" below.
47
+ model: {
48
+ provider: "@ai-sdk/openai",
49
+ model: "gpt-5-mini",
50
+ },
48
51
  });
52
+
53
+ // Start background processing workers
54
+ await greptor.start();
49
55
  ```
50
56
 
51
- - **`baseDir`**: Home directory for your project where all data will be stored.
57
+ - **`basePath`**: Base directory where data will be stored.
52
58
  - **`topic`**: Helps Greptor understand your data better and generate a relevant tag schema.
53
- - **`model`**: A `LanguageModel` instance from [Vercel AI SDK](https://ai-sdk.dev).
59
+ - **`tagSchema`**: Required. Define your tag fields (or generate them with `greptor generate tags`).
60
+ - **`model`**: A config object with `provider`, `model`, and optional `options` for the [Vercel AI SDK](https://ai-sdk.dev).
61
+
62
+ Greptor will automatically create and manage the following structure in your basePath:
63
+ - `raw/` - immediate raw content writes
64
+ - `processed/` - enriched/processed content from background workers
65
+
66
+ #### Model Config
67
+
68
+ Greptor uses an LLM (via [Greptor](https://github.com/greptorio/greptor)) to process content. You'll need to:
69
+
70
+ 1. **Choose a provider** from the [AI SDK ecosystem](https://sdk.vercel.ai/providers/ai-sdk-providers):
71
+ - `@ai-sdk/openai` - OpenAI (GPT-4, GPT-4o, etc.)
72
+ - `@ai-sdk/anthropic` - Anthropic (Claude)
73
+ - `@ai-sdk/groq` - Groq (fast inference)
74
+ - `@ai-sdk/openai-compatible` - OpenAI-compatible endpoints (NVIDIA NIM, OpenRouter, etc.)
75
+ - And [many more](https://sdk.vercel.ai/providers/ai-sdk-providers)...
76
+
77
+ 2. **Get an API key** from your provider and set it as an environment variable:
78
+ ```bash
79
+ export OPENAI_API_KEY="sk-..."
80
+ # or add to ~/.bashrc, ~/.zshrc, etc.
81
+ ```
82
+
83
+ 3. **Provide it in the model config** when creating Greptor.
84
+ ```typescript
85
+ const greptor = await createGreptor({
86
+ basePath: './projects/investing/content',
87
+ topic: 'Investing, stock market, financial, and macroeconomics',
88
+ tagSchema: YOUR_TAG_SCHEMA,
89
+ model: {
90
+ provider: "@ai-sdk/openai-compatible",
91
+ model: "z-ai/glm4.7",
92
+ name: "nvidia",
93
+ options: {
94
+ baseURL: "https://integrate.api.nvidia.com/v1",
95
+ apiKey: process.env.NVIDIA_API_KEY,
96
+ },
97
+ },
98
+ });
99
+
100
+ await greptor.start();
101
+ ```
54
102
 
55
103
  ### Step 3: Start Feeding Documents
56
104
 
@@ -87,52 +135,58 @@ await greptor.eat({
87
135
 
88
136
  ### Step 4: Wait for Background Processing
89
137
 
90
- Greptor will write your input to a raw Markdown file immediately, then run background enrichment (LLM cleaning + chunking + tagging) and write a processed Markdown file. You can grep the raw files right away, and the processed files will appear shortly after.
138
+ Greptor writes your input to a raw Markdown file immediately. After you call `await greptor.start()`, background workers run enrichment (LLM cleaning + chunking + tagging) and write a processed Markdown file. You can grep the raw files right away, and the processed files will appear shortly after.
91
139
 
92
- ### Step 5: Generate a Claude Code Skill
140
+ ### Step 5: Generate a Skill (CLI)
93
141
 
94
- ```typescript
95
- await greptor.createSkill(['youtube', 'reddit']);
142
+ Navigate to your workspace directory and run:
143
+
144
+ ```bash
145
+ greptor generate skills
96
146
  ```
97
147
 
98
- This generates a Claude Code skill that instructs agents on how to search your indexed content effectively.
148
+ The CLI will prompt you to pick an agent type (`claude code`, `codex`, or `opencode`)
149
+
150
+ Then it writes the appropriate skill file for your chosen agent.
99
151
 
100
152
  The skill is customized for the sources you provide and includes search tips based on the tag schema. You can always customize it manually further for better results.
101
153
 
102
154
  ### Step 6: Run the Agent
103
155
 
104
- By this point, you should have the following structure in your `baseDir`:
156
+ By this point, you should have the following structure in your `basePath`:
105
157
 
106
158
  ```
107
- ./projects/investing/
159
+ ./projects/investing/content/
108
160
  .claude/
109
161
  skills/
110
162
  search-youtube-reddit/
111
163
  SKILL.md
112
- content/
113
- raw/
114
- youtube/
115
- JosephCarlsonShow/
116
- 2025-12/
117
- 2025-12-01-Top-Five-AI-Stocks-Im-Buying-Now.md
118
- reddit/
119
- investing/
120
- 2025-12/
121
- 2025-12-03-Tesla-reports-418227-deliveries-for-the-fourth-quarter-down-16.md
122
- processed/
123
- youtube/
124
- JosephCarlsonShow/
125
- 2025-12/
126
- 2025-12-01-Top-Five-AI-Stocks-Im-Buying-Now.md
127
- reddit/
128
- investing/
129
- 2025-12/
130
- 2025-12-03-Tesla-reports-418227-deliveries-for-the-fourth-quarter-down-16.md
164
+ raw/
165
+ youtube/
166
+ JosephCarlsonShow/
167
+ 2025-12/
168
+ 2025-12-01-Top-Five-AI-Stocks-Im-Buying-Now.md
169
+ reddit/
170
+ investing/
171
+ 2025-12/
172
+ 2025-12-03-Tesla-reports-418227-deliveries-for-the-fourth-quarter-down-16.md
173
+ processed/
174
+ youtube/
175
+ JosephCarlsonShow/
176
+ 2025-12/
177
+ 2025-12-01-Top-Five-AI-Stocks-Im-Buying-Now.md
178
+ reddit/
179
+ investing/
180
+ 2025-12/
181
+ 2025-12-03-Tesla-reports-418227-deliveries-for-the-fourth-quarter-down-16.md
131
182
  ```
132
183
 
133
- Now run Claude Code (or any other agent) in this folder and ask questions about your data or perform research tasks!
184
+ If you chose Codex or OpenCode, the skill file will be written to:
185
+
186
+ - `.codex/skills/search-*.md` (Codex)
187
+ - `.opencode/skills/search-*.md` (OpenCode)
134
188
 
135
- **Note**: For other agents, you may need to adapt the skill accordingly.
189
+ Now run your chosen agent in this folder and ask questions about your data or perform research tasks!
136
190
 
137
191
  **For better results**:
138
192
  1. Connect MCP servers like Yahoo Finance or other relevant financial/stock market MCP servers for up-to-date information.
@@ -296,86 +350,124 @@ rg -n -C 6 "narrative=ev_transition" content/processed/ | rg "sentiment=bearish"
296
350
 
297
351
  ## Configuration
298
352
 
299
- ### Event Hooks
353
+ ### Custom Processing Prompts
300
354
 
301
- Greptor provides optional hooks to monitor the ingestion and processing pipeline. These are useful for logging, metrics, progress tracking, or building custom UIs.
355
+ You can override the default processing prompt for specific sources to tailor how content is processed:
302
356
 
303
357
  ```typescript
304
358
  const greptor = await createGreptor({
305
- baseDir: './projects/investing',
359
+ basePath: './projects/investing/content',
306
360
  topic: 'Investing, stock market, financial, and macroeconomics',
307
- model: openai("gpt-5-mini"),
308
- hooks: {
309
- onProcessingRunStarted: ({ documentsToProcess, totalDocuments }) => {
310
- console.log(`📋 Starting processing run: ${documentsToProcess} documents queued`);
311
- },
312
-
313
- onDocumentProcessingStarted: ({ source, publisher, label, successful, failed, queueSize }) => {
314
- const processed = successful + failed;
315
- console.log(`[${processed}/${queueSize}] Processing: ${source}/${publisher}/${label}`);
316
- },
361
+ tagSchema: YOUR_TAG_SCHEMA,
362
+ model: {
363
+ provider: "@ai-sdk/openai",
364
+ model: "gpt-5-mini",
365
+ },
366
+ customProcessingPrompts: {
367
+ // Custom prompt for Twitter/X content
368
+ 'twitter': `
369
+ # INSTRUCTIONS
370
+ Process this Twitter/X content for investment research. Focus on:
371
+ - Investment signals, predictions, or analysis
372
+ - Key metrics and numbers mentioned
373
+ - Influencer sentiment and conviction level
374
+
375
+ # CONTENT TO PROCESS:
376
+ {CONTENT}
377
+ `,
317
378
 
318
- onDocumentProcessingCompleted: ({
319
- success,
320
- label,
321
- successful,
322
- failed,
323
- queueSize,
324
- elapsedMs,
325
- inputTokens,
326
- outputTokens,
327
- totalTokens
328
- }) => {
329
- const processed = successful + failed;
330
- const status = success ? '✓' : '✗';
331
- console.log(
332
- `[${processed}/${queueSize}] ${status} ${label} (${elapsedMs}ms, ${totalTokens} tokens)`
333
- );
334
- },
379
+ // Custom prompt for SEC filings
380
+ 'sec_filing': `
381
+ # INSTRUCTIONS
382
+ Process this SEC filing with extreme precision:
383
+ - Preserve all financial figures, dates, and legal language exactly
384
+ - Extract key financial metrics and risk factors
385
+ - Maintain formal, factual tone throughout
386
+
387
+ # CONTENT TO PROCESS:
388
+ {CONTENT}
389
+ `,
335
390
 
336
- onProcessingRunCompleted: ({ successful, failed, elapsedMs }) => {
337
- const total = successful + failed;
338
- console.log(
339
- `✨ Run complete: ${successful}/${total} succeeded in ${(elapsedMs / 1000).toFixed(1)}s`
340
- );
341
- if (failed > 0) {
342
- console.log(`⚠️ ${failed} documents failed`);
343
- }
391
+ // Custom prompt for earnings transcripts
392
+ 'earnings': `
393
+ # INSTRUCTIONS
394
+ Process this earnings call transcript:
395
+ - Extract forward-looking statements and guidance
396
+ - Preserve exact numbers, percentages, and ranges
397
+ - Capture management sentiment and key Q&A points
398
+
399
+ # CONTENT TO PROCESS:
400
+ {CONTENT}
401
+ `,
402
+ },
403
+ });
404
+
405
+ await greptor.start();
406
+ ```
407
+
408
+ **Usage notes**:
409
+ - Use `{CONTENT}` as a placeholder where the raw content will be inserted
410
+ - Each custom prompt should include the placeholder exactly once
411
+ - If no custom prompt is defined for a source, Greptor falls back to the default processing prompt
412
+ - Custom prompts are matched against the document's `source` field (e.g., `youtube`, `reddit`, `twitter`)
413
+
414
+ ### Event Hooks
415
+
416
+ Greptor provides optional hooks to monitor document processing. These are useful for logging, metrics, progress tracking, or building custom UIs.
417
+
418
+ ```typescript
419
+ const greptor = await createGreptor({
420
+ basePath: './projects/investing/content',
421
+ topic: 'Investing, stock market, financial, and macroeconomics',
422
+ tagSchema: YOUR_TAG_SCHEMA,
423
+ model: {
424
+ provider: "@ai-sdk/openai",
425
+ model: "gpt-5-mini",
426
+ },
427
+ hooks: {
428
+ onDocumentProcessingStarted: ({ source, publisher, label, documentsCount }) => {
429
+ const count = documentsCount[source] || { fetched: 0, processed: 0 };
430
+ console.log(`Processing: ${source}/${publisher}/${label} (${count.fetched} fetched, ${count.processed} processed)`);
344
431
  },
345
-
346
- onError: ({ error, context }) => {
347
- if (context?.label) {
348
- console.error(`❌ Error processing ${context.label}: ${error.message}`);
432
+
433
+ onDocumentProcessingCompleted: (event) => {
434
+ if (event.success) {
435
+ const { source, publisher, label, documentsCount, elapsedMs, totalTokens } = event;
436
+ const count = documentsCount[source] || { fetched: 0, processed: 0 };
437
+ console.log(`✓ Completed: ${source}/${publisher}/${label} (${elapsedMs}ms, ${totalTokens} tokens, ${count.processed}/${count.fetched} processed)`);
349
438
  } else {
350
- console.error(`❌ Error: ${error.message}`);
439
+ const { source, publisher, label, error } = event;
440
+ console.error(`✗ Failed: ${source}/${publisher}/${label} - ${error}`);
351
441
  }
352
442
  },
353
443
  },
354
444
  });
445
+
446
+ await greptor.start();
355
447
  ```
356
448
 
357
449
  #### Available Hooks
358
450
 
359
451
  | Hook | When Called | Event Data |
360
452
  |------|-------------|------------|
361
- | `onProcessingRunStarted` | When background workers detect queued documents | `documentsToProcess`, `totalDocuments` |
362
- | `onDocumentProcessingStarted` | Before processing each document | `source`, `publisher`, `label`, `successful`, `failed`, `queueSize` |
363
- | `onDocumentProcessingCompleted` | After processing succeeds or fails | `success`, `source`, `publisher`, `label`, `successful`, `failed`, `queueSize`, `elapsedMs`, `inputTokens`, `outputTokens`, `totalTokens` |
364
- | `onProcessingRunCompleted` | When all queued documents are processed | `successful`, `failed`, `elapsedMs` |
365
- | `onError` | When errors occur during processing or ingestion | `error`, `context` (with optional `source`, `publisher`, `label`, `ref`) |
453
+ | `onDocumentProcessingStarted` | Before processing each document | `source`, `publisher?`, `label`, `documentsCount: SourceCounts` |
454
+ | `onDocumentProcessingCompleted` | After processing succeeds or fails | Union type:<br/>• **Success**: `success: true`, `source`, `publisher?`, `label`, `documentsCount`, `elapsedMs`, `inputTokens`, `outputTokens`, `totalTokens`<br/>• **Failure**: `success: false`, `error: string`, `source`, `publisher?`, `label` |
366
455
 
367
456
 
368
457
  ## Tag Schemas
369
458
 
370
- If you don't provide a schema, Greptor can initialize one for your topic. However, for better results, provide a custom tag schema.
459
+ Greptor requires a tag schema. For best results, provide a custom tag schema (or generate one with `greptor generate tags`).
371
460
 
372
461
  Here's a comprehensive example for investment research:
373
462
 
374
463
  ```typescript
375
464
  const greptor = await createGreptor({
376
- baseDir: './projects/investing',
465
+ basePath: './projects/investing/content',
377
466
  topic: 'Investing, stock market, financial, and macroeconomics',
378
- model: openai("gpt-5-mini"),
467
+ model: {
468
+ provider: "@ai-sdk/openai",
469
+ model: "gpt-5-mini",
470
+ },
379
471
  tagSchema: [
380
472
  {
381
473
  name: 'company',
@@ -446,6 +538,8 @@ const greptor = await createGreptor({
446
538
  },
447
539
  ],
448
540
  });
541
+
542
+ await greptor.start();
449
543
  ```
450
544
 
451
545
  ## License
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare const app: import("@stricli/core").Application<import("@stricli/core").CommandContext>;
3
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/cli/app.ts"],"names":[],"mappings":";AAgBA,eAAO,MAAM,GAAG,6EAKd,CAAC"}
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import { buildApplication, buildRouteMap } from "@stricli/core";
3
+ import { run } from "@stricli/core";
4
+ import { generateRoutes } from "./commands/generate/index.js";
5
+ import { loginCommand } from "./commands/login.js";
6
+ const routes = buildRouteMap({
7
+ routes: {
8
+ login: loginCommand,
9
+ generate: generateRoutes,
10
+ },
11
+ docs: {
12
+ brief: "Greptor CLI - Transform unstructured text into grep-friendly data",
13
+ },
14
+ });
15
+ export const app = buildApplication(routes, {
16
+ name: "greptor",
17
+ versionInfo: {
18
+ currentVersion: "0.6.0",
19
+ },
20
+ });
21
+ await run(app, process.argv.slice(2), {
22
+ process: {
23
+ stdout: process.stdout,
24
+ stderr: process.stderr,
25
+ exitCode: process.exitCode ?? null,
26
+ },
27
+ });
28
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/cli/app.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,MAAM,GAAG,aAAa,CAAC;IAC5B,MAAM,EAAE;QACP,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,cAAc;KACxB;IACD,IAAI,EAAE;QACL,KAAK,EAAE,mEAAmE;KAC1E;CACD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,EAAE;IAC3C,IAAI,EAAE,SAAS;IACf,WAAW,EAAE;QACZ,cAAc,EAAE,OAAO;KACvB;CACD,CAAC,CAAC;AAEH,MAAM,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;IACrC,OAAO,EAAE;QACR,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;KAClC;CACD,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const generateRoutes: import("@stricli/core").RouteMap<import("@stricli/core").CommandContext>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/generate/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,0EAQzB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { buildRouteMap } from "@stricli/core";
2
+ import { skillsCommand } from "./skills/command.js";
3
+ import { tagsCommand } from "./tags/command.js";
4
+ export const generateRoutes = buildRouteMap({
5
+ routes: {
6
+ tags: tagsCommand,
7
+ skills: skillsCommand,
8
+ },
9
+ docs: {
10
+ brief: "Generate tags or skills",
11
+ },
12
+ });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cli/commands/generate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;IAC3C,MAAM,EAAE;QACP,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,aAAa;KACrB;IACD,IAAI,EAAE;QACL,KAAK,EAAE,yBAAyB;KAChC;CACD,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const skillsCommand: import("@stricli/core").Command<import("@stricli/core").CommandContext>;
2
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/generate/skills/command.ts"],"names":[],"mappings":"AAgKA,eAAO,MAAM,aAAa,yEASxB,CAAC"}
@@ -0,0 +1,134 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { cancel, intro, isCancel, log, outro, select, spinner, } from "@clack/prompts";
4
+ import { buildCommand } from "@stricli/core";
5
+ import { findConfigFile, readConfig } from "../../../../lib/config.js";
6
+ import { generateSkill } from "./generator.js";
7
+ import { PROCESSED_DIR_NAME, RAW_DIR_NAME, } from "../../../../lib/storage/file-storage.js";
8
+ async function findGreptorPaths(workspacePath) {
9
+ let rawPath;
10
+ let processedPath;
11
+ const configPath = await findConfigFile(".");
12
+ const queue = [workspacePath];
13
+ const visited = new Set();
14
+ while (queue.length > 0) {
15
+ if (rawPath && processedPath) {
16
+ break;
17
+ }
18
+ const current = queue.shift();
19
+ if (!current || visited.has(current)) {
20
+ continue;
21
+ }
22
+ visited.add(current);
23
+ try {
24
+ const entries = await readdir(current, { withFileTypes: true });
25
+ for (const entry of entries) {
26
+ if (entry.isDirectory()) {
27
+ const fullPath = path.join(current, entry.name);
28
+ if (entry.name === RAW_DIR_NAME && !rawPath) {
29
+ rawPath = fullPath;
30
+ }
31
+ else if (entry.name === PROCESSED_DIR_NAME && !processedPath) {
32
+ processedPath = fullPath;
33
+ }
34
+ else {
35
+ queue.push(fullPath);
36
+ }
37
+ }
38
+ }
39
+ }
40
+ catch { }
41
+ }
42
+ return {
43
+ configPath: configPath,
44
+ rawContentPath: rawPath,
45
+ processedContentPath: processedPath,
46
+ };
47
+ }
48
+ async function findSources(processedPath) {
49
+ const entries = await readdir(processedPath, { withFileTypes: true });
50
+ const sources = [];
51
+ for (const entry of entries) {
52
+ if (entry.isDirectory()) {
53
+ sources.push(entry.name);
54
+ }
55
+ }
56
+ return sources;
57
+ }
58
+ async function generateSkillsCommand() {
59
+ console.clear();
60
+ intro("greptor generate skills");
61
+ const s = spinner();
62
+ try {
63
+ // Step 1: Find greptor content directories for the skill
64
+ s.start("Scanning workspace for greptor paths...");
65
+ const greptorPaths = await findGreptorPaths(".");
66
+ s.stop();
67
+ if (!greptorPaths.rawContentPath ||
68
+ !greptorPaths.processedContentPath ||
69
+ !greptorPaths.configPath) {
70
+ cancel("The current directory doesn't contain greptor content.");
71
+ return;
72
+ }
73
+ // Step 2: Select agent type
74
+ const agent = await select({
75
+ message: "Select agent type:",
76
+ options: [
77
+ {
78
+ value: "claude-code",
79
+ label: "Claude Code",
80
+ hint: "Anthropic Claude Code agent",
81
+ },
82
+ { value: "codex", label: "Codex", hint: "OpenAI Codex CLI agent" },
83
+ { value: "opencode", label: "OpenCode", hint: "OpenCode agent" },
84
+ ],
85
+ });
86
+ if (isCancel(agent)) {
87
+ cancel("Cancelled");
88
+ return;
89
+ }
90
+ // Step 4: Load config.yaml from workspace
91
+ s.start("Loading config.yaml...");
92
+ const config = await readConfig(greptorPaths.configPath);
93
+ if (!config?.domain || !config.tagSchema || config.tagSchema.length === 0) {
94
+ s.stop("Invalid config");
95
+ cancel("Invalid configuration");
96
+ return;
97
+ }
98
+ s.stop("Config loaded");
99
+ // Step 5: Find content sources from the processed content
100
+ s.start("Finding content sources for the skill...");
101
+ const sources = await findSources(greptorPaths.processedContentPath);
102
+ s.stop(`Found ${sources.length} sources`);
103
+ // Step 6: Generate skills
104
+ s.start("Generating skills...");
105
+ const { skillPath } = await generateSkill({
106
+ domain: config.domain,
107
+ sources,
108
+ basePath: ".",
109
+ greptorPaths: greptorPaths,
110
+ tagsSchema: config.tagSchema,
111
+ agent,
112
+ });
113
+ const relativePath = path.relative(process.cwd(), skillPath);
114
+ s.stop(`Skill file generated at ${relativePath}`);
115
+ outro("Skill generation complete!");
116
+ }
117
+ catch (error) {
118
+ s.stop("Error");
119
+ const message = error instanceof Error ? error.message : String(error);
120
+ log.error(`Failed to generate skill: ${message}`);
121
+ cancel("Generation failed");
122
+ }
123
+ }
124
+ export const skillsCommand = buildCommand({
125
+ func: generateSkillsCommand,
126
+ parameters: {
127
+ flags: {},
128
+ positional: { kind: "tuple", parameters: [] },
129
+ },
130
+ docs: {
131
+ brief: "Generate skills file for AI coding agents",
132
+ },
133
+ });
134
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/cli/commands/generate/skills/command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { SkillGeneratorOptions } from "./types.js";
2
+ /**
3
+ * Generate a skill file for the give options and agent type.
4
+ */
5
+ export declare function generateSkill(options: SkillGeneratorOptions): Promise<{
6
+ skillPath: string;
7
+ }>;
8
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/generate/skills/generator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AA2LxD;;GAEG;AACH,wBAAsB,aAAa,CAClC,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAWhC"}