mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 07:03:25 +00:00
feat: add claude-rules extension example (#461)
Add an extension that scans .claude/rules/ folder for project-specific rules and lists them in the system prompt. The agent can then load relevant rules using the read tool when needed.
This commit is contained in:
parent
042d3fa310
commit
49c4fe0bc1
1 changed files with 83 additions and 0 deletions
83
packages/coding-agent/examples/extensions/claude-rules.ts
Normal file
83
packages/coding-agent/examples/extensions/claude-rules.ts
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
* Claude Rules Extension
|
||||||
|
*
|
||||||
|
* Scans the project's .claude/rules/ folder for rule files and lists them
|
||||||
|
* in the system prompt. The agent can then use the read tool to load
|
||||||
|
* specific rules when needed.
|
||||||
|
*
|
||||||
|
* Best practices for .claude/rules/:
|
||||||
|
* - Keep rules focused: Each file should cover one topic (e.g., testing.md, api-design.md)
|
||||||
|
* - Use descriptive filenames: The filename should indicate what the rules cover
|
||||||
|
* - Use conditional rules sparingly: Only add paths frontmatter when rules truly apply to specific file types
|
||||||
|
* - Organize with subdirectories: Group related rules (e.g., frontend/, backend/)
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* 1. Copy this file to ~/.pi/agent/extensions/ or your project's .pi/extensions/
|
||||||
|
* 2. Create .claude/rules/ folder in your project root
|
||||||
|
* 3. Add .md files with your rules
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
import * as path from "node:path";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively find all .md files in a directory
|
||||||
|
*/
|
||||||
|
function findMarkdownFiles(dir: string, basePath: string = ""): string[] {
|
||||||
|
const results: string[] = [];
|
||||||
|
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
results.push(...findMarkdownFiles(path.join(dir, entry.name), relativePath));
|
||||||
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
||||||
|
results.push(relativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function claudeRulesExtension(pi: ExtensionAPI) {
|
||||||
|
let ruleFiles: string[] = [];
|
||||||
|
let rulesDir: string = "";
|
||||||
|
|
||||||
|
// Scan for rules on session start
|
||||||
|
pi.on("session_start", async (_event, ctx) => {
|
||||||
|
rulesDir = path.join(ctx.cwd, ".claude", "rules");
|
||||||
|
ruleFiles = findMarkdownFiles(rulesDir);
|
||||||
|
|
||||||
|
if (ruleFiles.length > 0) {
|
||||||
|
ctx.ui.notify(`Found ${ruleFiles.length} rule(s) in .claude/rules/`, "info");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Append available rules to system prompt
|
||||||
|
pi.on("before_agent_start", async () => {
|
||||||
|
if (ruleFiles.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rulesList = ruleFiles.map((f) => `- .claude/rules/${f}`).join("\n");
|
||||||
|
|
||||||
|
return {
|
||||||
|
systemPromptAppend: `
|
||||||
|
## Project Rules
|
||||||
|
|
||||||
|
The following project rules are available in .claude/rules/:
|
||||||
|
|
||||||
|
${rulesList}
|
||||||
|
|
||||||
|
When working on tasks related to these rules, use the read tool to load the relevant rule files for guidance.
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue