@doquflow/cli 0.4.4 → 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.
Files changed (2) hide show
  1. package/dist/commands/init.js +183 -23
  2. package/package.json +2 -2
@@ -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"));
@@ -29,6 +30,12 @@ function getVSCodeMcpConfigPath() {
29
30
  }
30
31
  return node_path_1.default.join(node_os_1.default.homedir(), ".config", "Code", "User", "mcp.json");
31
32
  }
33
+ function getCopilotCliMcpConfigPath() {
34
+ return node_path_1.default.join(node_os_1.default.homedir(), ".copilot", "mcp-config.json");
35
+ }
36
+ function getCodexConfigPath() {
37
+ return node_path_1.default.join(node_os_1.default.homedir(), ".codex", "config.toml");
38
+ }
32
39
  function resolveServerBin() {
33
40
  // Try npm-installed package first
34
41
  try {
@@ -158,9 +165,98 @@ async function writeClaudeMd(projectDir) {
158
165
  await promises_1.default.writeFile(claudeMdPath, newSection, "utf8");
159
166
  }
160
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
+ }
161
255
  async function run() {
162
256
  const configPath = getClaudeDesktopConfigPath();
163
257
  const vscodeConfigPath = getVSCodeMcpConfigPath();
258
+ const copilotCliConfigPath = getCopilotCliMcpConfigPath();
259
+ const codexConfigPath = getCodexConfigPath();
164
260
  const serverBin = resolveServerBin();
165
261
  const nodeBin = process.execPath;
166
262
  // Register in Claude Desktop config
@@ -198,6 +294,45 @@ async function run() {
198
294
  catch {
199
295
  // VS Code not installed or config dir not writable — skip silently
200
296
  }
297
+ // Register in GitHub Copilot CLI MCP config (~/.copilot/mcp-config.json)
298
+ let copilotCliRegistered = false;
299
+ let copilotCliConfig = {};
300
+ try {
301
+ const raw = await promises_1.default.readFile(copilotCliConfigPath, "utf8");
302
+ copilotCliConfig = JSON.parse(raw);
303
+ }
304
+ catch {
305
+ // File may not exist yet
306
+ }
307
+ if (!copilotCliConfig.mcpServers)
308
+ copilotCliConfig.mcpServers = {};
309
+ copilotCliConfig.mcpServers.docuflow = { type: "local", command: nodeBin, args: [serverBin], tools: ["*"] };
310
+ try {
311
+ await promises_1.default.mkdir(node_path_1.default.dirname(copilotCliConfigPath), { recursive: true });
312
+ await promises_1.default.writeFile(copilotCliConfigPath, JSON.stringify(copilotCliConfig, null, 2) + "\n", "utf8");
313
+ copilotCliRegistered = true;
314
+ }
315
+ catch {
316
+ // Copilot CLI not installed — skip silently
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
+ }
201
336
  // Create .docuflow/ directory structure
202
337
  const projectDir = process.cwd();
203
338
  const docuflowDir = node_path_1.default.join(projectDir, ".docuflow");
@@ -220,6 +355,29 @@ async function run() {
220
355
  await copyTemplateFile("log.md", node_path_1.default.join(docuflowDir, "log.md"));
221
356
  // Generate CLAUDE.md so Claude Code picks up DocuFlow automatically
222
357
  await writeClaudeMd(projectDir);
358
+ // Generate AGENTS.md so OpenAI Codex picks up DocuFlow automatically
359
+ await writeAgentsMd(projectDir);
360
+ // Write .vscode/mcp.json for project-level workspace MCP config (shareable via git)
361
+ // Uses npx so it works on any machine — safe to commit
362
+ const vscodeDirPath = node_path_1.default.join(projectDir, ".vscode");
363
+ const vscodeWorkspaceMcpPath = node_path_1.default.join(vscodeDirPath, "mcp.json");
364
+ let workspaceMcpConfig = {};
365
+ try {
366
+ const raw = await promises_1.default.readFile(vscodeWorkspaceMcpPath, "utf8");
367
+ workspaceMcpConfig = JSON.parse(raw);
368
+ }
369
+ catch {
370
+ // File doesn't exist yet
371
+ }
372
+ if (!workspaceMcpConfig.servers)
373
+ workspaceMcpConfig.servers = {};
374
+ workspaceMcpConfig.servers.docuflow = {
375
+ command: "npx",
376
+ args: ["-y", "-p", "@doquflow/server", "docuflow-server"],
377
+ type: "stdio",
378
+ };
379
+ await promises_1.default.mkdir(vscodeDirPath, { recursive: true });
380
+ await promises_1.default.writeFile(vscodeWorkspaceMcpPath, JSON.stringify(workspaceMcpConfig, null, 2) + "\n", "utf8");
223
381
  // Add .docuflow/ to .gitignore if present and not already listed
224
382
  const gitignorePath = node_path_1.default.join(process.cwd(), ".gitignore");
225
383
  if (node_fs_1.default.existsSync(gitignorePath)) {
@@ -228,32 +386,34 @@ async function run() {
228
386
  await promises_1.default.appendFile(gitignorePath, "\n# Docuflow\n.docuflow/\n");
229
387
  }
230
388
  }
231
- console.log(" Docuflow initialised successfully.");
389
+ console.log("\u2713 DocuFlow initialised successfully.");
232
390
  console.log("");
233
- console.log("📁 Structure created:");
391
+ console.log("\ud83d\udcc1 Structure created:");
234
392
  console.log(` ${docuflowDir}/`);
235
- console.log(` ├── specs/ (for legacy specs)`);
236
- console.log(` ├── wiki/ (LLM-generated pages)`);
237
- console.log(` ├── entities/`);
238
- console.log(` ├── concepts/`);
239
- console.log(` ├── timelines/`);
240
- console.log(` └── syntheses/`);
241
- console.log(` ├── sources/ (immutable raw files)`);
242
- console.log(` ├── schema.md (wiki configuration)`);
243
- console.log(` ├── index.md (auto-maintained catalog)`);
244
- console.log(` └── log.md (operation log)`);
393
+ console.log(` \u251c\u2500\u2500 specs/ (code specs written by the agent)`);
394
+ console.log(` \u251c\u2500\u2500 wiki/ (LLM-generated wiki pages)`);
395
+ console.log(` \u2502 \u251c\u2500\u2500 entities/`);
396
+ console.log(` \u2502 \u251c\u2500\u2500 concepts/`);
397
+ console.log(` \u2502 \u251c\u2500\u2500 timelines/`);
398
+ console.log(` \u2502 \u2514\u2500\u2500 syntheses/`);
399
+ console.log(` \u251c\u2500\u2500 sources/ (raw markdown documents to ingest)`);
400
+ console.log(` \u251c\u2500\u2500 schema.md (wiki configuration)`);
401
+ console.log(` \u251c\u2500\u2500 index.md (auto-maintained catalog)`);
402
+ console.log(` \u2514\u2500\u2500 log.md (operation log)`);
245
403
  console.log("");
246
- console.log("📝 CLAUDE.md:");
247
- console.log(` Generated at: ${node_path_1.default.join(projectDir, "CLAUDE.md")}`);
248
- console.log(` Claude Code will automatically read DocuFlow tool instructions.`);
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")}`);
249
407
  console.log("");
250
- console.log("🔧 MCP Configuration:");
251
- console.log(` Claude Desktop: registered`);
252
- console.log(` GitHub Copilot: ${vscodeRegistered ? " registered" : " VS Code not detected (add manually to .vscode/mcp.json)"}`);
408
+ console.log("\ud83d\udd27 MCP Registration:");
409
+ console.log(` Claude Desktop: \u2713 registered`);
410
+ console.log(` VS Code Copilot: ${vscodeRegistered ? "\u2713 registered (user-level)" : "\u2014 not detected"}`);
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"}`);
413
+ console.log(` Workspace: \u2713 .vscode/mcp.json written (commit to share with team)`);
253
414
  console.log("");
254
- console.log("📖 Next steps:");
255
- console.log(" 1. Edit .docuflow/schema.md to customize your wiki");
256
- console.log(" 2. Add source files to .docuflow/sources/");
257
- console.log(" 3. Use DocuFlow tools to ingest, query, and maintain wiki");
258
- console.log(" 4. Restart Claude Desktop / reload VS Code window to activate");
415
+ console.log("\ud83d\udcd6 Next steps:");
416
+ console.log(" 1. Edit .docuflow/schema.md to customize your wiki domain");
417
+ console.log(" 2. Add markdown docs to .docuflow/sources/ then ingest them");
418
+ console.log(" 3. Restart Claude Desktop / reload VS Code / restart Copilot CLI");
259
419
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doquflow/cli",
3
- "version": "0.4.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.4"
33
+ "@doquflow/server": "0.4.6"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^22.0.0",