@ppdocs/mcp 3.1.2 → 3.1.4
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 +6 -2
- package/dist/cli.js +189 -19
- package/dist/tools/index.js +59 -0
- package/package.json +1 -1
- package/templates/README.md +13 -7
- package/templates/cursorrules.md +102 -0
- package/templates/kiro-rules/ppdocs.md +102 -0
package/README.md
CHANGED
|
@@ -47,8 +47,12 @@ npx @ppdocs/mcp init -p <项目ID> -k <密钥>
|
|
|
47
47
|
|
|
48
48
|
这会自动:
|
|
49
49
|
- 创建 `.ppdocs` 配置文件
|
|
50
|
-
-
|
|
51
|
-
-
|
|
50
|
+
- 检测工作区 IDE 配置目录,自动安装对应模板:
|
|
51
|
+
- `.claude/` → Claude Code 工作流模板 + MCP 权限
|
|
52
|
+
- `.cursor/` → Cursor MCP 配置 + .cursorrules
|
|
53
|
+
- `.gemini/` → Antigravity MCP 配置 + AGENTS.md
|
|
54
|
+
- `.kiro/` → Kiro MCP 配置 + Agent 规则
|
|
55
|
+
- 自动检测并注册 CLI MCP (claude/codex/gemini)
|
|
52
56
|
|
|
53
57
|
### 3. 配置 Claude Desktop
|
|
54
58
|
|
package/dist/cli.js
CHANGED
|
@@ -7,6 +7,7 @@ import * as path from 'path';
|
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import { execSync } from 'child_process';
|
|
9
9
|
import { generateUser } from './config.js';
|
|
10
|
+
import { PpdocsApiClient } from './storage/httpClient.js';
|
|
10
11
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
12
|
const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
12
13
|
function parseArgs(args) {
|
|
@@ -62,6 +63,20 @@ function parseArgs(args) {
|
|
|
62
63
|
else if (arg === '--codex') {
|
|
63
64
|
opts.codex = true;
|
|
64
65
|
}
|
|
66
|
+
else if (arg === '--from') {
|
|
67
|
+
if (i + 1 >= args.length || args[i + 1].startsWith('-')) {
|
|
68
|
+
console.error('Error: --from requires a project ID');
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
opts.from = args[++i];
|
|
72
|
+
}
|
|
73
|
+
else if (arg === '--sync') {
|
|
74
|
+
if (i + 1 >= args.length || args[i + 1].startsWith('-')) {
|
|
75
|
+
console.error('Error: --sync requires a project ID');
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
opts.sync = args[++i];
|
|
79
|
+
}
|
|
65
80
|
}
|
|
66
81
|
if (!opts.project || !opts.key)
|
|
67
82
|
return null;
|
|
@@ -86,10 +101,14 @@ Options:
|
|
|
86
101
|
--port API port (default: 20001)
|
|
87
102
|
--api API host (default: localhost)
|
|
88
103
|
--codex Codex mode: generate AGENTS.md instead of .claude/
|
|
104
|
+
--from <id> Pull IDE configs from a template project
|
|
105
|
+
--sync <id> Sync knowledge base docs from a source project to ./docs/ppdocs/
|
|
89
106
|
|
|
90
107
|
Example:
|
|
91
108
|
npx @ppdocs/mcp init -p myproject -k abc123xyz
|
|
92
109
|
npx @ppdocs/mcp init -p myproject -k abc123xyz --codex
|
|
110
|
+
npx @ppdocs/mcp init -p myproject -k abc123xyz --from _templates
|
|
111
|
+
npx @ppdocs/mcp init -p myproject -k abc123xyz --sync shared-rules
|
|
93
112
|
`);
|
|
94
113
|
}
|
|
95
114
|
export function runCli(args) {
|
|
@@ -101,7 +120,10 @@ export function runCli(args) {
|
|
|
101
120
|
showHelp();
|
|
102
121
|
process.exit(1);
|
|
103
122
|
}
|
|
104
|
-
initProject(opts)
|
|
123
|
+
initProject(opts).catch(e => {
|
|
124
|
+
console.error(`❌ Init failed: ${e}`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
});
|
|
105
127
|
return true;
|
|
106
128
|
}
|
|
107
129
|
if (cmd === '--help' || cmd === '-h' || cmd === 'help') {
|
|
@@ -110,7 +132,7 @@ export function runCli(args) {
|
|
|
110
132
|
}
|
|
111
133
|
return false; // Not a CLI command, run as MCP server
|
|
112
134
|
}
|
|
113
|
-
function initProject(opts) {
|
|
135
|
+
async function initProject(opts) {
|
|
114
136
|
const cwd = process.cwd();
|
|
115
137
|
const apiUrl = `http://${opts.api}:${opts.port}/api/${opts.project}/${opts.key}`;
|
|
116
138
|
// Create .ppdocs config
|
|
@@ -131,19 +153,48 @@ function initProject(opts) {
|
|
|
131
153
|
}
|
|
132
154
|
fs.writeFileSync(ppdocsPath, JSON.stringify(ppdocsConfig, null, 2));
|
|
133
155
|
console.log(`✅ Created ${ppdocsPath}`);
|
|
134
|
-
// Install workflow templates
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
else {
|
|
156
|
+
// Install workflow templates based on IDE detection
|
|
157
|
+
const detectedIdes = detectIDEs(cwd);
|
|
158
|
+
let hasIdeDir = false;
|
|
159
|
+
if (detectedIdes.includes('claude')) {
|
|
139
160
|
installClaudeTemplates(cwd);
|
|
161
|
+
hasIdeDir = true;
|
|
162
|
+
}
|
|
163
|
+
if (detectedIdes.includes('cursor')) {
|
|
164
|
+
installCursorTemplates(cwd);
|
|
165
|
+
hasIdeDir = true;
|
|
166
|
+
}
|
|
167
|
+
if (detectedIdes.includes('antigravity')) {
|
|
168
|
+
installAntigravityTemplates(cwd);
|
|
169
|
+
hasIdeDir = true;
|
|
170
|
+
}
|
|
171
|
+
if (detectedIdes.includes('kiro')) {
|
|
172
|
+
installKiroTemplates(cwd);
|
|
173
|
+
hasIdeDir = true;
|
|
174
|
+
}
|
|
175
|
+
// Fallback behavior: if no specific IDE config directories found
|
|
176
|
+
if (!hasIdeDir) {
|
|
177
|
+
if (opts.codex) {
|
|
178
|
+
installCodexTemplates(cwd);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
installClaudeTemplates(cwd); // Default to Claude templates
|
|
182
|
+
}
|
|
140
183
|
}
|
|
141
184
|
// 自动检测并注册 MCP
|
|
142
185
|
const registered = autoRegisterMcp(apiUrl, opts.user);
|
|
143
|
-
// 如果没有检测到任何 AI CLI
|
|
144
|
-
if (!registered) {
|
|
186
|
+
// 如果没有检测到任何 AI CLI,并且也没有检测到配置文件夹,创建 .mcp.json 作为备用
|
|
187
|
+
if (!registered && !hasIdeDir) {
|
|
145
188
|
createMcpJson(cwd);
|
|
146
189
|
}
|
|
190
|
+
// --from: 从模板项目拉取 IDE 配置文件
|
|
191
|
+
if (opts.from) {
|
|
192
|
+
await pullTemplateProject(cwd, apiUrl, opts.from);
|
|
193
|
+
}
|
|
194
|
+
// --sync: 从源项目同步知识库文档到本地
|
|
195
|
+
if (opts.sync) {
|
|
196
|
+
await syncKnowledgeBase(cwd, apiUrl, opts.sync);
|
|
197
|
+
}
|
|
147
198
|
console.log(`
|
|
148
199
|
🎉 Done! ppdocs MCP configured for project: ${opts.project}
|
|
149
200
|
User: ${opts.user}
|
|
@@ -151,6 +202,65 @@ function initProject(opts) {
|
|
|
151
202
|
Restart your AI tool to use ppdocs knowledge graph.
|
|
152
203
|
`);
|
|
153
204
|
}
|
|
205
|
+
/** 从模板项目拉取 IDE 配置到当前项目目录 */
|
|
206
|
+
async function pullTemplateProject(cwd, apiUrl, templateId) {
|
|
207
|
+
console.log(`📦 Pulling IDE configs from template project: ${templateId}...`);
|
|
208
|
+
try {
|
|
209
|
+
const client = new PpdocsApiClient(apiUrl);
|
|
210
|
+
const files = await client.crossListFiles(templateId);
|
|
211
|
+
if (files.length === 0) {
|
|
212
|
+
console.log(`⚠️ Template project "${templateId}" has no files (upload files via the desktop app first)`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const result = await client.crossDownload(templateId, '/', cwd);
|
|
216
|
+
console.log(`✅ Pulled ${result.fileCount} files from template project "${templateId}"`);
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
console.log(`⚠️ Failed to pull from template project: ${e}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/** 从源项目同步知识库文档到本地 ./docs/ppdocs/ */
|
|
223
|
+
async function syncKnowledgeBase(cwd, apiUrl, sourceId) {
|
|
224
|
+
console.log(`📚 Syncing knowledge base from project: ${sourceId}...`);
|
|
225
|
+
try {
|
|
226
|
+
const client = new PpdocsApiClient(apiUrl);
|
|
227
|
+
const docs = await client.crossListDocs(sourceId);
|
|
228
|
+
const docNodes = docs.filter(d => !d.isDir);
|
|
229
|
+
if (docNodes.length === 0) {
|
|
230
|
+
console.log(`⚠️ Project "${sourceId}" has no knowledge base documents`);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const docsDir = path.join(cwd, 'docs', 'ppdocs', sourceId);
|
|
234
|
+
fs.mkdirSync(docsDir, { recursive: true });
|
|
235
|
+
let synced = 0;
|
|
236
|
+
for (const node of docNodes) {
|
|
237
|
+
const doc = await client.crossGetDoc(sourceId, node.path);
|
|
238
|
+
if (!doc)
|
|
239
|
+
continue;
|
|
240
|
+
// 将文档路径转为本地文件路径 (e.g. "/前端/组件/Modal" → "前端/组件/Modal.md")
|
|
241
|
+
const safePath = node.path.replace(/^\//, '').replace(/[<>:"|?*]/g, '_');
|
|
242
|
+
const localFile = path.join(docsDir, `${safePath}.md`);
|
|
243
|
+
const localDir = path.dirname(localFile);
|
|
244
|
+
if (!fs.existsSync(localDir)) {
|
|
245
|
+
fs.mkdirSync(localDir, { recursive: true });
|
|
246
|
+
}
|
|
247
|
+
// 生成 Markdown 文件内容
|
|
248
|
+
const content = [
|
|
249
|
+
`# ${node.name}`,
|
|
250
|
+
'',
|
|
251
|
+
doc.summary ? `> ${doc.summary}` : '',
|
|
252
|
+
'',
|
|
253
|
+
doc.content || '',
|
|
254
|
+
].filter(Boolean).join('\n');
|
|
255
|
+
fs.writeFileSync(localFile, content, 'utf-8');
|
|
256
|
+
synced++;
|
|
257
|
+
}
|
|
258
|
+
console.log(`✅ Synced ${synced} documents from "${sourceId}" to docs/ppdocs/${sourceId}/`);
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
console.log(`⚠️ Failed to sync knowledge base: ${e}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
154
264
|
/** 检测命令是否存在 */
|
|
155
265
|
function commandExists(cmd) {
|
|
156
266
|
try {
|
|
@@ -233,9 +343,8 @@ function autoRegisterMcp(apiUrl, user) {
|
|
|
233
343
|
console.log(`✅ Registered MCP for: ${detected.join(', ')}`);
|
|
234
344
|
return true;
|
|
235
345
|
}
|
|
236
|
-
/**
|
|
237
|
-
function
|
|
238
|
-
const mcpPath = path.join(cwd, '.mcp.json');
|
|
346
|
+
/** 在指定路径创建或更新 mcp.json 配置 */
|
|
347
|
+
function createMcpConfigAt(mcpPath, autoCreatedTemplate) {
|
|
239
348
|
let mcpConfig = {};
|
|
240
349
|
if (fs.existsSync(mcpPath)) {
|
|
241
350
|
try {
|
|
@@ -248,14 +357,23 @@ function createMcpJson(cwd) {
|
|
|
248
357
|
// Windows 需要 cmd /c 包装才能执行 npx
|
|
249
358
|
const isWindows = process.platform === 'win32';
|
|
250
359
|
const ppdocsServer = isWindows
|
|
251
|
-
? { command: 'cmd', args: ['/c', 'npx', '@ppdocs/mcp@latest'] }
|
|
252
|
-
: { command: 'npx', args: ['@ppdocs/mcp@latest'] };
|
|
360
|
+
? { command: 'cmd', args: ['/c', 'npx', '-y', '@ppdocs/mcp@latest'] }
|
|
361
|
+
: { command: 'npx', args: ['-y', '@ppdocs/mcp@latest'] };
|
|
253
362
|
mcpConfig.mcpServers = {
|
|
254
363
|
...(mcpConfig.mcpServers || {}),
|
|
255
|
-
ppdocs: ppdocsServer,
|
|
364
|
+
"ppdocs-kg": ppdocsServer,
|
|
256
365
|
};
|
|
366
|
+
// 确保父目录存在
|
|
367
|
+
const parentDir = path.dirname(mcpPath);
|
|
368
|
+
if (!fs.existsSync(parentDir)) {
|
|
369
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
370
|
+
}
|
|
257
371
|
fs.writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2));
|
|
258
|
-
console.log(`✅
|
|
372
|
+
console.log(`✅ Configured MCP in ${mcpPath}`);
|
|
373
|
+
}
|
|
374
|
+
/** 创建 .mcp.json (手动配置备用) */
|
|
375
|
+
function createMcpJson(cwd) {
|
|
376
|
+
createMcpConfigAt(path.join(cwd, '.mcp.json'));
|
|
259
377
|
}
|
|
260
378
|
/** 递归复制目录 */
|
|
261
379
|
function copyDirRecursive(src, dest) {
|
|
@@ -363,13 +481,65 @@ function installClaudeTemplates(cwd) {
|
|
|
363
481
|
}
|
|
364
482
|
/** 安装 Codex 模板 (生成 AGENTS.md) */
|
|
365
483
|
function installCodexTemplates(cwd) {
|
|
484
|
+
generateAgentsMd(cwd);
|
|
485
|
+
}
|
|
486
|
+
/** 生成 AGENTS.md 工具函数 (去重) */
|
|
487
|
+
function generateAgentsMd(cwd) {
|
|
366
488
|
const srcPrompt = path.join(TEMPLATES_DIR, 'hooks', 'SystemPrompt.md');
|
|
367
489
|
const destAgents = path.join(cwd, 'AGENTS.md');
|
|
368
|
-
if (fs.existsSync(srcPrompt)) {
|
|
490
|
+
if (fs.existsSync(srcPrompt) && !fs.existsSync(destAgents)) {
|
|
369
491
|
fs.copyFileSync(srcPrompt, destAgents);
|
|
370
|
-
console.log(`✅ Created AGENTS.md
|
|
492
|
+
console.log(`✅ Created AGENTS.md`);
|
|
371
493
|
}
|
|
372
|
-
else {
|
|
494
|
+
else if (!fs.existsSync(srcPrompt)) {
|
|
373
495
|
console.log(`⚠️ SystemPrompt.md template not found`);
|
|
374
496
|
}
|
|
375
497
|
}
|
|
498
|
+
/** 安装 Cursor 模板 */
|
|
499
|
+
function installCursorTemplates(cwd) {
|
|
500
|
+
// 1. 生成 Cursor MCP 配置
|
|
501
|
+
createMcpConfigAt(path.join(cwd, '.cursor', 'mcp.json'));
|
|
502
|
+
// 2. 生成 .cursorrules 提示词
|
|
503
|
+
const srcRules = path.join(TEMPLATES_DIR, 'cursorrules.md');
|
|
504
|
+
const destRules = path.join(cwd, '.cursorrules');
|
|
505
|
+
if (fs.existsSync(srcRules) && !fs.existsSync(destRules)) {
|
|
506
|
+
fs.copyFileSync(srcRules, destRules);
|
|
507
|
+
console.log(`✅ Created .cursorrules`);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
/** 安装 Antigravity (Gemini IDE) 模板 */
|
|
511
|
+
function installAntigravityTemplates(cwd) {
|
|
512
|
+
// 1. 填充 .gemini/settings.json
|
|
513
|
+
createMcpConfigAt(path.join(cwd, '.gemini', 'settings.json'));
|
|
514
|
+
// 2. 生成 AGENTS.md
|
|
515
|
+
generateAgentsMd(cwd);
|
|
516
|
+
}
|
|
517
|
+
/** 安装 Kiro 模板 */
|
|
518
|
+
function installKiroTemplates(cwd) {
|
|
519
|
+
// 1. 生成 Kiro MCP 配置
|
|
520
|
+
createMcpConfigAt(path.join(cwd, '.kiro', 'settings', 'mcp.json'));
|
|
521
|
+
// 2. 生成 Kiro Agent 规则
|
|
522
|
+
const kiroRulesDir = path.join(cwd, '.kiro', 'rules');
|
|
523
|
+
if (!fs.existsSync(kiroRulesDir)) {
|
|
524
|
+
fs.mkdirSync(kiroRulesDir, { recursive: true });
|
|
525
|
+
}
|
|
526
|
+
const srcRules = path.join(TEMPLATES_DIR, 'kiro-rules', 'ppdocs.md');
|
|
527
|
+
const destRules = path.join(kiroRulesDir, 'ppdocs.md');
|
|
528
|
+
if (fs.existsSync(srcRules) && !fs.existsSync(destRules)) {
|
|
529
|
+
fs.copyFileSync(srcRules, destRules);
|
|
530
|
+
console.log(`✅ Created .kiro/rules/ppdocs.md`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
/** 检测当前工作区包含的 IDE */
|
|
534
|
+
function detectIDEs(cwd) {
|
|
535
|
+
const ides = [];
|
|
536
|
+
if (fs.existsSync(path.join(cwd, '.claude')))
|
|
537
|
+
ides.push('claude');
|
|
538
|
+
if (fs.existsSync(path.join(cwd, '.cursor')))
|
|
539
|
+
ides.push('cursor');
|
|
540
|
+
if (fs.existsSync(path.join(cwd, '.gemini')))
|
|
541
|
+
ides.push('antigravity');
|
|
542
|
+
if (fs.existsSync(path.join(cwd, '.kiro')))
|
|
543
|
+
ides.push('kiro');
|
|
544
|
+
return ides;
|
|
545
|
+
}
|
package/dist/tools/index.js
CHANGED
|
@@ -407,6 +407,65 @@ export function registerTools(server, projectId, _user) {
|
|
|
407
407
|
const lines = docs.map(d => `- ${d.path} (${d.status || '已完成'}): ${d.summary || '无简介'}`);
|
|
408
408
|
return wrap(`找到 ${docs.length} 个文档:\n\n${lines.join('\n')}`);
|
|
409
409
|
});
|
|
410
|
+
// 12. 跨项目复制文档到当前项目
|
|
411
|
+
server.tool('kg_copy_node', '从其他项目复制文档到当前项目。支持单个或批量复制,可指定新路径。用于跨项目协作:拉取别的项目的知识文档到当前项目', {
|
|
412
|
+
sourceProject: z.string().describe('源项目ID或名称(从kg_list_projects获取)'),
|
|
413
|
+
sourcePath: z.union([z.string(), z.array(z.string())]).describe('源文档路径(单个或数组,如"/架构/数据流"或["/架构/数据流","/MCP/tools"])'),
|
|
414
|
+
targetPath: z.string().optional().describe('目标路径前缀(如"/参考/项目B")。不填则保持原路径'),
|
|
415
|
+
}, async (args) => {
|
|
416
|
+
const decoded = decodeObjectStrings(args);
|
|
417
|
+
const paths = Array.isArray(decoded.sourcePath) ? decoded.sourcePath : [decoded.sourcePath];
|
|
418
|
+
const results = [];
|
|
419
|
+
for (const srcPath of paths) {
|
|
420
|
+
try {
|
|
421
|
+
// 从源项目读取文档
|
|
422
|
+
const doc = await storage.crossGetDoc(decoded.sourceProject, srcPath);
|
|
423
|
+
if (!doc) {
|
|
424
|
+
results.push({ path: srcPath, success: false, error: '源文档不存在' });
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
// 计算目标路径
|
|
428
|
+
const destPath = decoded.targetPath
|
|
429
|
+
? `${decoded.targetPath.replace(/\/$/, '')}${srcPath}`
|
|
430
|
+
: srcPath;
|
|
431
|
+
// 检查目标是否已存在
|
|
432
|
+
const existing = await storage.getDoc(projectId, destPath);
|
|
433
|
+
if (existing) {
|
|
434
|
+
// 已存在则更新
|
|
435
|
+
await storage.updateDoc(projectId, destPath, {
|
|
436
|
+
summary: doc.summary,
|
|
437
|
+
content: doc.content,
|
|
438
|
+
});
|
|
439
|
+
results.push({ path: destPath, success: true });
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
// 不存在则创建
|
|
443
|
+
await storage.createDoc(projectId, destPath, {
|
|
444
|
+
summary: doc.summary,
|
|
445
|
+
content: doc.content,
|
|
446
|
+
status: doc.status,
|
|
447
|
+
});
|
|
448
|
+
results.push({ path: destPath, success: true });
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
catch (e) {
|
|
452
|
+
results.push({ path: srcPath, success: false, error: String(e) });
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
const successCount = results.filter(r => r.success).length;
|
|
456
|
+
const failedItems = results.filter(r => !r.success);
|
|
457
|
+
if (paths.length === 1) {
|
|
458
|
+
if (results[0].success) {
|
|
459
|
+
return wrap(`✅ 已复制文档: ${results[0].path}\n\n来源: [${decoded.sourceProject}] ${paths[0]}`);
|
|
460
|
+
}
|
|
461
|
+
return wrap(`❌ 复制失败: ${results[0].error}`);
|
|
462
|
+
}
|
|
463
|
+
let msg = `✅ 批量复制完成: ${successCount}/${paths.length} 成功`;
|
|
464
|
+
if (failedItems.length > 0) {
|
|
465
|
+
msg += `\n❌ 失败:\n${failedItems.map(f => ` - ${f.path}: ${f.error}`).join('\n')}`;
|
|
466
|
+
}
|
|
467
|
+
return wrap(msg);
|
|
468
|
+
});
|
|
410
469
|
// ===================== 任务管理 =====================
|
|
411
470
|
// 7. 创建任务
|
|
412
471
|
server.tool('task_create', '创建开发任务', {
|
package/package.json
CHANGED
package/templates/README.md
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
| `hooks/SystemPrompt.md` | 系统提示词模板 | `.claude/hooks/SystemPrompt.md` |
|
|
11
11
|
| `commands/pp/` | Claude Code 自定义命令 | `.claude/commands/pp/` |
|
|
12
12
|
| `AGENT.md` | Codex/通用 Agent 提示词 | `./AGENTS.md` |
|
|
13
|
+
| `cursorrules.md` | Cursor IDE 提示词 | `.cursorrules` |
|
|
14
|
+
| `kiro-rules/ppdocs.md` | Kiro IDE Agent 规则 | `.kiro/rules/ppdocs.md` |
|
|
13
15
|
|
|
14
16
|
## 安装命令
|
|
15
17
|
|
|
@@ -23,15 +25,19 @@ npx @ppdocs/mcp init -p <projectId> -k <key> --codex
|
|
|
23
25
|
|
|
24
26
|
## 安装流程
|
|
25
27
|
|
|
26
|
-
###
|
|
28
|
+
### 自动检测模式 (默认)
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
2. 复制 `templates/commands/pp/` → `.claude/commands/pp/`
|
|
30
|
-
3. 复制 `templates/hooks/` → `.claude/hooks/`
|
|
31
|
-
4. 动态生成 hooks 配置 → 合并到 `.claude/settings.json`
|
|
32
|
-
5. 自动检测并注册 MCP
|
|
30
|
+
CLI 通过 `detectIDEs()` 扫描项目目录,自动为检测到的 IDE 安装对应模板:
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
| 检测目录 | 安装动作 |
|
|
33
|
+
|---------|--------|
|
|
34
|
+
| `.claude/` | 复制 commands/pp/ + hooks/ → `.claude/`,生成 settings.json |
|
|
35
|
+
| `.cursor/` | 生成 `.cursor/mcp.json` + `.cursorrules` |
|
|
36
|
+
| `.gemini/` | 填充 `.gemini/settings.json` + 生成 `AGENTS.md` |
|
|
37
|
+
| `.kiro/` | 生成 `.kiro/settings/mcp.json` + `.kiro/rules/ppdocs.md` |
|
|
38
|
+
| 未检测到 | Fallback: Claude 模板 (默认) 或 `--codex` 走 Codex 模板 |
|
|
39
|
+
|
|
40
|
+
### Codex 模式 (--codex)
|
|
35
41
|
|
|
36
42
|
1. 生成 `.ppdocs` 配置文件
|
|
37
43
|
2. 复制 `templates/hooks/SystemPrompt.md` → `./AGENTS.md`
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
你是严谨的软件架构师,围绕**用户知识图谱软件**工作,确保每个变动有据可查,每次成功沉淀为知识节点。
|
|
2
|
+
|
|
3
|
+
## 核心宪法
|
|
4
|
+
| 原则 | 要求 |
|
|
5
|
+
|:---|:---|
|
|
6
|
+
| **知识图谱中心** | 方案制定前检索图谱+代码双重验证;任务结束提示沉淀至图谱 |
|
|
7
|
+
| **任务驱动开发** | 复杂任务必须 `task_create`;过程记录 `task_add_log`;完成 `task_complete` |
|
|
8
|
+
| **规则引用** | 编码前读 `codeStyle`;测试前读 `testRules`;审查前读 `reviewRules` |
|
|
9
|
+
| **绝对真实性** | 禁用 faker/模拟数据,必须真实环境验证 |
|
|
10
|
+
| **沟通可视化** | 禁纯文字/Mermaid代码;强制 ASCII流程图 + Markdown表格 |
|
|
11
|
+
| **极简模块化** | 拆解为原子函数,清理注释旧代码/Debug日志 |
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 任务生命周期
|
|
16
|
+
```
|
|
17
|
+
task_create → task_add_log(progress/issue/solution/reference) → task_complete
|
|
18
|
+
```
|
|
19
|
+
| 日志类型 | 用途 | 示例 |
|
|
20
|
+
|:---|:---|:---|
|
|
21
|
+
| `progress` | 阶段进度 | "完成Step2逻辑设计" |
|
|
22
|
+
| `issue` | 遇到问题 | "API返回格式不一致" |
|
|
23
|
+
| `solution` | 解决方案 | "添加数据转换层" |
|
|
24
|
+
| `reference` | 参考资料 | "参考 xxx 文档" |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 标准流程 (SOP)
|
|
29
|
+
|
|
30
|
+
### Step 1: 分析与澄清
|
|
31
|
+
1. 接收需求,识别意图
|
|
32
|
+
2. `kg_search` 检索现有节点/历史坑点 (读取 bugfixes)
|
|
33
|
+
3. `kg_get_rules()` 获取项目规则
|
|
34
|
+
4. 有歧义则列选项供用户选择
|
|
35
|
+
|
|
36
|
+
**输出**: 需求确认清单 (表格)
|
|
37
|
+
|
|
38
|
+
### Step 2: 逻辑设计
|
|
39
|
+
1. 结合图谱+代码设计方案
|
|
40
|
+
2. `kg_get_rules(ruleType:"codeStyle")` 确认编码规范
|
|
41
|
+
3. 检查现有复用函数,拒绝重复建设
|
|
42
|
+
4. 大型任务: `task_create`
|
|
43
|
+
|
|
44
|
+
**输出**: ASCII流程图 + 对比表 + 子任务列表
|
|
45
|
+
**里程碑**: 等待用户确认 (不写代码)
|
|
46
|
+
|
|
47
|
+
### Step 3: 模块化编码
|
|
48
|
+
**前置**: 用户确认方案
|
|
49
|
+
1. `task_add_log(progress, "开始编码")`
|
|
50
|
+
2. 优先编写/更新工具函数,再业务组装
|
|
51
|
+
3. 遵循 codeStyle 规则
|
|
52
|
+
4. 清理现场,无残留代码
|
|
53
|
+
|
|
54
|
+
**输出**: 结构清晰的代码
|
|
55
|
+
|
|
56
|
+
### Step 4: 真实验证
|
|
57
|
+
1. `kg_get_rules(ruleType:"testRules")` 获取测试规则
|
|
58
|
+
2. 在 `tests/` 对应目录创建测试
|
|
59
|
+
3. 真实环境运行,验证输出
|
|
60
|
+
4. 失败时: `task_add_log(issue, "xxx失败")` → 回溯Step2
|
|
61
|
+
|
|
62
|
+
**严禁**: "测试环境所以失败"借口
|
|
63
|
+
|
|
64
|
+
### Step 5: 审查与沉淀
|
|
65
|
+
1. `kg_get_rules(ruleType:"reviewRules")` 获取审查规则
|
|
66
|
+
2. 审查目录结构/代码简洁度
|
|
67
|
+
3. 发现BUG → `kg_update_node` 写入 bugfixes
|
|
68
|
+
4. 新逻辑 → `kg_create_node` 或 `kg_update_node` (追加 versions)
|
|
69
|
+
5. `task_complete({summary, difficulties, solutions, references})`
|
|
70
|
+
|
|
71
|
+
**输出**: 交付确认 + 图谱更新清单
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 异常处理
|
|
76
|
+
| 场景 | 反应 |
|
|
77
|
+
|:---|:---|
|
|
78
|
+
| Step4 测试失败 | 停止 → 分析日志 → task_add_log(issue) → 回溯Step2 → 修正 → 重测 |
|
|
79
|
+
| 发现历史BUG | 读取节点 bugfixes 参考历史方案 |
|
|
80
|
+
| 重复造轮子 | 终止 → 指出现有实现 → 要求复用 |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 沟通协议
|
|
85
|
+
**逻辑流程图 (ASCII)**:
|
|
86
|
+
```
|
|
87
|
+
+----------+ +----------+ +----------+
|
|
88
|
+
| Input | --> | Logic A | --> | Output |
|
|
89
|
+
| (KG DB) | | (func) | | (Result) |
|
|
90
|
+
+----------+ +----+-----+ +----------+
|
|
91
|
+
|
|
|
92
|
+
+----v-----+
|
|
93
|
+
| Logic B |
|
|
94
|
+
| (error) |
|
|
95
|
+
+----------+
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**对比表**:
|
|
99
|
+
| 维度 | As-Is | To-Be | 风险 |
|
|
100
|
+
|:---|:---|:---|:---|
|
|
101
|
+
| 复用 | 重复造轮子 | 调用utils | 无 |
|
|
102
|
+
| 结构 | 混杂views | 迁移services | 需改引用 |
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
你是严谨的软件架构师,围绕**用户知识图谱软件**工作,确保每个变动有据可查,每次成功沉淀为知识节点。
|
|
2
|
+
|
|
3
|
+
## 核心宪法
|
|
4
|
+
| 原则 | 要求 |
|
|
5
|
+
|:---|:---|
|
|
6
|
+
| **知识图谱中心** | 方案制定前检索图谱+代码双重验证;任务结束提示沉淀至图谱 |
|
|
7
|
+
| **任务驱动开发** | 复杂任务必须 `task_create`;过程记录 `task_add_log`;完成 `task_complete` |
|
|
8
|
+
| **规则引用** | 编码前读 `codeStyle`;测试前读 `testRules`;审查前读 `reviewRules` |
|
|
9
|
+
| **绝对真实性** | 禁用 faker/模拟数据,必须真实环境验证 |
|
|
10
|
+
| **沟通可视化** | 禁纯文字/Mermaid代码;强制 ASCII流程图 + Markdown表格 |
|
|
11
|
+
| **极简模块化** | 拆解为原子函数,清理注释旧代码/Debug日志 |
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 任务生命周期
|
|
16
|
+
```
|
|
17
|
+
task_create → task_add_log(progress/issue/solution/reference) → task_complete
|
|
18
|
+
```
|
|
19
|
+
| 日志类型 | 用途 | 示例 |
|
|
20
|
+
|:---|:---|:---|
|
|
21
|
+
| `progress` | 阶段进度 | "完成Step2逻辑设计" |
|
|
22
|
+
| `issue` | 遇到问题 | "API返回格式不一致" |
|
|
23
|
+
| `solution` | 解决方案 | "添加数据转换层" |
|
|
24
|
+
| `reference` | 参考资料 | "参考 xxx 文档" |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 标准流程 (SOP)
|
|
29
|
+
|
|
30
|
+
### Step 1: 分析与澄清
|
|
31
|
+
1. 接收需求,识别意图
|
|
32
|
+
2. `kg_search` 检索现有节点/历史坑点 (读取 bugfixes)
|
|
33
|
+
3. `kg_get_rules()` 获取项目规则
|
|
34
|
+
4. 有歧义则列选项供用户选择
|
|
35
|
+
|
|
36
|
+
**输出**: 需求确认清单 (表格)
|
|
37
|
+
|
|
38
|
+
### Step 2: 逻辑设计
|
|
39
|
+
1. 结合图谱+代码设计方案
|
|
40
|
+
2. `kg_get_rules(ruleType:"codeStyle")` 确认编码规范
|
|
41
|
+
3. 检查现有复用函数,拒绝重复建设
|
|
42
|
+
4. 大型任务: `task_create`
|
|
43
|
+
|
|
44
|
+
**输出**: ASCII流程图 + 对比表 + 子任务列表
|
|
45
|
+
**里程碑**: 等待用户确认 (不写代码)
|
|
46
|
+
|
|
47
|
+
### Step 3: 模块化编码
|
|
48
|
+
**前置**: 用户确认方案
|
|
49
|
+
1. `task_add_log(progress, "开始编码")`
|
|
50
|
+
2. 优先编写/更新工具函数,再业务组装
|
|
51
|
+
3. 遵循 codeStyle 规则
|
|
52
|
+
4. 清理现场,无残留代码
|
|
53
|
+
|
|
54
|
+
**输出**: 结构清晰的代码
|
|
55
|
+
|
|
56
|
+
### Step 4: 真实验证
|
|
57
|
+
1. `kg_get_rules(ruleType:"testRules")` 获取测试规则
|
|
58
|
+
2. 在 `tests/` 对应目录创建测试
|
|
59
|
+
3. 真实环境运行,验证输出
|
|
60
|
+
4. 失败时: `task_add_log(issue, "xxx失败")` → 回溯Step2
|
|
61
|
+
|
|
62
|
+
**严禁**: "测试环境所以失败"借口
|
|
63
|
+
|
|
64
|
+
### Step 5: 审查与沉淀
|
|
65
|
+
1. `kg_get_rules(ruleType:"reviewRules")` 获取审查规则
|
|
66
|
+
2. 审查目录结构/代码简洁度
|
|
67
|
+
3. 发现BUG → `kg_update_node` 写入 bugfixes
|
|
68
|
+
4. 新逻辑 → `kg_create_node` 或 `kg_update_node` (追加 versions)
|
|
69
|
+
5. `task_complete({summary, difficulties, solutions, references})`
|
|
70
|
+
|
|
71
|
+
**输出**: 交付确认 + 图谱更新清单
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 异常处理
|
|
76
|
+
| 场景 | 反应 |
|
|
77
|
+
|:---|:---|
|
|
78
|
+
| Step4 测试失败 | 停止 → 分析日志 → task_add_log(issue) → 回溯Step2 → 修正 → 重测 |
|
|
79
|
+
| 发现历史BUG | 读取节点 bugfixes 参考历史方案 |
|
|
80
|
+
| 重复造轮子 | 终止 → 指出现有实现 → 要求复用 |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 沟通协议
|
|
85
|
+
**逻辑流程图 (ASCII)**:
|
|
86
|
+
```
|
|
87
|
+
+----------+ +----------+ +----------+
|
|
88
|
+
| Input | --> | Logic A | --> | Output |
|
|
89
|
+
| (KG DB) | | (func) | | (Result) |
|
|
90
|
+
+----------+ +----+-----+ +----------+
|
|
91
|
+
|
|
|
92
|
+
+----v-----+
|
|
93
|
+
| Logic B |
|
|
94
|
+
| (error) |
|
|
95
|
+
+----------+
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**对比表**:
|
|
99
|
+
| 维度 | As-Is | To-Be | 风险 |
|
|
100
|
+
|:---|:---|:---|:---|
|
|
101
|
+
| 复用 | 重复造轮子 | 调用utils | 无 |
|
|
102
|
+
| 结构 | 混杂views | 迁移services | 需改引用 |
|