prelude-context 1.0.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 (94) hide show
  1. package/README.md +354 -0
  2. package/dist/bin/prelude.d.ts +3 -0
  3. package/dist/bin/prelude.d.ts.map +1 -0
  4. package/dist/bin/prelude.js +35 -0
  5. package/dist/bin/prelude.js.map +1 -0
  6. package/dist/src/commands/decision.d.ts +3 -0
  7. package/dist/src/commands/decision.d.ts.map +1 -0
  8. package/dist/src/commands/decision.js +74 -0
  9. package/dist/src/commands/decision.js.map +1 -0
  10. package/dist/src/commands/export.d.ts +3 -0
  11. package/dist/src/commands/export.d.ts.map +1 -0
  12. package/dist/src/commands/export.js +132 -0
  13. package/dist/src/commands/export.js.map +1 -0
  14. package/dist/src/commands/init.d.ts +3 -0
  15. package/dist/src/commands/init.d.ts.map +1 -0
  16. package/dist/src/commands/init.js +80 -0
  17. package/dist/src/commands/init.js.map +1 -0
  18. package/dist/src/commands/share.d.ts +3 -0
  19. package/dist/src/commands/share.d.ts.map +1 -0
  20. package/dist/src/commands/share.js +133 -0
  21. package/dist/src/commands/share.js.map +1 -0
  22. package/dist/src/commands/watch.d.ts +3 -0
  23. package/dist/src/commands/watch.d.ts.map +1 -0
  24. package/dist/src/commands/watch.js +58 -0
  25. package/dist/src/commands/watch.js.map +1 -0
  26. package/dist/src/constants.d.ts +16 -0
  27. package/dist/src/constants.d.ts.map +1 -0
  28. package/dist/src/constants.js +49 -0
  29. package/dist/src/constants.js.map +1 -0
  30. package/dist/src/core/exporter.d.ts +4 -0
  31. package/dist/src/core/exporter.d.ts.map +1 -0
  32. package/dist/src/core/exporter.js +196 -0
  33. package/dist/src/core/exporter.js.map +1 -0
  34. package/dist/src/core/infer.d.ts +6 -0
  35. package/dist/src/core/infer.d.ts.map +1 -0
  36. package/dist/src/core/infer.js +900 -0
  37. package/dist/src/core/infer.js.map +1 -0
  38. package/dist/src/core/updater.d.ts +8 -0
  39. package/dist/src/core/updater.d.ts.map +1 -0
  40. package/dist/src/core/updater.js +120 -0
  41. package/dist/src/core/updater.js.map +1 -0
  42. package/dist/src/core/watcher.d.ts +15 -0
  43. package/dist/src/core/watcher.d.ts.map +1 -0
  44. package/dist/src/core/watcher.js +119 -0
  45. package/dist/src/core/watcher.js.map +1 -0
  46. package/dist/src/schema/architecture.d.ts +75 -0
  47. package/dist/src/schema/architecture.d.ts.map +1 -0
  48. package/dist/src/schema/architecture.js +24 -0
  49. package/dist/src/schema/architecture.js.map +1 -0
  50. package/dist/src/schema/constraints.d.ts +146 -0
  51. package/dist/src/schema/constraints.d.ts.map +1 -0
  52. package/dist/src/schema/constraints.js +39 -0
  53. package/dist/src/schema/constraints.js.map +1 -0
  54. package/dist/src/schema/decisions.d.ts +122 -0
  55. package/dist/src/schema/decisions.d.ts.map +1 -0
  56. package/dist/src/schema/decisions.js +23 -0
  57. package/dist/src/schema/decisions.js.map +1 -0
  58. package/dist/src/schema/index.d.ts +7 -0
  59. package/dist/src/schema/index.d.ts.map +1 -0
  60. package/dist/src/schema/index.js +7 -0
  61. package/dist/src/schema/index.js.map +1 -0
  62. package/dist/src/schema/project.d.ts +69 -0
  63. package/dist/src/schema/project.d.ts.map +1 -0
  64. package/dist/src/schema/project.js +24 -0
  65. package/dist/src/schema/project.js.map +1 -0
  66. package/dist/src/schema/session.d.ts +210 -0
  67. package/dist/src/schema/session.d.ts.map +1 -0
  68. package/dist/src/schema/session.js +26 -0
  69. package/dist/src/schema/session.js.map +1 -0
  70. package/dist/src/schema/stack.d.ts +58 -0
  71. package/dist/src/schema/stack.d.ts.map +1 -0
  72. package/dist/src/schema/stack.js +23 -0
  73. package/dist/src/schema/stack.js.map +1 -0
  74. package/dist/src/utils/fs.d.ts +10 -0
  75. package/dist/src/utils/fs.d.ts.map +1 -0
  76. package/dist/src/utils/fs.js +63 -0
  77. package/dist/src/utils/fs.js.map +1 -0
  78. package/dist/src/utils/log.d.ts +20 -0
  79. package/dist/src/utils/log.d.ts.map +1 -0
  80. package/dist/src/utils/log.js +45 -0
  81. package/dist/src/utils/log.js.map +1 -0
  82. package/dist/src/utils/time.d.ts +5 -0
  83. package/dist/src/utils/time.d.ts.map +1 -0
  84. package/dist/src/utils/time.js +33 -0
  85. package/dist/src/utils/time.js.map +1 -0
  86. package/package.json +64 -0
  87. package/schemas/architecture.schema.json +98 -0
  88. package/schemas/constraints.schema.json +161 -0
  89. package/schemas/decisions.schema.json +95 -0
  90. package/schemas/export.schema.json +46 -0
  91. package/schemas/project.schema.json +102 -0
  92. package/schemas/session.schema.json +101 -0
  93. package/schemas/stack.schema.json +103 -0
  94. package/spec.md +717 -0
package/README.md ADDED
@@ -0,0 +1,354 @@
1
+ # Prelude
2
+
3
+ **The open standard for machine-readable codebase context.**
4
+
5
+ Prelude transforms your codebase into structured, AI-optimized context that makes working with LLMs 10x more effective.
6
+
7
+ [![npm version](https://badge.fury.io/js/prelude-context.svg)](https://www.npmjs.com/package/prelude-context)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ---
11
+
12
+ ## Why Prelude?
13
+
14
+ Every time you start a new conversation with an AI assistant, you're forced to explain:
15
+ - What stack you're using
16
+ - How your codebase is organized
17
+ - What patterns and constraints you follow
18
+ - What decisions have been made
19
+
20
+ **Prelude solves this.**
21
+
22
+ Instead of repeating yourself, run `prelude export` and get a comprehensive, AI-optimized context document that captures:
23
+
24
+ - ✅ Your technology stack
25
+ - ✅ Project architecture and patterns
26
+ - ✅ Development constraints and preferences
27
+ - ✅ Key decisions and their rationale
28
+ - ✅ Recent changes and work sessions
29
+
30
+ ## Quick Start
31
+
32
+ ```bash
33
+ # Install globally
34
+ npm install -g prelude-context
35
+
36
+ # Initialize in your project
37
+ cd your-project
38
+ prelude init
39
+
40
+ # Generate AI-optimized context
41
+ prelude export
42
+ ```
43
+
44
+ The export is automatically copied to your clipboard - just paste it into Claude, ChatGPT, or any LLM!
45
+
46
+ ---
47
+
48
+ ## Example Output
49
+
50
+ Here's what Prelude generates for a Next.js monorepo:
51
+
52
+ ```markdown
53
+ # Project Context
54
+ > Generated by Prelude
55
+
56
+ ## 📋 Project Overview
57
+ **Name:** lucem-monorepo
58
+ **Description:** Universal operating system for verified work
59
+ **Version:** 1.0.0
60
+
61
+ ## 🔧 Technology Stack
62
+ **Language:** TypeScript/JavaScript
63
+ **Runtime:** Node.js >=18.0.0
64
+ **Package Manager:** pnpm
65
+ **Frameworks:** Next.js, React
66
+ **Database:** Supabase, PostgreSQL
67
+ **ORM:** Drizzle ORM
68
+
69
+ ## 🏗️ Architecture
70
+ **Type:** monorepo
71
+ **Patterns:** Component-based architecture, Server Components
72
+ **Key Directories:**
73
+ - apps/web - Next.js application
74
+ - packages/db - Database schemas and migrations
75
+
76
+ ## ⚠️ Constraints & Preferences
77
+ **Must Use:**
78
+ - Turborepo for monorepo management
79
+ - TypeScript strict mode
80
+ - Server Components by default
81
+ ```
82
+
83
+ [See full example →](./examples/nextjs-monorepo)
84
+
85
+ ---
86
+
87
+ ## What Makes Prelude Different?
88
+
89
+ | Feature | Prelude | Manual Context | Other Tools |
90
+ |---------|---------|----------------|-------------|
91
+ | Automatic inference | ✅ | ❌ | ⚠️ |
92
+ | Standards-based | ✅ | ❌ | ❌ |
93
+ | Human-readable | ✅ | ✅ | ❌ |
94
+ | Machine-optimized | ✅ | ❌ | ✅ |
95
+ | Version controlled | ✅ | ⚠️ | ❌ |
96
+ | Zero configuration | ✅ | N/A | ❌ |
97
+
98
+ ---
99
+
100
+ ## Core Commands
101
+
102
+ ### `prelude init`
103
+ Analyzes your codebase and creates a `.context/` directory with:
104
+ - `project.json` - Project metadata
105
+ - `stack.json` - Technology stack
106
+ - `architecture.json` - Architecture patterns and structure
107
+ - `constraints.json` - Development rules and preferences
108
+ - `decisions.json` - Architecture decision records
109
+ - `changelog.md` - Project timeline
110
+
111
+ All files follow the [Prelude specification](./SPEC.md) and include JSON Schema validation.
112
+
113
+ ### `prelude export`
114
+ Generates a markdown document optimized for LLMs:
115
+ - Combines all context into a single, focused document
116
+ - Automatically copied to clipboard
117
+ - Perfect for starting new AI conversations
118
+
119
+ ### `prelude decision <title>`
120
+ Logs architecture decisions:
121
+ ```bash
122
+ prelude decision "Use Drizzle ORM instead of Prisma"
123
+ # Opens editor for you to document the decision and rationale
124
+ ```
125
+
126
+ ### `prelude watch`
127
+ Tracks development sessions:
128
+ ```bash
129
+ prelude watch
130
+ # Monitors file changes and logs your work session
131
+ # Press Ctrl+C when done to save the session
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Use Cases
137
+
138
+ ### 🎯 Starting New Conversations
139
+ Paste your Prelude export to instantly give any LLM full context:
140
+
141
+ ```
142
+ Here's my project context:
143
+
144
+ [paste prelude export]
145
+
146
+ I want to add user authentication. What's the best approach given our stack?
147
+ ```
148
+
149
+ ### 🐛 Debugging
150
+ ```
151
+ Here's my project context:
152
+
153
+ [paste prelude export]
154
+
155
+ I'm seeing this error: [error]
156
+ In file: apps/web/app/api/route.ts
157
+
158
+ What's likely causing this?
159
+ ```
160
+
161
+ ### 🏗️ Architecture Decisions
162
+ ```
163
+ Here's my project context:
164
+
165
+ [paste prelude export]
166
+
167
+ Should I use Server Actions or API routes for [feature]?
168
+ Consider our existing patterns and constraints.
169
+ ```
170
+
171
+ ### 📚 Onboarding
172
+ Share your `.context/` directory with new team members so they can:
173
+ - Understand the stack instantly
174
+ - Learn architectural patterns
175
+ - See past decisions and rationale
176
+
177
+ ---
178
+
179
+ ## The Prelude Format
180
+
181
+ Prelude is an **open standard** - not just a CLI tool. The format is:
182
+ - **Versioned** - Semantic versioning for safe evolution
183
+ - **Validated** - JSON Schema for every file type
184
+ - **Extensible** - Add custom fields as needed
185
+ - **Language-agnostic** - Implement in any language
186
+
187
+ See the [full specification →](./SPEC.md)
188
+
189
+ All schemas are hosted at: `https://adjective.us/prelude/schemas/v1/`
190
+
191
+ ---
192
+
193
+ ## Advanced Usage
194
+
195
+ ### Manual Edits
196
+ The `.context/` files are human-readable JSON. Edit them directly:
197
+
198
+ ```json
199
+ {
200
+ "$schema": "https://adjective.us/prelude/schemas/v1/constraints.json",
201
+ "version": "1.0.0",
202
+ "mustUse": [
203
+ "TypeScript strict mode",
204
+ "Server Components by default"
205
+ ],
206
+ "preferences": [
207
+ {
208
+ "category": "state-management",
209
+ "preference": "Prefer URL state over client state",
210
+ "rationale": "Improves sharability and reduces bugs"
211
+ }
212
+ ]
213
+ }
214
+ ```
215
+
216
+ ### Custom Fields
217
+ Add project-specific fields - the schemas allow additional properties:
218
+
219
+ ```json
220
+ {
221
+ "$schema": "https://adjective.us/prelude/schemas/v1/project.json",
222
+ "version": "1.0.0",
223
+ "name": "my-app",
224
+ "customField": "your data",
225
+ "team": [
226
+ { "name": "Alice", "role": "Tech Lead" }
227
+ ]
228
+ }
229
+ ```
230
+
231
+ ### Integration
232
+ Use Prelude in your tools:
233
+
234
+ ```typescript
235
+ import { readFileSync } from 'fs';
236
+ import { join } from 'path';
237
+
238
+ // Read project context
239
+ const project = JSON.parse(
240
+ readFileSync(join(process.cwd(), '.context/project.json'), 'utf-8')
241
+ );
242
+
243
+ console.log(`Project: ${project.name}`);
244
+ console.log(`Stack: ${project.stack?.language}`);
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Requirements
250
+
251
+ - Node.js >= 18.0.0
252
+ - Git (optional, for tracking changes)
253
+
254
+ ---
255
+
256
+ ## Project Structure
257
+
258
+ ```
259
+ your-project/
260
+ ├── .context/ # Created by Prelude
261
+ │ ├── project.json # Project metadata
262
+ │ ├── stack.json # Technology stack
263
+ │ ├── architecture.json # Architecture patterns
264
+ │ ├── constraints.json # Development rules
265
+ │ ├── decisions.json # Architecture decisions
266
+ │ └── changelog.md # Project timeline
267
+ ├── .gitignore # Add .context/*.session.json
268
+ └── ...
269
+ ```
270
+
271
+ **Note:** Commit `.context/` to version control (except `*.session.json` files).
272
+
273
+ ---
274
+
275
+ ## FAQ
276
+
277
+ ### Should I commit `.context/` to git?
278
+ **Yes!** The context is part of your project documentation. Exception: `.context/*.session.json` should be gitignored (it's for local work tracking).
279
+
280
+ ### How often should I update the context?
281
+ Prelude auto-updates timestamps. Run `prelude export` whenever you need fresh context for an AI conversation. Update the JSON files manually when you make architectural changes.
282
+
283
+ ### Can I use this with any LLM?
284
+ Yes! The export format is optimized for Claude, ChatGPT, Gemini, and any text-based AI assistant.
285
+
286
+ ### What if my project structure is unusual?
287
+ Prelude's inference is smart but not perfect. Just edit the `.context/` files directly - they're human-readable JSON.
288
+
289
+ ### Does this work with non-JavaScript projects?
290
+ Yes! While the CLI is built with Node.js, the Prelude format works with any language. The inference currently focuses on JavaScript/TypeScript but the format is universal.
291
+
292
+ ---
293
+
294
+ ## Roadmap
295
+
296
+ - [ ] Improved inference for Python, Rust, Go
297
+ - [ ] VS Code extension for inline context
298
+ - [ ] GitHub Action for automated updates
299
+ - [ ] Plugin system for custom inference
300
+ - [ ] CLI validation command
301
+ - [ ] Context diff tool
302
+
303
+ Want to contribute? See [CONTRIBUTING.md](./CONTRIBUTING.md)
304
+
305
+ ---
306
+
307
+ ## Design Principles
308
+
309
+ 1. **Human-readable first** - All files are readable JSON/Markdown
310
+ 2. **AI-optimized** - Structured for maximum LLM effectiveness
311
+ 3. **Standards-based** - Open spec, not proprietary format
312
+ 4. **Zero lock-in** - Edit files manually, use any tool
313
+ 5. **Incremental adoption** - Works with partial information
314
+
315
+ ---
316
+
317
+ ## Examples
318
+
319
+ - [Next.js Monorepo](./examples/nextjs-monorepo) - Turborepo + Drizzle + Supabase
320
+ - [Express API](./examples/express-api) - REST API with PostgreSQL
321
+ - [Vite React App](./examples/vite-react) - Frontend SPA
322
+
323
+ ---
324
+
325
+ ## Contributing
326
+
327
+ Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) first.
328
+
329
+ Areas we'd love help with:
330
+ - Improved inference patterns
331
+ - Support for more languages/frameworks
332
+ - Example projects
333
+ - Documentation improvements
334
+ - Bug reports and feature requests
335
+
336
+ ---
337
+
338
+ ## License
339
+
340
+ MIT © [Adjective](https://adjective.us)
341
+
342
+ ---
343
+
344
+ ## Links
345
+
346
+ - [Specification](./SPEC.md)
347
+ - [Schema Documentation](./schemas/README.md)
348
+ - [Examples](./examples/)
349
+ - [NPM Package](https://www.npmjs.com/package/prelude-context)
350
+ - [Issues & Feature Requests](https://github.com/adjective-rob/prelude/issues)
351
+
352
+ ---
353
+
354
+ **Built by [Adjective](https://adjective.us) - Sovereign Software for AI-Native Teams**
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=prelude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prelude.d.ts","sourceRoot":"","sources":["../../bin/prelude.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import { cac } from 'cac';
3
+ import { readFileSync } from 'fs';
4
+ import { join, dirname } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ // Get package.json - works in both dev and built versions
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+ // Try built location first (dist/bin), then dev location (bin)
10
+ let packageJson;
11
+ try {
12
+ packageJson = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
13
+ }
14
+ catch {
15
+ packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
16
+ }
17
+ const cli = cac('prelude');
18
+ cli
19
+ .version(packageJson.version)
20
+ .help();
21
+ // Import commands
22
+ import { registerInitCommand } from '../src/commands/init.js';
23
+ import { registerExportCommand } from '../src/commands/export.js';
24
+ import { registerShareCommand } from '../src/commands/share.js';
25
+ import { registerDecisionCommand } from '../src/commands/decision.js';
26
+ import { registerWatchCommand } from '../src/commands/watch.js';
27
+ // Register all commands
28
+ registerInitCommand(cli);
29
+ registerExportCommand(cli);
30
+ registerShareCommand(cli);
31
+ registerDecisionCommand(cli);
32
+ registerWatchCommand(cli);
33
+ // Parse and run
34
+ cli.parse();
35
+ //# sourceMappingURL=prelude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prelude.js","sourceRoot":"","sources":["../../bin/prelude.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,0DAA0D;AAC1D,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,+DAA+D;AAC/D,IAAI,WAAgB,CAAC;AACrB,IAAI,CAAC;IACH,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACzF,CAAC;AAAC,MAAM,CAAC;IACP,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;AAE3B,GAAG;KACA,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;KAC5B,IAAI,EAAE,CAAC;AAEV,kBAAkB;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,wBAAwB;AACxB,mBAAmB,CAAC,GAAG,CAAC,CAAC;AACzB,qBAAqB,CAAC,GAAG,CAAC,CAAC;AAC3B,oBAAoB,CAAC,GAAG,CAAC,CAAC;AAC1B,uBAAuB,CAAC,GAAG,CAAC,CAAC;AAC7B,oBAAoB,CAAC,GAAG,CAAC,CAAC;AAE1B,gBAAgB;AAChB,GAAG,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { CAC } from 'cac';
2
+ export declare function registerDecisionCommand(cli: CAC): void;
3
+ //# sourceMappingURL=decision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../../src/commands/decision.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAY/B,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,GAAG,QAoF/C"}
@@ -0,0 +1,74 @@
1
+ import { join } from 'path';
2
+ import { readJSON, writeJSON, fileExists } from '../utils/fs.js';
3
+ import { logger } from '../utils/log.js';
4
+ import { getCurrentTimestamp, generateId } from '../utils/time.js';
5
+ import { CONTEXT_DIR, CONTEXT_FILES } from '../constants.js';
6
+ // Add these constants
7
+ const PRELUDE_VERSION = "1.0.0";
8
+ const SCHEMA_URL = "https://prelude.dev/schemas/v1";
9
+ export function registerDecisionCommand(cli) {
10
+ cli
11
+ .command('decision <title>', 'Log an architectural decision')
12
+ .option('--rationale <text>', 'Decision rationale')
13
+ .option('--alternatives <items>', 'Comma-separated list of alternatives considered')
14
+ .option('--impact <text>', 'Impact of the decision')
15
+ .option('--status <status>', 'Decision status (proposed, accepted, rejected)', { default: 'accepted' })
16
+ .option('--author <name>', 'Decision author')
17
+ .option('--tags <items>', 'Comma-separated tags')
18
+ .action(async (title, options, dir = process.cwd()) => {
19
+ const rootDir = dir;
20
+ const contextDir = join(rootDir, CONTEXT_DIR);
21
+ const decisionsPath = join(contextDir, CONTEXT_FILES.DECISIONS);
22
+ // Check if .context exists
23
+ if (!(await fileExists(contextDir))) {
24
+ logger.error('.context/ directory not found. Run `prelude init` first.');
25
+ process.exit(1);
26
+ }
27
+ logger.decision(`Recording decision: ${title}`);
28
+ // Read existing decisions
29
+ // MODIFIED LINE: Add default $schema and version to the initial object
30
+ let decisions = {
31
+ $schema: `${SCHEMA_URL}/decisions.json`,
32
+ version: PRELUDE_VERSION,
33
+ decisions: []
34
+ };
35
+ if (await fileExists(decisionsPath)) {
36
+ decisions = await readJSON(decisionsPath);
37
+ }
38
+ // Prompt for rationale if not provided
39
+ let rationale = options.rationale;
40
+ if (!rationale) {
41
+ logger.warn('No rationale provided. Please provide a brief explanation:');
42
+ // In a real implementation, you'd use a prompt library like enquirer
43
+ // For now, we'll require it via the flag
44
+ logger.error('Please provide --rationale flag');
45
+ process.exit(1);
46
+ }
47
+ // Parse alternatives and tags
48
+ const alternatives = options.alternatives ? options.alternatives.split(',').map(s => s.trim()) : undefined;
49
+ const tags = options.tags ? options.tags.split(',').map(s => s.trim()) : undefined;
50
+ // Create new decision
51
+ const decision = {
52
+ id: generateId(),
53
+ timestamp: getCurrentTimestamp(),
54
+ title,
55
+ status: options.status || 'accepted',
56
+ rationale,
57
+ alternatives,
58
+ impact: options.impact,
59
+ author: options.author,
60
+ tags
61
+ };
62
+ // Add to decisions
63
+ decisions.decisions.push(decision);
64
+ // Write back
65
+ await writeJSON(decisionsPath, decisions);
66
+ logger.success('✓ Decision recorded successfully!');
67
+ logger.info(`\nDecision ID: ${decision.id}`);
68
+ logger.info(`Status: ${decision.status}`);
69
+ if (alternatives) {
70
+ logger.info(`Alternatives considered: ${alternatives.length}`);
71
+ }
72
+ });
73
+ }
74
+ //# sourceMappingURL=decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../../../src/commands/decision.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CAC } from 'cac';
2
+ export declare function registerExportCommand(cli: CAC): void;
3
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/commands/export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AA0E/B,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,QA0E7C"}
@@ -0,0 +1,132 @@
1
+ import { join } from 'path';
2
+ import { readFile } from 'fs/promises';
3
+ import { spawn, execSync } from 'child_process';
4
+ import { platform } from 'os';
5
+ import { fileExists } from '../utils/fs.js';
6
+ import { logger, spinner } from '../utils/log.js';
7
+ import { CONTEXT_DIR } from '../constants.js';
8
+ import { saveExport } from '../core/exporter.js';
9
+ // Check if a command exists
10
+ function commandExists(command) {
11
+ try {
12
+ execSync(`which ${command}`, { stdio: 'ignore' });
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ // Native clipboard using shell commands (no dependencies!)
20
+ async function copyToClipboard(text) {
21
+ return new Promise((resolve) => {
22
+ try {
23
+ const os = platform();
24
+ let command;
25
+ let args = [];
26
+ if (os === 'darwin') {
27
+ command = 'pbcopy';
28
+ }
29
+ else if (os === 'linux') {
30
+ // Check which clipboard tool is available
31
+ if (commandExists('xclip')) {
32
+ command = 'xclip';
33
+ args = ['-selection', 'clipboard'];
34
+ }
35
+ else if (commandExists('xsel')) {
36
+ command = 'xsel';
37
+ args = ['--clipboard', '--input'];
38
+ }
39
+ else {
40
+ resolve(false);
41
+ return;
42
+ }
43
+ }
44
+ else if (os === 'win32') {
45
+ command = 'clip.exe';
46
+ }
47
+ else {
48
+ resolve(false);
49
+ return;
50
+ }
51
+ const proc = spawn(command, args);
52
+ let errorOccurred = false;
53
+ proc.on('error', () => {
54
+ errorOccurred = true;
55
+ resolve(false);
56
+ });
57
+ // For clipboard commands, if stdin closes without error, assume success
58
+ proc.stdin.on('finish', () => {
59
+ if (!errorOccurred) {
60
+ // Give it a tiny moment to process, then assume success
61
+ setTimeout(() => resolve(true), 100);
62
+ }
63
+ });
64
+ proc.stdin.write(text);
65
+ proc.stdin.end();
66
+ }
67
+ catch {
68
+ resolve(false);
69
+ }
70
+ });
71
+ }
72
+ export function registerExportCommand(cli) {
73
+ cli
74
+ .command('export [dir]', 'Generate LLM-optimized export')
75
+ .option('--format <format>', 'Output format (md or json)', { default: 'md' })
76
+ .option('--no-copy', 'Skip copying to clipboard')
77
+ .option('--print', 'Print to stdout after export')
78
+ .action(async (dir = process.cwd(), options) => {
79
+ const rootDir = dir;
80
+ const contextDir = join(rootDir, CONTEXT_DIR);
81
+ // Check if .context exists
82
+ if (!(await fileExists(contextDir))) {
83
+ logger.error('.context/ directory not found. Run `prelude init` first.');
84
+ process.exit(1);
85
+ }
86
+ logger.export('Exporting context...');
87
+ const format = options.format === 'json' ? 'json' : 'md';
88
+ const spin = spinner(`Generating ${format.toUpperCase()} export...`);
89
+ try {
90
+ const exportPath = await saveExport(rootDir, format);
91
+ spin.stop();
92
+ logger.success(`✓ Export generated: ${exportPath}`);
93
+ // Read the exported content
94
+ const content = await readFile(exportPath, 'utf-8');
95
+ // Auto-copy to clipboard by default (unless --no-copy is specified)
96
+ const shouldCopy = options.copy !== false;
97
+ if (shouldCopy) {
98
+ const copySpin = spinner('Copying to clipboard...');
99
+ const copied = await copyToClipboard(content);
100
+ copySpin.stop();
101
+ if (copied) {
102
+ logger.success('✓ Copied to clipboard!');
103
+ logger.info('📋 Ready to paste into your AI chat');
104
+ }
105
+ else {
106
+ const os = platform();
107
+ logger.warn('⚠ Clipboard tool not found');
108
+ if (os === 'linux') {
109
+ logger.info('\nInstall xclip or xsel:');
110
+ logger.info(' sudo apt install xclip');
111
+ logger.info(' # or');
112
+ logger.info(' sudo apt install xsel');
113
+ }
114
+ logger.info('\nManual copy:');
115
+ logger.info(` cat ${exportPath}`);
116
+ }
117
+ }
118
+ // Handle --print flag
119
+ if (options.print) {
120
+ console.log('\n' + '─'.repeat(50));
121
+ console.log(content);
122
+ console.log('─'.repeat(50) + '\n');
123
+ }
124
+ }
125
+ catch (error) {
126
+ spin.stop();
127
+ logger.error(`Failed to generate export: ${error}`);
128
+ process.exit(1);
129
+ }
130
+ });
131
+ }
132
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/commands/export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CAC } from 'cac';
2
+ export declare function registerInitCommand(cli: CAC): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAY/B,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,QA+E3C"}