openclew 0.2.1 → 0.4.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/LICENSE +190 -21
- package/README.md +40 -3
- package/UPGRADING.md +167 -0
- package/bin/openclew.js +49 -18
- package/commands/oc-checkout.md +134 -0
- package/commands/oc-init.md +27 -0
- package/commands/oc-peek.md +41 -0
- package/commands/oc-search.md +25 -0
- package/commands/oc-status.md +20 -0
- package/lib/checkout.js +2 -4
- package/lib/index-gen.js +100 -25
- package/lib/init.js +103 -31
- package/lib/inject.js +17 -7
- package/lib/mcp-server.js +313 -0
- package/lib/new-doc.js +12 -4
- package/lib/new-log.js +4 -4
- package/lib/peek.js +166 -0
- package/lib/search.js +242 -0
- package/lib/status.js +151 -0
- package/lib/templates.js +193 -13
- package/package.json +15 -3
- package/skills/oc-checkpoint/SKILL.md +36 -0
- package/skills/oc-init/SKILL.md +49 -0
- package/skills/oc-search/SKILL.md +45 -0
- package/templates/FORMAT.md +300 -0
- package/templates/log.md +1 -1
- package/templates/onboarding/flow.md +59 -0
- package/templates/onboarding/scaffold_index.md +31 -0
- package/templates/refdoc.md +1 -1
- package/hooks/generate-index.py +0 -226
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<!-- openclew-managed -->
|
|
2
|
+
# oc-init — Set up openclew in the current project
|
|
3
|
+
|
|
4
|
+
Initialize structured documentation so AI agents and humans navigate project knowledge efficiently.
|
|
5
|
+
|
|
6
|
+
**Usage:** `/oc-init`
|
|
7
|
+
|
|
8
|
+
## Sequence
|
|
9
|
+
|
|
10
|
+
1. Run `npx openclew init`
|
|
11
|
+
2. Display what was created
|
|
12
|
+
3. Read the generated guide (`doc/_USING_OPENCLEW.md`) to understand the setup
|
|
13
|
+
4. Propose creating a first architecture doc:
|
|
14
|
+
- "Want me to create `doc/_ARCHITECTURE.md` based on the current project structure?"
|
|
15
|
+
- If yes: analyze the project (main dirs, stack, key files) and fill in the template
|
|
16
|
+
|
|
17
|
+
## After setup
|
|
18
|
+
|
|
19
|
+
The agent will now consult `doc/_INDEX.md` before starting tasks. Available commands:
|
|
20
|
+
|
|
21
|
+
- `/oc-search <query>` — Search existing docs
|
|
22
|
+
- `/oc-status` — Health dashboard
|
|
23
|
+
- `/oc-checkout` — End-of-session summary
|
|
24
|
+
|
|
25
|
+
To add knowledge manually:
|
|
26
|
+
- `npx openclew add ref "Title"` — Create a reference doc
|
|
27
|
+
- `npx openclew add log "Title"` — Create a session log
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!-- openclew-managed -->
|
|
2
|
+
# oc-peek — Discover project knowledge before working
|
|
3
|
+
|
|
4
|
+
First reflex before exploring a project: shows the instruction file and lists all available docs.
|
|
5
|
+
|
|
6
|
+
**Usage:** `/oc-peek` (no arguments, uses the current project)
|
|
7
|
+
|
|
8
|
+
## Sequence
|
|
9
|
+
|
|
10
|
+
### Step 1: Run the CLI
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx openclew peek
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
This lists:
|
|
17
|
+
- The instruction file (CLAUDE.md / AGENTS.md) path
|
|
18
|
+
- All refdocs in `doc/` with their subjects
|
|
19
|
+
- All `_*.md` files outside `doc/` (prompts, scripts, etc.)
|
|
20
|
+
- Subdirectories of `doc/`
|
|
21
|
+
|
|
22
|
+
### Step 2: Display the instruction file
|
|
23
|
+
|
|
24
|
+
Read the instruction file (CLAUDE.md or AGENTS.md) and display it **in full** — do not summarize.
|
|
25
|
+
|
|
26
|
+
### Step 3: Display the refdoc list
|
|
27
|
+
|
|
28
|
+
Display the CLI output as-is. This is a **listing only** — do not read the refdocs at this stage.
|
|
29
|
+
|
|
30
|
+
## Rules
|
|
31
|
+
|
|
32
|
+
- **Do not summarize** the instruction file — display it integrally
|
|
33
|
+
- **Do not read** the refdocs — list file names only
|
|
34
|
+
- If no instruction file exists: indicate `(no instruction file found)`
|
|
35
|
+
- If no `doc/` directory exists: indicate `(no doc/ directory)`
|
|
36
|
+
|
|
37
|
+
## Related commands
|
|
38
|
+
|
|
39
|
+
- `/oc-search <query>` — Search docs by keyword
|
|
40
|
+
- `/oc-status` — Documentation health dashboard
|
|
41
|
+
- `/oc-checkout` — End-of-session summary
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!-- openclew-managed -->
|
|
2
|
+
# oc-search — Search project documentation
|
|
3
|
+
|
|
4
|
+
Search your project's knowledge base by keyword.
|
|
5
|
+
|
|
6
|
+
**Usage:** `/oc-search <query>`
|
|
7
|
+
|
|
8
|
+
## Sequence
|
|
9
|
+
|
|
10
|
+
1. Run `npx openclew search "$ARGUMENTS"` to get results
|
|
11
|
+
2. Display results to the user
|
|
12
|
+
3. If results found: propose to read the most relevant doc(s) at L2 level
|
|
13
|
+
4. If no results: suggest alternative keywords or propose creating a new doc
|
|
14
|
+
|
|
15
|
+
## Reading results
|
|
16
|
+
|
|
17
|
+
After finding a doc, read it progressively:
|
|
18
|
+
- **L1** (between `L1_START`/`L1_END`) — subject + brief, ~40 tokens. "Should I read this?"
|
|
19
|
+
- **L2** (between `L2_START`/`L2_END`) — summary, essential context
|
|
20
|
+
- **L3** (between `L3_START`/`L3_END`) — full details, only when deep-diving
|
|
21
|
+
|
|
22
|
+
## Related commands
|
|
23
|
+
|
|
24
|
+
- `/oc-status` — Health dashboard (missing briefs, stale docs)
|
|
25
|
+
- `/oc-checkout` — End-of-session summary
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!-- openclew-managed -->
|
|
2
|
+
# oc-status — Documentation health dashboard
|
|
3
|
+
|
|
4
|
+
Display the health status of project documentation.
|
|
5
|
+
|
|
6
|
+
**Usage:** `/oc-status`
|
|
7
|
+
|
|
8
|
+
## Sequence
|
|
9
|
+
|
|
10
|
+
1. Run `npx openclew status` to get the dashboard
|
|
11
|
+
2. Display results to the user
|
|
12
|
+
3. If issues found, propose actions:
|
|
13
|
+
- **Missing doc_brief**: "These docs have empty briefs — want me to fill them in?"
|
|
14
|
+
- **Stale docs**: "These docs haven't been updated in a while — want me to review them?"
|
|
15
|
+
- **No recent logs**: "No log created recently — want me to create one for this session?"
|
|
16
|
+
|
|
17
|
+
## Related commands
|
|
18
|
+
|
|
19
|
+
- `/oc-search <query>` — Search docs by keyword
|
|
20
|
+
- `/oc-checkout` — End-of-session summary (also creates logs)
|
package/lib/checkout.js
CHANGED
|
@@ -253,11 +253,9 @@ ${commitList}
|
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
function regenerateIndex() {
|
|
256
|
-
const indexScript = path.join(DOC_DIR, "generate-index.py");
|
|
257
|
-
if (!fs.existsSync(indexScript)) return;
|
|
258
|
-
|
|
259
256
|
try {
|
|
260
|
-
|
|
257
|
+
const { writeIndex } = require("./index-gen");
|
|
258
|
+
writeIndex(DOC_DIR);
|
|
261
259
|
console.log(" 📋 Regenerated doc/_INDEX.md");
|
|
262
260
|
} catch {
|
|
263
261
|
// Silent — index will be regenerated on next commit anyway
|
package/lib/index-gen.js
CHANGED
|
@@ -1,40 +1,115 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* openclew index — regenerate doc/_INDEX.md
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
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
|
|
130
|
-
|
|
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
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
console.log(" doc/generate-index.py
|
|
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
|
-
//
|
|
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
|
-
|
|
204
|
-
|
|
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,66 @@ function createDocs() {
|
|
|
217
229
|
}
|
|
218
230
|
|
|
219
231
|
function runIndexGenerator() {
|
|
220
|
-
|
|
221
|
-
if (!fs.existsSync(indexScript)) return;
|
|
232
|
+
if (!fs.existsSync(DOC_DIR)) return;
|
|
222
233
|
|
|
223
234
|
try {
|
|
224
|
-
const {
|
|
225
|
-
|
|
226
|
-
console.log(
|
|
227
|
-
} catch {
|
|
228
|
-
console.log(
|
|
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}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function installSlashCommands() {
|
|
244
|
+
const home = process.env.HOME || process.env.USERPROFILE;
|
|
245
|
+
if (!home) {
|
|
246
|
+
console.log(" Cannot determine home directory — skipping");
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const claudeCommandsDir = path.join(home, ".claude", "commands");
|
|
251
|
+
if (!fs.existsSync(path.join(home, ".claude"))) {
|
|
252
|
+
console.log(" No ~/.claude/ found (Claude Code not installed) — skipping");
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (!fs.existsSync(claudeCommandsDir)) {
|
|
257
|
+
fs.mkdirSync(claudeCommandsDir, { recursive: true });
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Find commands/ dir relative to this package
|
|
261
|
+
const pkgCommandsDir = path.join(__dirname, "..", "commands");
|
|
262
|
+
if (!fs.existsSync(pkgCommandsDir)) {
|
|
263
|
+
console.log(" No commands/ directory in package — skipping");
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const MARKER = "<!-- openclew-managed -->";
|
|
268
|
+
const files = fs.readdirSync(pkgCommandsDir).filter((f) => f.endsWith(".md"));
|
|
269
|
+
let installed = 0;
|
|
270
|
+
|
|
271
|
+
for (const file of files) {
|
|
272
|
+
const dest = path.join(claudeCommandsDir, file);
|
|
273
|
+
|
|
274
|
+
// Only overwrite if file has the managed marker (or doesn't exist)
|
|
275
|
+
if (fs.existsSync(dest)) {
|
|
276
|
+
const existing = fs.readFileSync(dest, "utf-8");
|
|
277
|
+
if (!existing.includes(MARKER)) {
|
|
278
|
+
console.log(` Skipped ${file} (user-modified)`);
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
fs.copyFileSync(path.join(pkgCommandsDir, file), dest);
|
|
284
|
+
installed++;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (installed > 0) {
|
|
288
|
+
console.log(` Installed ${installed} slash command(s) → ~/.claude/commands/`);
|
|
289
|
+
console.log(" Available: /oc-checkout, /oc-search, /oc-init, /oc-status");
|
|
290
|
+
} else {
|
|
291
|
+
console.log(" Slash commands already up to date");
|
|
229
292
|
}
|
|
230
293
|
}
|
|
231
294
|
|
|
@@ -240,9 +303,9 @@ async function main() {
|
|
|
240
303
|
console.log("\n2. Gitignore");
|
|
241
304
|
updateGitignore();
|
|
242
305
|
|
|
243
|
-
// Step 3:
|
|
306
|
+
// Step 3: Cleanup legacy Python (if upgrading from older version)
|
|
244
307
|
console.log("\n3. Index generator");
|
|
245
|
-
|
|
308
|
+
cleanupLegacyPython();
|
|
246
309
|
|
|
247
310
|
// Step 4: Entry point
|
|
248
311
|
console.log("\n4. Entry point");
|
|
@@ -273,12 +336,21 @@ async function main() {
|
|
|
273
336
|
|
|
274
337
|
// Step 6: Docs
|
|
275
338
|
console.log("\n6. Docs");
|
|
276
|
-
createDocs();
|
|
339
|
+
createDocs(entryPoint ? entryPoint.fullPath : null);
|
|
277
340
|
|
|
278
341
|
// Step 7: Generate index
|
|
279
342
|
console.log("\n7. Index");
|
|
280
343
|
runIndexGenerator();
|
|
281
344
|
|
|
345
|
+
// Step 8: Install Claude Code slash commands
|
|
346
|
+
const noCommands = args.includes("--no-commands");
|
|
347
|
+
console.log("\n8. Slash commands");
|
|
348
|
+
if (noCommands) {
|
|
349
|
+
console.log(" Skipping (--no-commands)");
|
|
350
|
+
} else {
|
|
351
|
+
installSlashCommands();
|
|
352
|
+
}
|
|
353
|
+
|
|
282
354
|
// Done
|
|
283
355
|
console.log("\n─── Ready ───\n");
|
|
284
356
|
if (entryPoint) {
|
package/lib/inject.js
CHANGED
|
@@ -7,17 +7,27 @@ const fs = require("fs");
|
|
|
7
7
|
const OPENCLEW_BLOCK = `
|
|
8
8
|
## Project knowledge (openclew)
|
|
9
9
|
|
|
10
|
-
This
|
|
10
|
+
This project uses \`doc/\` as its knowledge base. Before starting any task:
|
|
11
11
|
|
|
12
|
-
**
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
- "peek" → \`npx openclew peek\` (list instruction file + all refdocs)
|
|
27
|
+
- "checkout" → \`npx openclew checkout\` (end-of-session summary + log)
|
|
28
|
+
- "new doc about X" → \`npx openclew new "X"\` (create refdoc)
|
|
29
|
+
- "search X" → \`npx openclew search "X"\` (search docs)
|
|
30
|
+
- "doc status" → \`npx openclew status\` (health dashboard)
|
|
21
31
|
`.trim();
|
|
22
32
|
|
|
23
33
|
const MARKER_START = "<!-- openclew_START -->";
|