openclew 0.2.1 → 0.3.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/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/openclew/openclew/main/assets/logo.png" alt="openclew" width="200">
3
+ </p>
4
+
1
5
  # openclew
2
6
 
3
7
  > Long Life Memory for LLMs
@@ -114,7 +118,7 @@ The index auto-regenerates on every commit. Never edit it manually.
114
118
  1. Create `doc/` and `doc/log/`
115
119
  2. Copy templates from [`templates/`](templates/) (refdoc.md, log.md)
116
120
  3. Add the openclew block to your instruction file (see `doc/_USING_OPENCLEW.md` after init for the exact format)
117
- 4. Copy [`hooks/generate-index.py`](hooks/generate-index.py) and wire it as a pre-commit hook
121
+ 4. Run `openclew index` to generate `doc/_INDEX.md` (or wire it as a pre-commit hook)
118
122
 
119
123
  </details>
120
124
 
package/UPGRADING.md ADDED
@@ -0,0 +1,167 @@
1
+ # Upgrading openclew
2
+
3
+ openclew evolves. When the format changes, your existing docs still work — parsers
4
+ are backward-compatible. But new features expect the current format.
5
+
6
+ `openclew migrate` bridges the gap.
7
+
8
+ ---
9
+
10
+ ## Quick version
11
+
12
+ ```bash
13
+ npm install -g openclew@latest # or: npx openclew@latest
14
+ openclew status # shows legacy doc count
15
+ openclew migrate # dry-run: what would change
16
+ openclew migrate --write # apply
17
+ git diff # review
18
+ git add doc/ && git commit -m "chore: migrate docs to openclew format"
19
+ ```
20
+
21
+ ---
22
+
23
+ ## When to upgrade
24
+
25
+ After updating openclew, run `openclew status`. If it reports legacy docs,
26
+ run `openclew migrate` to see what needs changing.
27
+
28
+ You can also check directly:
29
+
30
+ ```bash
31
+ openclew migrate
32
+ # → 12 to migrate, 45 already current, 0 errors (57 total)
33
+ ```
34
+
35
+ No output = nothing to do.
36
+
37
+ ---
38
+
39
+ ## How it works
40
+
41
+ `migrate` converts docs from older formats to the current openclew format.
42
+ It is **safe by default**:
43
+
44
+ - **Dry-run first** — shows what would change without touching files
45
+ - **`--write` to apply** — only modifies files when you explicitly ask
46
+ - **Git-friendly** — files are tracked, `git diff` shows exactly what changed
47
+ - **Idempotent** — running it twice produces the same result
48
+ - **Skips current docs** — only touches files that need updating
49
+
50
+ ### What it converts
51
+
52
+ | Before | After |
53
+ |--------|-------|
54
+ | `R.AlphA.Doc@7.0.0` (line 1) | `openclew@0.3.0 · created: ... · type: ... · ...` |
55
+ | `subject: Title` (plain L1) | `**subject:** Title` (bold L1) |
56
+ | `summary: ...` | `**doc_brief:** ...` |
57
+ | `# 📋 L1 · Métadonnées` | _(removed — metadata is on line 1)_ |
58
+ | `# 📝 L2 · Résumé` | `# L2 - Summary` |
59
+ | `# 🔧 L3 · Détails` | `# L3 - Details` |
60
+ | YAML frontmatter (`---`) | Replaced by line 1 + L1 block |
61
+ | `status: Vivant` | `status: Active` |
62
+ | `status: Terminé` | `status: Done` |
63
+
64
+ ### What it does NOT change
65
+
66
+ - **L2/L3 body content** — only headers are normalized, your content is untouched
67
+ - **Sub-headers** — `## Objective`, `## Key points` etc. are preserved as-is
68
+ - **`related_docs` paths** — kept on line 1 but not repointed if you move files
69
+ - **Files already in openclew format** — skipped entirely
70
+ - **`_INDEX.md`** — auto-generated, never touched
71
+
72
+ ---
73
+
74
+ ## Step by step
75
+
76
+ ### 1. Update openclew
77
+
78
+ ```bash
79
+ npm install -g openclew@latest
80
+ ```
81
+
82
+ ### 2. Check your docs
83
+
84
+ ```bash
85
+ openclew status
86
+ ```
87
+
88
+ Look for the "Legacy format" line. If it says 0, you're done.
89
+
90
+ ### 3. Preview changes
91
+
92
+ ```bash
93
+ openclew migrate
94
+ ```
95
+
96
+ This lists every file that would be converted. No files are modified.
97
+
98
+ ### 4. Apply
99
+
100
+ ```bash
101
+ openclew migrate --write
102
+ ```
103
+
104
+ Each converted file is printed with `✓`.
105
+
106
+ ### 5. Review and commit
107
+
108
+ ```bash
109
+ git diff # inspect the changes
110
+ openclew index # regenerate the index
111
+ git add doc/ && git commit -m "chore: migrate docs to openclew format"
112
+ ```
113
+
114
+ ### 6. Verify
115
+
116
+ ```bash
117
+ openclew status # should show 0 legacy docs
118
+ openclew migrate # should show "0 to migrate"
119
+ ```
120
+
121
+ ---
122
+
123
+ ## After migrating
124
+
125
+ - **New docs** you create with `openclew add ref` / `openclew add log` already
126
+ use the current format. No action needed.
127
+ - **Docs created by AI agents** will follow the format they see in your codebase.
128
+ Once your existing docs are migrated, agents will generate in the new format.
129
+ - **Empty `doc_brief`** — some old docs may have no brief after migration.
130
+ Run `openclew status` to find them and fill them in.
131
+
132
+ ---
133
+
134
+ ## Version-specific notes
135
+
136
+ ### → 0.4.0 (format migration)
137
+
138
+ First migration release. Converts from the legacy format (YAML frontmatter,
139
+ plain `key: value` L1, emoji headers) to the openclew format (condensed line 1,
140
+ bold L1 fields, clean headers).
141
+
142
+ **Scope**: line 1 + L1 block + L2/L3 main headers.
143
+
144
+ **Not in scope**: sub-header emojis, `related_docs` repointing, recursive
145
+ `doc/` subdirectory scanning (refdocs must be in `doc/_*.md`, not `doc/ref/`).
146
+
147
+ ---
148
+
149
+ ## Limitations
150
+
151
+ ### Flat `doc/` structure required
152
+
153
+ All openclew tools (search, index, status, migrate) scan `doc/_*.md` for refdocs
154
+ and `doc/log/*.md` for logs. Subdirectories like `doc/ref/` are not scanned yet.
155
+
156
+ If you plan to reorganize into subdirectories, wait for recursive scan support
157
+ (tracked in the openclew roadmap).
158
+
159
+ ### `related_docs` are not repointed
160
+
161
+ If a doc references `related_docs: [doc/_AUTH.md]` and you rename that file,
162
+ the reference breaks. `migrate` preserves paths as-is — manual update required.
163
+
164
+ ### Parsers are backward-compatible
165
+
166
+ Even without migrating, your docs are still readable by openclew tools.
167
+ Migration improves consistency and enables new features, but is not blocking.
package/bin/openclew.js CHANGED
@@ -9,39 +9,67 @@ const USAGE = `
9
9
  openclew — Long Life Memory for LLMs
10
10
 
11
11
  Usage:
12
- openclew init Set up openclew in the current project
13
- openclew new <title> Create a refdoc (evolves with the project)
14
- openclew log <title> Create a session log (frozen facts)
15
- openclew checkout End-of-session summary + log creation
16
- openclew index Regenerate doc/_INDEX.md
17
- openclew help Show this help
12
+ openclew init Set up openclew in your project
13
+ openclew add ref <title> Create a refdoc (evolves with the project)
14
+ openclew add log <title> Create a session log (frozen facts)
15
+ openclew search <query> Search docs by keyword
16
+ openclew checkout End-of-session summary
18
17
 
19
- Options:
20
- --no-hook Skip pre-commit hook installation (init)
21
- --no-inject Skip instruction file injection (init)
18
+ Run 'openclew help --all' for advanced commands.
19
+ More at: https://github.com/openclew/openclew
20
+ `.trim();
22
21
 
23
- Getting started:
24
- npx openclew init 1. Set up doc/ + guide + examples + git hook
25
- # Edit doc/_ARCHITECTURE.md 2. Replace the example with your project's architecture
26
- openclew new "API design" 3. Create your own refdocs
27
- git commit 4. Index auto-regenerates on commit
22
+ const USAGE_ALL = `
23
+ openclew Long Life Memory for LLMs
28
24
 
29
- Docs have 3 levels: L1 (metadata) → L2 (summary) → L3 (details).
30
- Agents read L1 to decide what's relevant, then L2 for context.
31
- More at: https://github.com/openclew/openclew
25
+ Usage:
26
+ openclew init Set up openclew in your project
27
+ openclew add ref <title> Create a refdoc (evolves with the project)
28
+ openclew add log <title> Create a session log (frozen facts)
29
+ openclew search <query> Search docs by keyword
30
+ openclew checkout End-of-session summary
31
+
32
+ Advanced:
33
+ openclew status Documentation health dashboard
34
+ openclew index Regenerate doc/_INDEX.md
35
+ openclew mcp Start MCP server (stdio JSON-RPC)
36
+
37
+ Options (init):
38
+ --no-hook Skip pre-commit hook installation
39
+ --no-inject Skip instruction file injection
32
40
  `.trim();
33
41
 
34
42
  if (!command || command === "help" || command === "--help" || command === "-h") {
35
- console.log(USAGE);
43
+ const showAll = args.includes("--all");
44
+ console.log(showAll ? USAGE_ALL : USAGE);
45
+ process.exit(0);
46
+ }
47
+
48
+ // Handle "add ref" / "add log" subcommands
49
+ if (command === "add") {
50
+ const sub = args[1];
51
+ if (sub === "ref") {
52
+ require("../lib/new-doc");
53
+ } else if (sub === "log") {
54
+ require("../lib/new-log");
55
+ } else {
56
+ console.error(`Unknown type: ${sub || "(none)"}`);
57
+ console.error('Usage: openclew add ref <title> or openclew add log <title>');
58
+ process.exit(1);
59
+ }
36
60
  process.exit(0);
37
61
  }
38
62
 
63
+ // Legacy aliases
39
64
  const commands = {
40
65
  init: () => require("../lib/init"),
41
66
  new: () => require("../lib/new-doc"),
42
67
  log: () => require("../lib/new-log"),
43
68
  checkout: () => require("../lib/checkout"),
69
+ search: () => require("../lib/search"),
70
+ status: () => require("../lib/status"),
44
71
  index: () => require("../lib/index-gen"),
72
+ mcp: () => require("../lib/mcp-server"),
45
73
  };
46
74
 
47
75
  if (!commands[command]) {
package/lib/index-gen.js CHANGED
@@ -1,40 +1,115 @@
1
1
  /**
2
2
  * openclew index — regenerate doc/_INDEX.md
3
3
  *
4
- * Wraps hooks/generate-index.py. Falls back to a JS implementation
5
- * if Python is not available.
4
+ * Pure JS implementation. Reuses parsers from search.js (SSOT).
5
+ * Zero dependencies Node 16+ standard library only.
6
6
  */
7
7
 
8
- const { execSync } = require("child_process");
9
8
  const fs = require("fs");
10
9
  const path = require("path");
10
+ const { collectDocs } = require("./search");
11
11
 
12
- const docDir = path.join(process.cwd(), "doc");
12
+ /**
13
+ * Generate _INDEX.md content from parsed docs.
14
+ *
15
+ * @param {string} docDir - Absolute path to doc/ directory
16
+ * @returns {string} Generated index content
17
+ */
18
+ function generateIndex(docDir) {
19
+ const docs = collectDocs(docDir);
20
+ const refdocs = docs.filter((d) => d.kind === "refdoc");
21
+ const logs = docs.filter((d) => d.kind === "log");
22
+
23
+ const now = new Date();
24
+ const timestamp = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
25
+
26
+ const lines = [
27
+ "# Project Knowledge Index",
28
+ "",
29
+ `> Auto-generated by [openclew](https://github.com/openclew/openclew) on ${timestamp}.`,
30
+ "> Do not edit manually — rebuilt from L1 metadata on every commit.",
31
+ "",
32
+ ];
33
+
34
+ // Refdocs section
35
+ lines.push("## Refdocs");
36
+ lines.push("");
37
+ if (refdocs.length) {
38
+ lines.push("| Document | Subject | Status | Category |");
39
+ lines.push("|----------|---------|--------|----------|");
40
+ for (const doc of refdocs) {
41
+ const name = path.basename(doc.filepath);
42
+ const subject = doc.meta.subject || "—";
43
+ const status = doc.meta.status || "—";
44
+ const category = doc.meta.category || "—";
45
+ const relPath = path.relative(path.dirname(docDir), doc.filepath);
46
+ lines.push(`| [${name}](${relPath}) | ${subject} | ${status} | ${category} |`);
47
+ }
48
+ } else {
49
+ lines.push("_No refdocs yet. Create one with `npx openclew add ref \"Title\"`._");
50
+ }
51
+ lines.push("");
52
+
53
+ // Logs section (last 20)
54
+ const displayLogs = logs.slice(0, 20);
55
+ lines.push("## Recent logs");
56
+ lines.push("");
57
+ if (displayLogs.length) {
58
+ lines.push("| Date | Subject | Status | Category |");
59
+ lines.push("|------|---------|--------|----------|");
60
+ for (const doc of displayLogs) {
61
+ const date = doc.meta.date || path.basename(doc.filepath).slice(0, 10);
62
+ const subject = doc.meta.subject || "—";
63
+ const status = doc.meta.status || "—";
64
+ const category = doc.meta.category || "—";
65
+ const relPath = path.relative(path.dirname(docDir), doc.filepath);
66
+ lines.push(`| ${date} | [${subject}](${relPath}) | ${status} | ${category} |`);
67
+ }
68
+ if (logs.length > 20) {
69
+ lines.push("");
70
+ lines.push(`_${logs.length - 20} older logs not shown._`);
71
+ }
72
+ } else {
73
+ lines.push("_No logs yet. Create one with `npx openclew add log \"Title\"`._");
74
+ }
75
+ lines.push("");
13
76
 
14
- if (!fs.existsSync(docDir)) {
15
- console.error("No doc/ directory found. Run 'openclew init' first.");
16
- process.exit(1);
77
+ // Stats
78
+ lines.push("---");
79
+ lines.push(`**${refdocs.length}** refdocs, **${logs.length}** logs.`);
80
+ lines.push("");
81
+
82
+ return lines.join("\n");
17
83
  }
18
84
 
19
- // Try local generate-index.py first
20
- const localScript = path.join(docDir, "generate-index.py");
21
- const packageScript = path.join(__dirname, "..", "hooks", "generate-index.py");
22
- const script = fs.existsSync(localScript) ? localScript : packageScript;
23
-
24
- if (fs.existsSync(script)) {
25
- try {
26
- const output = execSync(`python3 "${script}" "${docDir}"`, {
27
- encoding: "utf-8",
28
- });
29
- console.log(output.trim());
30
- process.exit(0);
31
- } catch {
32
- console.error(
33
- "python3 not available. Install Python 3.8+ or regenerate manually."
34
- );
85
+ /**
86
+ * Write _INDEX.md to disk.
87
+ *
88
+ * @param {string} docDir - Absolute path to doc/ directory
89
+ * @returns {{ refdocs: number, logs: number }} Counts
90
+ */
91
+ function writeIndex(docDir) {
92
+ const content = generateIndex(docDir);
93
+ const indexPath = path.join(docDir, "_INDEX.md");
94
+ fs.writeFileSync(indexPath, content, "utf-8");
95
+
96
+ const docs = collectDocs(docDir);
97
+ const refdocs = docs.filter((d) => d.kind === "refdoc").length;
98
+ const logs = docs.filter((d) => d.kind === "log").length;
99
+ return { refdocs, logs };
100
+ }
101
+
102
+ // CLI runner
103
+ if (require.main === module || process.argv.includes("index")) {
104
+ const docDir = process.argv[2] || path.join(process.cwd(), "doc");
105
+
106
+ if (!fs.existsSync(docDir)) {
107
+ console.error("No doc/ directory found. Run 'openclew init' first.");
35
108
  process.exit(1);
36
109
  }
110
+
111
+ const { refdocs, logs } = writeIndex(docDir);
112
+ console.log(`Generated doc/_INDEX.md (${refdocs} refdocs, ${logs} logs)`);
37
113
  }
38
114
 
39
- console.error("generate-index.py not found. Run 'openclew init' first.");
40
- process.exit(1);
115
+ module.exports = { generateIndex, writeIndex };
package/lib/init.js CHANGED
@@ -15,7 +15,7 @@ const readline = require("readline");
15
15
  const { detectInstructionFiles, findAgentsMdCaseInsensitive } = require("./detect");
16
16
  const { inject, isAlreadyInjected } = require("./inject");
17
17
  const { writeConfig } = require("./config");
18
- const { guideContent, exampleRefdocContent, exampleLogContent, today } = require("./templates");
18
+ const { guideContent, frameworkIntegrationContent, exampleRefdocContent, exampleLogContent, today } = require("./templates");
19
19
 
20
20
  const PROJECT_ROOT = process.cwd();
21
21
  const DOC_DIR = path.join(PROJECT_ROOT, "doc");
@@ -126,8 +126,8 @@ function installPreCommitHook() {
126
126
  }
127
127
 
128
128
  const preCommitPath = path.join(hooksDir, "pre-commit");
129
- const indexScript = `if [ -f doc/generate-index.py ]; then
130
- python3 doc/generate-index.py doc 2>/dev/null || echo "openclew: index generation failed"
129
+ const indexScript = `if command -v npx >/dev/null 2>&1; then
130
+ npx --yes openclew index 2>/dev/null || echo "openclew: index generation failed"
131
131
  git add doc/_INDEX.md 2>/dev/null
132
132
  fi`;
133
133
 
@@ -168,26 +168,19 @@ function updateGitignore() {
168
168
  }
169
169
  }
170
170
 
171
- function copyGenerateIndex() {
172
- const src = path.join(__dirname, "..", "hooks", "generate-index.py");
173
- const dst = path.join(DOC_DIR, "generate-index.py");
174
-
175
- if (fs.existsSync(dst)) {
176
- console.log(" doc/generate-index.py already exists");
177
- return false;
178
- }
179
-
180
- if (fs.existsSync(src)) {
181
- fs.copyFileSync(src, dst);
182
- console.log(" Copied generate-index.py to doc/");
171
+ function cleanupLegacyPython() {
172
+ // Remove legacy generate-index.py if present (replaced by JS-native index-gen)
173
+ const legacyScript = path.join(DOC_DIR, "generate-index.py");
174
+ if (fs.existsSync(legacyScript)) {
175
+ fs.unlinkSync(legacyScript);
176
+ console.log(" Removed legacy doc/generate-index.py (now JS-native)");
183
177
  return true;
184
178
  }
185
-
186
- console.log(" generate-index.py not found in package — skipping");
179
+ console.log(" No legacy Python script to clean up");
187
180
  return false;
188
181
  }
189
182
 
190
- function createDocs() {
183
+ function createDocs(entryPointPath) {
191
184
  // Guide — always created
192
185
  const guidePath = path.join(DOC_DIR, "_USING_OPENCLEW.md");
193
186
  if (!fs.existsSync(guidePath)) {
@@ -197,11 +190,30 @@ function createDocs() {
197
190
  console.log(" doc/_USING_OPENCLEW.md already exists");
198
191
  }
199
192
 
200
- // Example refdoc
193
+ // Framework integration guide
194
+ const frameworkPath = path.join(DOC_DIR, "_OPENCLEW_FRAMEWORK_INTEGRATION.md");
195
+ if (!fs.existsSync(frameworkPath)) {
196
+ fs.writeFileSync(frameworkPath, frameworkIntegrationContent(), "utf-8");
197
+ console.log(" Created doc/_OPENCLEW_FRAMEWORK_INTEGRATION.md (framework integration guide)");
198
+ } else {
199
+ console.log(" doc/_OPENCLEW_FRAMEWORK_INTEGRATION.md already exists");
200
+ }
201
+
202
+ // Architecture refdoc — seeded from existing instruction file if available
201
203
  const examplePath = path.join(DOC_DIR, "_ARCHITECTURE.md");
202
204
  if (!fs.existsSync(examplePath)) {
203
- fs.writeFileSync(examplePath, exampleRefdocContent(), "utf-8");
204
- console.log(" Created doc/_ARCHITECTURE.md (example refdoc)");
205
+ let existingInstructions = null;
206
+ if (entryPointPath && fs.existsSync(entryPointPath)) {
207
+ try {
208
+ existingInstructions = fs.readFileSync(entryPointPath, "utf-8");
209
+ } catch {}
210
+ }
211
+ fs.writeFileSync(examplePath, exampleRefdocContent(existingInstructions), "utf-8");
212
+ if (existingInstructions) {
213
+ console.log(" Created doc/_ARCHITECTURE.md (seeded from instruction file)");
214
+ } else {
215
+ console.log(" Created doc/_ARCHITECTURE.md (template)");
216
+ }
205
217
  } else {
206
218
  console.log(" doc/_ARCHITECTURE.md already exists");
207
219
  }
@@ -217,15 +229,14 @@ function createDocs() {
217
229
  }
218
230
 
219
231
  function runIndexGenerator() {
220
- const indexScript = path.join(DOC_DIR, "generate-index.py");
221
- if (!fs.existsSync(indexScript)) return;
232
+ if (!fs.existsSync(DOC_DIR)) return;
222
233
 
223
234
  try {
224
- const { execSync } = require("child_process");
225
- execSync(`python3 "${indexScript}" "${DOC_DIR}"`, { stdio: "pipe" });
226
- console.log(" Generated doc/_INDEX.md");
227
- } catch {
228
- console.log(" Could not generate index (python3 not available)");
235
+ const { writeIndex } = require("./index-gen");
236
+ const { refdocs, logs } = writeIndex(DOC_DIR);
237
+ console.log(` Generated doc/_INDEX.md (${refdocs} refdocs, ${logs} logs)`);
238
+ } catch (err) {
239
+ console.log(` Could not generate index: ${err.message}`);
229
240
  }
230
241
  }
231
242
 
@@ -240,9 +251,9 @@ async function main() {
240
251
  console.log("\n2. Gitignore");
241
252
  updateGitignore();
242
253
 
243
- // Step 3: Copy index generator
254
+ // Step 3: Cleanup legacy Python (if upgrading from older version)
244
255
  console.log("\n3. Index generator");
245
- copyGenerateIndex();
256
+ cleanupLegacyPython();
246
257
 
247
258
  // Step 4: Entry point
248
259
  console.log("\n4. Entry point");
@@ -273,7 +284,7 @@ async function main() {
273
284
 
274
285
  // Step 6: Docs
275
286
  console.log("\n6. Docs");
276
- createDocs();
287
+ createDocs(entryPoint ? entryPoint.fullPath : null);
277
288
 
278
289
  // Step 7: Generate index
279
290
  console.log("\n7. Index");
package/lib/inject.js CHANGED
@@ -7,17 +7,26 @@ const fs = require("fs");
7
7
  const OPENCLEW_BLOCK = `
8
8
  ## Project knowledge (openclew)
9
9
 
10
- This file is the **entry point** for project documentation.
10
+ This project uses \`doc/\` as its knowledge base. Before starting any task:
11
11
 
12
- **Doc-first rule:** before any task, read \`doc/_INDEX.md\` to find docs related to the task. Read them before exploring code.
12
+ 1. **Read \`doc/_INDEX.md\`** it lists all available docs with a one-line summary each
13
+ 2. **Pick your reference doc(s)** — choose one or more docs relevant to what you're about to do
14
+ 3. **Read them** (L1 for relevance, L2 for context) — then start working
15
+ 4. **No matching doc?** — propose creating a refdoc with \`npx openclew new "Title"\` before starting
13
16
 
14
- Two types of docs in \`doc/\`:
15
- - **Refdocs** (\`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
+ If a doc contains placeholder comments (\`<!-- ... -->\`), fill them in based on what you observe in the code. This is expected — the docs are meant to be written by you.
17
18
 
18
- Each doc has 3 levels: **L1** (metadata — read first to decide relevance) → **L2** (summary) → **L3** (full details, only when needed).
19
+ Two types of docs:
20
+ - **Refdocs** (\`doc/_*.md\`) — architecture, conventions, decisions (evolve over time)
21
+ - **Logs** (\`doc/log/YYYY-MM-DD_*.md\`) — frozen facts from past sessions
19
22
 
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\`.
23
+ Each doc has 3 levels: **L1** (subject + brief 1 line) **L2** (summary) **L3** (full details, only when needed).
24
+
25
+ **Session commands** (user asks in chat, you run):
26
+ - "checkout" → \`npx openclew checkout\` (end-of-session summary + log)
27
+ - "new doc about X" → \`npx openclew new "X"\` (create refdoc)
28
+ - "search X" → \`npx openclew search "X"\` (search docs)
29
+ - "doc status" → \`npx openclew status\` (health dashboard)
21
30
  `.trim();
22
31
 
23
32
  const MARKER_START = "<!-- openclew_START -->";