@doquflow/cli 0.4.5 → 0.4.6
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/dist/commands/init.js +116 -3
- package/package.json +2 -2
package/dist/commands/init.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.buildClaudeMd = buildClaudeMd;
|
|
7
|
+
exports.buildAgentsMd = buildAgentsMd;
|
|
7
8
|
exports.run = run;
|
|
8
9
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
10
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
@@ -32,6 +33,9 @@ function getVSCodeMcpConfigPath() {
|
|
|
32
33
|
function getCopilotCliMcpConfigPath() {
|
|
33
34
|
return node_path_1.default.join(node_os_1.default.homedir(), ".copilot", "mcp-config.json");
|
|
34
35
|
}
|
|
36
|
+
function getCodexConfigPath() {
|
|
37
|
+
return node_path_1.default.join(node_os_1.default.homedir(), ".codex", "config.toml");
|
|
38
|
+
}
|
|
35
39
|
function resolveServerBin() {
|
|
36
40
|
// Try npm-installed package first
|
|
37
41
|
try {
|
|
@@ -161,10 +165,98 @@ async function writeClaudeMd(projectDir) {
|
|
|
161
165
|
await promises_1.default.writeFile(claudeMdPath, newSection, "utf8");
|
|
162
166
|
}
|
|
163
167
|
}
|
|
168
|
+
function buildAgentsMd(projectDir) {
|
|
169
|
+
return `# DocuFlow — AI Documentation Assistant
|
|
170
|
+
|
|
171
|
+
DocuFlow is an MCP server that provides structured access to this codebase and maintains a living wiki.
|
|
172
|
+
It is registered via \`.codex/config.toml\` and available as MCP tools in every Codex session.
|
|
173
|
+
|
|
174
|
+
## Available MCP Tools
|
|
175
|
+
|
|
176
|
+
### Codebase Scanner
|
|
177
|
+
- **read_module** — Analyse a single file: language, classes, functions, dependencies, DB tables, endpoints, config refs, raw content.
|
|
178
|
+
- \`read_module({ path: "src/UserService.cs" })\`
|
|
179
|
+
- **list_modules** — Walk a directory, extract facts for every file. One call to understand the whole project.
|
|
180
|
+
- \`list_modules({ path: "${projectDir}" })\`
|
|
181
|
+
- **write_spec** — Save a markdown spec to \`.docuflow/specs/<name>.md\`.
|
|
182
|
+
- \`write_spec({ project_path: "${projectDir}", filename: "UserService", content: "..." })\`
|
|
183
|
+
- **read_specs** — Read saved specs, optionally filtered by name.
|
|
184
|
+
- \`read_specs({ project_path: "${projectDir}" })\`
|
|
185
|
+
|
|
186
|
+
### Wiki Pipeline
|
|
187
|
+
- **ingest_source** — Ingest a markdown file from \`.docuflow/sources/\` into the wiki (entities, concepts).
|
|
188
|
+
- **update_index** — Rebuild \`.docuflow/index.md\` from all wiki pages.
|
|
189
|
+
- **list_wiki** — List all wiki pages by category (entity/concept/timeline/synthesis).
|
|
190
|
+
- **wiki_search** — BM25 search across all wiki pages.
|
|
191
|
+
- **query_wiki** — Q&A: searches wiki, synthesises an answer, returns citations.
|
|
192
|
+
- \`query_wiki({ project_path: "${projectDir}", question: "How does auth work?" })\`
|
|
193
|
+
- **synthesize_answer** — Generate a markdown synthesis from a list of page IDs.
|
|
194
|
+
- **save_answer_as_page** — Persist a synthesis as a wiki page.
|
|
195
|
+
|
|
196
|
+
### Health & Guidance
|
|
197
|
+
- **lint_wiki** — Health check: orphan pages, broken refs, stale content. Returns a 0–100 health score.
|
|
198
|
+
- **get_schema_guidance** — Recommend what wiki pages should exist based on schema + current state.
|
|
199
|
+
- **preview_generation** — Preview what a tool will generate before running it.
|
|
200
|
+
|
|
201
|
+
## Common Workflows
|
|
202
|
+
|
|
203
|
+
Start here — understand the codebase:
|
|
204
|
+
\`\`\`
|
|
205
|
+
list_modules({ path: "${projectDir}" })
|
|
206
|
+
→ write_spec for important modules
|
|
207
|
+
\`\`\`
|
|
208
|
+
|
|
209
|
+
Answer a question:
|
|
210
|
+
\`\`\`
|
|
211
|
+
query_wiki({ project_path: "${projectDir}", question: "..." })
|
|
212
|
+
\`\`\`
|
|
213
|
+
|
|
214
|
+
Maintain wiki health:
|
|
215
|
+
\`\`\`
|
|
216
|
+
lint_wiki({ project_path: "${projectDir}" })
|
|
217
|
+
\`\`\`
|
|
218
|
+
|
|
219
|
+
## Storage Layout
|
|
220
|
+
|
|
221
|
+
\`\`\`
|
|
222
|
+
.docuflow/
|
|
223
|
+
├── specs/ Code specs written by write_spec
|
|
224
|
+
├── wiki/ LLM-generated wiki pages
|
|
225
|
+
│ ├── entities/
|
|
226
|
+
│ ├── concepts/
|
|
227
|
+
│ ├── timelines/
|
|
228
|
+
│ └── syntheses/
|
|
229
|
+
├── sources/ Raw markdown docs to ingest
|
|
230
|
+
├── schema.md Wiki configuration (edit to customise)
|
|
231
|
+
├── index.md Auto-maintained catalog
|
|
232
|
+
└── log.md Operation log
|
|
233
|
+
\`\`\`
|
|
234
|
+
`;
|
|
235
|
+
}
|
|
236
|
+
async function writeAgentsMd(projectDir) {
|
|
237
|
+
const agentsMdPath = node_path_1.default.join(projectDir, "AGENTS.md");
|
|
238
|
+
const newSection = buildAgentsMd(projectDir);
|
|
239
|
+
if (node_fs_1.default.existsSync(agentsMdPath)) {
|
|
240
|
+
const existing = await promises_1.default.readFile(agentsMdPath, "utf8");
|
|
241
|
+
if (existing.includes("DocuFlow")) {
|
|
242
|
+
// Replace existing DocuFlow section
|
|
243
|
+
const withoutDocuflow = existing.replace(/\n?# DocuFlow[\s\S]*/, "").trimEnd();
|
|
244
|
+
await promises_1.default.writeFile(agentsMdPath, withoutDocuflow + "\n\n" + newSection, "utf8");
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
// Append to existing AGENTS.md
|
|
248
|
+
await promises_1.default.appendFile(agentsMdPath, "\n\n" + newSection, "utf8");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
await promises_1.default.writeFile(agentsMdPath, newSection, "utf8");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
164
255
|
async function run() {
|
|
165
256
|
const configPath = getClaudeDesktopConfigPath();
|
|
166
257
|
const vscodeConfigPath = getVSCodeMcpConfigPath();
|
|
167
258
|
const copilotCliConfigPath = getCopilotCliMcpConfigPath();
|
|
259
|
+
const codexConfigPath = getCodexConfigPath();
|
|
168
260
|
const serverBin = resolveServerBin();
|
|
169
261
|
const nodeBin = process.execPath;
|
|
170
262
|
// Register in Claude Desktop config
|
|
@@ -223,6 +315,24 @@ async function run() {
|
|
|
223
315
|
catch {
|
|
224
316
|
// Copilot CLI not installed — skip silently
|
|
225
317
|
}
|
|
318
|
+
// Register in OpenAI Codex CLI (~/.codex/config.toml in TOML format)
|
|
319
|
+
let codexCliRegistered = false;
|
|
320
|
+
try {
|
|
321
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(codexConfigPath), { recursive: true });
|
|
322
|
+
let tomlContent = "";
|
|
323
|
+
try {
|
|
324
|
+
tomlContent = await promises_1.default.readFile(codexConfigPath, "utf8");
|
|
325
|
+
}
|
|
326
|
+
catch { /* new file */ }
|
|
327
|
+
if (!tomlContent.includes("[mcp_servers.docuflow]")) {
|
|
328
|
+
const entry = `\n[mcp_servers.docuflow]\ncommand = "${nodeBin}"\nargs = [${JSON.stringify(serverBin)}]\n`;
|
|
329
|
+
await promises_1.default.writeFile(codexConfigPath, tomlContent + entry, "utf8");
|
|
330
|
+
}
|
|
331
|
+
codexCliRegistered = true;
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
// Codex CLI not installed — skip silently
|
|
335
|
+
}
|
|
226
336
|
// Create .docuflow/ directory structure
|
|
227
337
|
const projectDir = process.cwd();
|
|
228
338
|
const docuflowDir = node_path_1.default.join(projectDir, ".docuflow");
|
|
@@ -245,6 +355,8 @@ async function run() {
|
|
|
245
355
|
await copyTemplateFile("log.md", node_path_1.default.join(docuflowDir, "log.md"));
|
|
246
356
|
// Generate CLAUDE.md so Claude Code picks up DocuFlow automatically
|
|
247
357
|
await writeClaudeMd(projectDir);
|
|
358
|
+
// Generate AGENTS.md so OpenAI Codex picks up DocuFlow automatically
|
|
359
|
+
await writeAgentsMd(projectDir);
|
|
248
360
|
// Write .vscode/mcp.json for project-level workspace MCP config (shareable via git)
|
|
249
361
|
// Uses npx so it works on any machine — safe to commit
|
|
250
362
|
const vscodeDirPath = node_path_1.default.join(projectDir, ".vscode");
|
|
@@ -289,14 +401,15 @@ async function run() {
|
|
|
289
401
|
console.log(` \u251c\u2500\u2500 index.md (auto-maintained catalog)`);
|
|
290
402
|
console.log(` \u2514\u2500\u2500 log.md (operation log)`);
|
|
291
403
|
console.log("");
|
|
292
|
-
console.log("\ud83d\udcdd
|
|
293
|
-
console.log(`
|
|
294
|
-
console.log(`
|
|
404
|
+
console.log("\ud83d\udcdd Instruction files:");
|
|
405
|
+
console.log(` CLAUDE.md ✓ ${node_path_1.default.join(projectDir, "CLAUDE.md")}`);
|
|
406
|
+
console.log(` AGENTS.md ✓ ${node_path_1.default.join(projectDir, "AGENTS.md")}`);
|
|
295
407
|
console.log("");
|
|
296
408
|
console.log("\ud83d\udd27 MCP Registration:");
|
|
297
409
|
console.log(` Claude Desktop: \u2713 registered`);
|
|
298
410
|
console.log(` VS Code Copilot: ${vscodeRegistered ? "\u2713 registered (user-level)" : "\u2014 not detected"}`);
|
|
299
411
|
console.log(` Copilot CLI: ${copilotCliRegistered ? "\u2713 registered (~/.copilot/mcp-config.json)" : "\u2014 not detected"}`);
|
|
412
|
+
console.log(` Codex CLI: ${codexCliRegistered ? "\u2713 registered (~/.codex/config.toml)" : "\u2014 not detected"}`);
|
|
300
413
|
console.log(` Workspace: \u2713 .vscode/mcp.json written (commit to share with team)`);
|
|
301
414
|
console.log("");
|
|
302
415
|
console.log("\ud83d\udcd6 Next steps:");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doquflow/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "CLI for setting up Docuflow in your project",
|
|
5
5
|
"author": "Docuflow <hello@doquflows.dev>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"build": "tsc"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@doquflow/server": "0.4.
|
|
33
|
+
"@doquflow/server": "0.4.6"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^22.0.0",
|