openclew 0.0.1 → 0.2.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/lib/inject.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Inject openclew block into an existing instruction file.
3
+ */
4
+
5
+ const fs = require("fs");
6
+
7
+ const OPENCLEW_BLOCK = `
8
+ ## Project knowledge (openclew)
9
+
10
+ This file is the **entry point** for project documentation.
11
+
12
+ **Doc-first rule:** before any task, read \`doc/_INDEX.md\` to find docs related to the task. Read them before exploring code.
13
+
14
+ Two types of docs in \`doc/\`:
15
+ - **Living docs** (\`doc/_*.md\`) — evolve with the project (architecture, conventions, decisions)
16
+ - **Logs** (\`doc/log/YYYY-MM-DD_*.md\`) — frozen facts from a session, never modified after
17
+
18
+ Each doc has 3 levels: **L1** (metadata — read first to decide relevance) → **L2** (summary) → **L3** (full details, only when needed).
19
+
20
+ **Creating docs:** when a decision, convention, or significant event needs to be captured, create the file directly following the format in \`doc/_USING_OPENCLEW.md\`.
21
+ `.trim();
22
+
23
+ const MARKER_START = "<!-- openclew_START -->";
24
+ const MARKER_END = "<!-- openclew_END -->";
25
+
26
+ function isAlreadyInjected(filePath) {
27
+ const content = fs.readFileSync(filePath, "utf-8");
28
+ return content.includes(MARKER_START);
29
+ }
30
+
31
+ function inject(filePath) {
32
+ if (isAlreadyInjected(filePath)) {
33
+ return false;
34
+ }
35
+
36
+ const content = fs.readFileSync(filePath, "utf-8");
37
+ const block = `\n\n${MARKER_START}\n${OPENCLEW_BLOCK}\n${MARKER_END}\n`;
38
+ fs.writeFileSync(filePath, content + block, "utf-8");
39
+ return true;
40
+ }
41
+
42
+ module.exports = { inject, isAlreadyInjected, OPENCLEW_BLOCK, MARKER_START };
package/lib/new-doc.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * openclew new <title> — create a new living doc.
3
+ */
4
+
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+ const { livingContent, slugify } = require("./templates");
8
+ const { readConfig } = require("./config");
9
+
10
+ const args = process.argv.slice(2);
11
+ // Remove "new" command from args
12
+ const cmdIndex = args.indexOf("new");
13
+ const titleArgs = cmdIndex >= 0 ? args.slice(cmdIndex + 1) : args.slice(1);
14
+ const title = titleArgs.join(" ");
15
+
16
+ if (!title) {
17
+ console.error('Usage: openclew new "Title of the document"');
18
+ process.exit(1);
19
+ }
20
+
21
+ const projectRoot = process.cwd();
22
+ const docDir = path.join(projectRoot, "doc");
23
+ if (!fs.existsSync(docDir)) {
24
+ console.error("No doc/ directory found. Run 'openclew init' first.");
25
+ process.exit(1);
26
+ }
27
+ if (!readConfig(projectRoot)) {
28
+ console.warn("Warning: no .openclew.json found. Run 'openclew init' first.");
29
+ }
30
+
31
+ const slug = slugify(title);
32
+ const filename = `_${slug}.md`;
33
+ const filepath = path.join(docDir, filename);
34
+
35
+ if (fs.existsSync(filepath)) {
36
+ console.error(`File already exists: doc/${filename}`);
37
+ process.exit(1);
38
+ }
39
+
40
+ fs.writeFileSync(filepath, livingContent(title), "utf-8");
41
+ console.log(`Created doc/${filename}`);
42
+ console.log("");
43
+ console.log("Next: open the file and fill in:");
44
+ console.log(" L1 — subject, status, keywords (so the index can find it)");
45
+ console.log(" L2 — objective + key points (what agents and humans need to know)");
46
+ console.log(" L3 — full details (only when needed)");
package/lib/new-log.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * openclew log <title> — create a new session log.
3
+ */
4
+
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+ const { logContent, slugifyLog, today } = require("./templates");
8
+ const { readConfig } = require("./config");
9
+
10
+ const args = process.argv.slice(2);
11
+ // Remove "log" command from args
12
+ const cmdIndex = args.indexOf("log");
13
+ const titleArgs = cmdIndex >= 0 ? args.slice(cmdIndex + 1) : args.slice(1);
14
+ const title = titleArgs.join(" ");
15
+
16
+ if (!title) {
17
+ console.error('Usage: openclew log "Title of the log"');
18
+ process.exit(1);
19
+ }
20
+
21
+ const projectRoot = process.cwd();
22
+ const logDir = path.join(projectRoot, "doc", "log");
23
+ if (!fs.existsSync(logDir)) {
24
+ console.error("No doc/log/ directory found. Run 'openclew init' first.");
25
+ process.exit(1);
26
+ }
27
+ if (!readConfig(projectRoot)) {
28
+ console.warn("Warning: no .openclew.json found. Run 'openclew init' first.");
29
+ }
30
+
31
+ const slug = slugifyLog(title);
32
+ const date = today();
33
+ const filename = `${date}_${slug}.md`;
34
+ const filepath = path.join(logDir, filename);
35
+
36
+ if (fs.existsSync(filepath)) {
37
+ console.error(`File already exists: doc/log/${filename}`);
38
+ process.exit(1);
39
+ }
40
+
41
+ fs.writeFileSync(filepath, logContent(title), "utf-8");
42
+ console.log(`Created doc/log/${filename}`);
43
+ console.log("");
44
+ console.log("Next: open the file and fill in:");
45
+ console.log(" L1 — type, status, short_story (what happened in 1-2 sentences)");
46
+ console.log(" L2 — problem + solution (the facts, frozen after this session)");
47
+ console.log("");
48
+ console.log("Logs are immutable — once written, never modified.");
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Template content for living docs and logs.
3
+ * Embedded here so the CLI works standalone without needing to locate template files.
4
+ */
5
+
6
+ function today() {
7
+ return new Date().toISOString().slice(0, 10);
8
+ }
9
+
10
+ function slugify(title) {
11
+ return title
12
+ .toUpperCase()
13
+ .replace(/[^A-Z0-9]+/g, "_")
14
+ .replace(/^_|_$/g, "");
15
+ }
16
+
17
+ function slugifyLog(title) {
18
+ return title
19
+ .toLowerCase()
20
+ .replace(/[^a-z0-9]+/g, "-")
21
+ .replace(/^-|-$/g, "");
22
+ }
23
+
24
+ function livingContent(title) {
25
+ const date = today();
26
+ return `<!-- L1_START -->
27
+ # L1 - Metadata
28
+ type: Reference
29
+ subject: ${title}
30
+ created: ${date}
31
+ updated: ${date}
32
+ short_story:
33
+ status: Active
34
+ category:
35
+ keywords: []
36
+ <!-- L1_END -->
37
+
38
+ ---
39
+
40
+ <!-- L2_START -->
41
+ # L2 - Summary
42
+
43
+ ## Objective
44
+ <!-- Why this document exists -->
45
+
46
+ ## Key points
47
+ <!-- 3-5 essential takeaways -->
48
+ <!-- L2_END -->
49
+
50
+ ---
51
+
52
+ <!-- L3_START -->
53
+ # L3 - Details
54
+
55
+ <!-- Full technical content -->
56
+
57
+ ---
58
+
59
+ ## Changelog
60
+
61
+ | Date | Change |
62
+ |------|--------|
63
+ | ${date} | Initial creation |
64
+ <!-- L3_END -->
65
+ `;
66
+ }
67
+
68
+ function logContent(title) {
69
+ const date = today();
70
+ return `<!-- L1_START -->
71
+ # L1 - Metadata
72
+ date: ${date}
73
+ type: Feature
74
+ subject: ${title}
75
+ short_story:
76
+ status: In progress
77
+ category:
78
+ keywords: []
79
+ <!-- L1_END -->
80
+
81
+ ---
82
+
83
+ <!-- L2_START -->
84
+ # L2 - Summary
85
+
86
+ ## Objective
87
+ <!-- Why this work was undertaken -->
88
+
89
+ ## Problem
90
+ <!-- What was observed -->
91
+
92
+ ## Solution
93
+ <!-- How it was resolved -->
94
+ <!-- L2_END -->
95
+
96
+ ---
97
+
98
+ <!-- L3_START -->
99
+ # L3 - Details
100
+
101
+ <!-- Technical details, code changes, debugging steps... -->
102
+ <!-- L3_END -->
103
+ `;
104
+ }
105
+
106
+ /**
107
+ * Guide doc — always created by init.
108
+ * This is what agents read to understand openclew.
109
+ */
110
+ function guideContent() {
111
+ const date = today();
112
+ return `<!-- L1_START -->
113
+ # L1 - Metadata
114
+ type: Guide
115
+ subject: How openclew works
116
+ created: ${date}
117
+ updated: ${date}
118
+ short_story: How openclew structures project knowledge in 3 levels (L1/L2/L3) so AI agents and humans navigate efficiently.
119
+ status: Active
120
+ category: Documentation
121
+ keywords: [openclew, L1, L2, L3, index, living-doc, log]
122
+ <!-- L1_END -->
123
+
124
+ ---
125
+
126
+ <!-- L2_START -->
127
+ # L2 - Summary
128
+
129
+ ## What is openclew?
130
+
131
+ openclew gives your project a structured memory that both humans and AI agents can navigate efficiently.
132
+
133
+ ## Doc-first rule
134
+
135
+ Before starting any task, read \`doc/_INDEX.md\` to find docs related to the task. Read them before exploring code. This avoids reinventing what's already documented.
136
+
137
+ ## Two types of docs
138
+
139
+ **Living docs** (\`doc/_*.md\`): knowledge that evolves with the project.
140
+ Architecture decisions, conventions, known pitfalls — anything that stays relevant over time.
141
+ Naming: \`doc/_UPPER_SNAKE_CASE.md\` (e.g. \`doc/_AUTH_DESIGN.md\`)
142
+
143
+ **Logs** (\`doc/log/YYYY-MM-DD_*.md\`): frozen facts from a work session.
144
+ What happened, what was decided, what was tried. Never modified after the session.
145
+ Naming: \`doc/log/YYYY-MM-DD_lowercase-slug.md\` (e.g. \`doc/log/2026-01-15_setup-auth.md\`)
146
+
147
+ ## Three levels per doc
148
+
149
+ Every doc has 3 levels. Read only what you need:
150
+
151
+ - **L1 — Metadata** (~40 tokens): subject, keywords, status. Read this first to decide if the doc is relevant.
152
+ - **L2 — Summary**: the essential context — objective, key points, decisions.
153
+ - **L3 — Details**: full technical content. Only read when deep-diving.
154
+
155
+ ## Index
156
+
157
+ \`doc/_INDEX.md\` is auto-generated from L1 metadata on every git commit (via a pre-commit hook).
158
+ Never edit it manually. To force a rebuild: \`openclew index\`
159
+ <!-- L2_END -->
160
+
161
+ ---
162
+
163
+ <!-- L3_START -->
164
+ # L3 - Details
165
+
166
+ ## Creating a living doc
167
+
168
+ Create \`doc/_TITLE.md\` (uppercase snake_case) with this structure:
169
+
170
+ \`\`\`
171
+ <!-- L1_START -->
172
+ # L1 - Metadata
173
+ type: Reference
174
+ subject: Title
175
+ created: YYYY-MM-DD
176
+ updated: YYYY-MM-DD
177
+ short_story:
178
+ status: Active
179
+ category:
180
+ keywords: []
181
+ <!-- L1_END -->
182
+
183
+ ---
184
+
185
+ <!-- L2_START -->
186
+ # L2 - Summary
187
+ ## Objective
188
+ ## Key points
189
+ <!-- L2_END -->
190
+
191
+ ---
192
+
193
+ <!-- L3_START -->
194
+ # L3 - Details
195
+ <!-- L3_END -->
196
+ \`\`\`
197
+
198
+ **When to create one:**
199
+ - A decision was made that others need to know (architecture, convention, API design)
200
+ - A pattern or pitfall keeps coming up
201
+ - You want an agent to know something at the start of every session
202
+
203
+ ## Creating a log
204
+
205
+ Create \`doc/log/YYYY-MM-DD_slug.md\` (lowercase, hyphens) with this structure:
206
+
207
+ \`\`\`
208
+ <!-- L1_START -->
209
+ # L1 - Metadata
210
+ date: YYYY-MM-DD
211
+ type: Feature
212
+ subject: Title
213
+ short_story:
214
+ status: In progress
215
+ category:
216
+ keywords: []
217
+ <!-- L1_END -->
218
+
219
+ ---
220
+
221
+ <!-- L2_START -->
222
+ # L2 - Summary
223
+ ## Objective
224
+ ## Problem
225
+ ## Solution
226
+ <!-- L2_END -->
227
+
228
+ ---
229
+
230
+ <!-- L3_START -->
231
+ # L3 - Details
232
+ <!-- L3_END -->
233
+ \`\`\`
234
+
235
+ **When to create one:**
236
+ - End of a work session (what was done, what's left)
237
+ - A bug was investigated and resolved
238
+ - A spike or experiment was conducted
239
+
240
+ Logs are immutable — once the session ends, the log is never modified.
241
+
242
+ ## How agents should use this
243
+
244
+ 1. At session start: read the entry point file
245
+ 2. Before any task: read \`doc/_INDEX.md\`, scan L1 metadata, identify relevant docs
246
+ 3. Read L2 of relevant docs for context
247
+ 4. Only read L3 when you need implementation details
248
+ 5. After significant work: create or update living docs and logs directly
249
+
250
+ The index (\`doc/_INDEX.md\`) auto-regenerates on every git commit. To force a rebuild: \`openclew index\`
251
+
252
+ ---
253
+
254
+ ## Changelog
255
+
256
+ | Date | Change |
257
+ |------|--------|
258
+ | ${date} | Created by openclew init |
259
+ <!-- L3_END -->
260
+ `;
261
+ }
262
+
263
+ /**
264
+ * Example living doc — shows what a filled-in doc looks like.
265
+ */
266
+ function exampleLivingDocContent() {
267
+ const date = today();
268
+ return `<!-- L1_START -->
269
+ # L1 - Metadata
270
+ type: Reference
271
+ subject: Architecture overview
272
+ created: ${date}
273
+ updated: ${date}
274
+ short_story: High-level architecture of the project — components, data flow, key decisions.
275
+ status: Active
276
+ category: Architecture
277
+ keywords: [architecture, overview, components]
278
+ <!-- L1_END -->
279
+
280
+ ---
281
+
282
+ <!-- L2_START -->
283
+ # L2 - Summary
284
+
285
+ ## Objective
286
+ Document the high-level architecture so new contributors and AI agents understand the system quickly.
287
+
288
+ ## Key points
289
+ - Replace this with your actual architecture
290
+ - Describe the main components and how they interact
291
+ - Note key technical decisions and their rationale
292
+ <!-- L2_END -->
293
+
294
+ ---
295
+
296
+ <!-- L3_START -->
297
+ # L3 - Details
298
+
299
+ <!-- Replace this with your actual architecture details -->
300
+
301
+ This is an example living doc created by \`openclew init\`.
302
+ Edit it to document your project's architecture, or delete it and create your own.
303
+
304
+ ---
305
+
306
+ ## Changelog
307
+
308
+ | Date | Change |
309
+ |------|--------|
310
+ | ${date} | Created by openclew init (example) |
311
+ <!-- L3_END -->
312
+ `;
313
+ }
314
+
315
+ /**
316
+ * Example log — shows what a filled-in log looks like.
317
+ */
318
+ function exampleLogContent() {
319
+ const date = today();
320
+ return `<!-- L1_START -->
321
+ # L1 - Metadata
322
+ date: ${date}
323
+ type: Feature
324
+ subject: Set up openclew
325
+ short_story: Initialized openclew for structured project knowledge. Created doc/ structure, git hook, guide, and example docs.
326
+ status: Done
327
+ category: Tooling
328
+ keywords: [openclew, setup, documentation]
329
+ <!-- L1_END -->
330
+
331
+ ---
332
+
333
+ <!-- L2_START -->
334
+ # L2 - Summary
335
+
336
+ ## Objective
337
+ Set up structured documentation so AI agents and new contributors can navigate project knowledge efficiently.
338
+
339
+ ## Problem
340
+ Project knowledge was scattered — README, inline comments, tribal knowledge. Each new AI session started from zero.
341
+
342
+ ## Solution
343
+ Installed openclew. Every doc now has L1 (metadata for triage), L2 (summary for context), L3 (details when needed).
344
+ The index auto-regenerates on each commit via a git hook.
345
+ <!-- L2_END -->
346
+
347
+ ---
348
+
349
+ <!-- L3_START -->
350
+ # L3 - Details
351
+
352
+ This log was created by \`openclew init\`.
353
+ It shows what a filled-in log looks like. Logs are immutable — once the session ends, the log is frozen.
354
+ For evolving knowledge, use living docs (\`doc/_*.md\`).
355
+ <!-- L3_END -->
356
+ `;
357
+ }
358
+
359
+ module.exports = {
360
+ livingContent,
361
+ logContent,
362
+ guideContent,
363
+ exampleLivingDocContent,
364
+ exampleLogContent,
365
+ slugify,
366
+ slugifyLog,
367
+ today,
368
+ };
package/package.json CHANGED
@@ -1,10 +1,35 @@
1
1
  {
2
2
  "name": "openclew",
3
- "version": "0.0.1",
4
- "description": "Long Life Memory for LLMs",
3
+ "version": "0.2.0",
4
+ "description": "Long Life Memory for LLMs — structured project knowledge for AI agents and humans",
5
5
  "license": "MIT",
6
+ "bin": {
7
+ "openclew": "./bin/openclew.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "lib/",
12
+ "templates/",
13
+ "hooks/",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "keywords": [
18
+ "ai",
19
+ "llm",
20
+ "documentation",
21
+ "knowledge",
22
+ "memory",
23
+ "claude",
24
+ "cursor",
25
+ "copilot",
26
+ "agents"
27
+ ],
6
28
  "repository": {
7
29
  "type": "git",
8
30
  "url": "https://github.com/openclew/openclew"
31
+ },
32
+ "engines": {
33
+ "node": ">=16"
9
34
  }
10
35
  }
@@ -0,0 +1,45 @@
1
+ <!-- L1_START -->
2
+ # L1 - Metadata
3
+ type: Reference | Architecture | Guide | Analysis
4
+ subject: Short title (< 60 chars)
5
+ created: YYYY-MM-DD
6
+ updated: YYYY-MM-DD
7
+ short_story: 1-2 sentences. What this doc covers and what it concludes. Must be enough to decide if you need to read further.
8
+ status: Active | Stable | Archived
9
+ category: Main domain (e.g. Auth, API, Database, UI...)
10
+ keywords: [tag1, tag2, tag3]
11
+ <!-- L1_END -->
12
+
13
+ ---
14
+
15
+ <!-- L2_START -->
16
+ # L2 - Summary
17
+
18
+ ## Objective
19
+ <!-- Why this document exists, what need it covers -->
20
+
21
+ ## Key points
22
+ <!-- 3-5 essential takeaways -->
23
+
24
+ ## Solution
25
+ <!-- Recommended approach or pattern -->
26
+
27
+ ## Watch out
28
+ <!-- Common pitfalls, edge cases, things to be aware of -->
29
+ <!-- L2_END -->
30
+
31
+ ---
32
+
33
+ <!-- L3_START -->
34
+ # L3 - Details
35
+
36
+ <!-- Full technical content: code examples, diagrams, references, deep dives... -->
37
+
38
+ ---
39
+
40
+ ## Changelog
41
+
42
+ | Date | Change |
43
+ |------|--------|
44
+ | YYYY-MM-DD | Initial creation |
45
+ <!-- L3_END -->
@@ -0,0 +1,36 @@
1
+ <!-- L1_START -->
2
+ # L1 - Metadata
3
+ date: YYYY-MM-DD
4
+ type: Bug | Feature | Refactor | Doc | Deploy
5
+ subject: Short title (< 60 chars)
6
+ short_story: 1-2 sentences. What happened and what was the outcome. Include conclusions, not just process.
7
+ status: Done | In progress | Abandoned
8
+ category: Main domain (e.g. Auth, API, Database, UI...)
9
+ keywords: [tag1, tag2, tag3]
10
+ <!-- L1_END -->
11
+
12
+ ---
13
+
14
+ <!-- L2_START -->
15
+ # L2 - Summary
16
+
17
+ ## Objective
18
+ <!-- Why this work was undertaken -->
19
+
20
+ ## Problem
21
+ <!-- What was observed, context of discovery -->
22
+
23
+ ## Solution
24
+ <!-- How it was resolved -->
25
+
26
+ ## Watch out
27
+ <!-- Side effects, edge cases, things to know -->
28
+ <!-- L2_END -->
29
+
30
+ ---
31
+
32
+ <!-- L3_START -->
33
+ # L3 - Details
34
+
35
+ <!-- Technical details: code changes, debugging steps, commands, references... -->
36
+ <!-- L3_END -->