xtrm-tools 0.7.7 → 0.7.9

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 (123) hide show
  1. package/.xtrm/config/hooks.json +0 -3
  2. package/.xtrm/registry.json +537 -565
  3. package/.xtrm/skills/default/gitnexus-cli/SKILL.md +82 -0
  4. package/.xtrm/skills/default/gitnexus-exploring/SKILL.md +78 -0
  5. package/.xtrm/skills/default/gitnexus-guide/SKILL.md +64 -0
  6. package/.xtrm/skills/default/init-session/SKILL.md +3 -0
  7. package/.xtrm/skills/default/last30days/SKILL.md +1 -1
  8. package/.xtrm/skills/default/last30days/scripts/lib/youtube_yt.py +59 -40
  9. package/.xtrm/skills/default/sync-docs/references/doc-structure.md +1 -1
  10. package/.xtrm/skills/default/sync-docs/references/schema.md +1 -1
  11. package/.xtrm/skills/default/sync-docs/scripts/doc_structure_analyzer.py +2 -2
  12. package/.xtrm/skills/default/using-specialists/SKILL.md +346 -138
  13. package/.xtrm/skills/default/using-specialists/SKILL.safe.md +1082 -0
  14. package/.xtrm/skills/default/using-specialists/SKILL.ultra.md +1082 -0
  15. package/.xtrm/skills/default/vaultctl/SKILL.md +150 -0
  16. package/CHANGELOG.md +4 -4
  17. package/cli/dist/index.cjs +328 -192
  18. package/cli/dist/index.cjs.map +1 -1
  19. package/cli/package.json +1 -1
  20. package/package.json +8 -8
  21. package/packages/pi-extensions/MIGRATION_NOTES.md +39 -0
  22. package/packages/pi-extensions/README.md +43 -0
  23. package/packages/pi-extensions/extensions/README.md +5 -0
  24. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/beads/index.ts +1 -1
  25. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/beads/package.json +1 -4
  26. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/custom-footer/index.ts +1 -1
  27. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/custom-footer/package.json +1 -4
  28. package/packages/pi-extensions/extensions/custom-provider-qwen-cli/package.json +16 -0
  29. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/pi-serena-compact/package.json +9 -2
  30. package/{.xtrm/ext-src → packages/pi-extensions/extensions}/quality-gates/index.ts +1 -1
  31. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/quality-gates/package.json +1 -4
  32. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/service-skills/index.ts +1 -1
  33. package/{.xtrm/ext-src → packages/pi-extensions/extensions}/service-skills/package.json +1 -4
  34. package/{.xtrm/ext-src → packages/pi-extensions/extensions}/session-flow/index.ts +1 -1
  35. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/session-flow/package.json +1 -4
  36. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-loader/index.ts +1 -1
  37. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-loader/package.json +1 -4
  38. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-ui/index.ts +1 -1
  39. package/packages/pi-extensions/package.json +46 -0
  40. package/packages/pi-extensions/src/core/README.md +9 -0
  41. package/{.xtrm/ext-src/core/lib.ts → packages/pi-extensions/src/core/index.ts} +3 -1
  42. package/packages/pi-extensions/src/extensions/auto-session-name.ts +3 -0
  43. package/packages/pi-extensions/src/extensions/auto-update.ts +3 -0
  44. package/packages/pi-extensions/src/extensions/beads.ts +3 -0
  45. package/packages/pi-extensions/src/extensions/compact-header.ts +3 -0
  46. package/packages/pi-extensions/src/extensions/custom-footer.ts +3 -0
  47. package/packages/pi-extensions/src/extensions/custom-provider-qwen-cli.ts +3 -0
  48. package/packages/pi-extensions/src/extensions/git-checkpoint.ts +3 -0
  49. package/packages/pi-extensions/src/extensions/lsp-bootstrap.ts +3 -0
  50. package/packages/pi-extensions/src/extensions/pi-serena-compact.ts +3 -0
  51. package/packages/pi-extensions/src/extensions/quality-gates.ts +3 -0
  52. package/packages/pi-extensions/src/extensions/service-skills.ts +3 -0
  53. package/packages/pi-extensions/src/extensions/session-flow.ts +3 -0
  54. package/packages/pi-extensions/src/extensions/xtrm-loader.ts +3 -0
  55. package/packages/pi-extensions/src/extensions/xtrm-ui.ts +3 -0
  56. package/packages/pi-extensions/src/index.ts +9 -0
  57. package/packages/pi-extensions/src/registry.ts +52 -0
  58. package/packages/pi-extensions/src/shared/index.ts +1 -0
  59. package/packages/pi-extensions/src/shared/legacy-path-map.ts +23 -0
  60. package/.xtrm/config/pi/extensions/core/package.json +0 -18
  61. package/.xtrm/config/pi/extensions/custom-provider-qwen-cli/package.json +0 -1
  62. package/.xtrm/config/pi/extensions/quality-gates/index.ts +0 -66
  63. package/.xtrm/config/pi/extensions/service-skills/package.json +0 -19
  64. package/.xtrm/config/pi/extensions/session-flow/index.ts +0 -96
  65. package/.xtrm/config/pi/extensions/xtrm-ui/themes/pidex-dark.json +0 -89
  66. package/.xtrm/config/pi/extensions/xtrm-ui/themes/pidex-light.json +0 -89
  67. package/.xtrm/ext-src/auto-session-name/index.ts +0 -29
  68. package/.xtrm/ext-src/auto-session-name/package.json +0 -16
  69. package/.xtrm/ext-src/auto-update/index.ts +0 -71
  70. package/.xtrm/ext-src/auto-update/package.json +0 -16
  71. package/.xtrm/ext-src/beads/index.ts +0 -232
  72. package/.xtrm/ext-src/beads/package.json +0 -19
  73. package/.xtrm/ext-src/compact-header/index.ts +0 -69
  74. package/.xtrm/ext-src/compact-header/package.json +0 -16
  75. package/.xtrm/ext-src/core/adapter.ts +0 -52
  76. package/.xtrm/ext-src/core/guard-rules.ts +0 -100
  77. package/.xtrm/ext-src/core/logger.ts +0 -45
  78. package/.xtrm/ext-src/core/package.json +0 -18
  79. package/.xtrm/ext-src/core/runner.ts +0 -71
  80. package/.xtrm/ext-src/core/session-state.ts +0 -59
  81. package/.xtrm/ext-src/custom-footer/index.ts +0 -398
  82. package/.xtrm/ext-src/custom-footer/package.json +0 -19
  83. package/.xtrm/ext-src/custom-provider-qwen-cli/index.ts +0 -363
  84. package/.xtrm/ext-src/custom-provider-qwen-cli/package.json +0 -1
  85. package/.xtrm/ext-src/git-checkpoint/index.ts +0 -53
  86. package/.xtrm/ext-src/git-checkpoint/package.json +0 -16
  87. package/.xtrm/ext-src/lsp-bootstrap/index.ts +0 -134
  88. package/.xtrm/ext-src/lsp-bootstrap/package.json +0 -17
  89. package/.xtrm/ext-src/pi-serena-compact/index.ts +0 -121
  90. package/.xtrm/ext-src/pi-serena-compact/package.json +0 -16
  91. package/.xtrm/ext-src/quality-gates/package.json +0 -19
  92. package/.xtrm/ext-src/service-skills/index.ts +0 -108
  93. package/.xtrm/ext-src/session-flow/package.json +0 -19
  94. package/.xtrm/ext-src/xtrm-loader/index.ts +0 -152
  95. package/.xtrm/ext-src/xtrm-loader/package.json +0 -19
  96. package/.xtrm/ext-src/xtrm-ui/format.ts +0 -282
  97. package/.xtrm/ext-src/xtrm-ui/index.ts +0 -1112
  98. package/.xtrm/ext-src/xtrm-ui/package.json +0 -21
  99. /package/.xtrm/{ext-src → config/pi/extensions}/custom-footer/.pi/structured-returns/83051fe4-97da-4e2c-bdaa-343b32f4e714.combined.log +0 -0
  100. /package/.xtrm/{ext-src → config/pi/extensions}/custom-footer/.pi/structured-returns/83051fe4-97da-4e2c-bdaa-343b32f4e714.stderr.log +0 -0
  101. /package/.xtrm/{ext-src → config/pi/extensions}/custom-footer/.pi/structured-returns/83051fe4-97da-4e2c-bdaa-343b32f4e714.stdout.log +0 -0
  102. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/auto-session-name/index.ts +0 -0
  103. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/auto-session-name/package.json +0 -0
  104. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/auto-update/index.ts +0 -0
  105. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/auto-update/package.json +0 -0
  106. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/compact-header/index.ts +0 -0
  107. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/compact-header/package.json +0 -0
  108. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/custom-provider-qwen-cli/index.ts +0 -0
  109. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/git-checkpoint/index.ts +0 -0
  110. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/git-checkpoint/package.json +0 -0
  111. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/lsp-bootstrap/index.ts +0 -0
  112. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/lsp-bootstrap/package.json +0 -0
  113. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/pi-serena-compact/index.ts +0 -0
  114. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-ui/format.ts +0 -0
  115. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-ui/package.json +0 -0
  116. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/adapter.ts +0 -0
  117. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/guard-rules.ts +0 -0
  118. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/lib.ts +0 -0
  119. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/logger.ts +0 -0
  120. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/runner.ts +0 -0
  121. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/session-state.ts +0 -0
  122. /package/{.xtrm/ext-src/xtrm-ui/themes → packages/pi-extensions/themes/xtrm-ui}/pidex-dark.json +0 -0
  123. /package/{.xtrm/ext-src/xtrm-ui/themes → packages/pi-extensions/themes/xtrm-ui}/pidex-light.json +0 -0
@@ -1,121 +0,0 @@
1
- import type { ExtensionAPI, ToolResultEvent } from "@mariozechner/pi-coding-agent";
2
-
3
- // Serena/GitNexus MCP tool names that produce verbose output
4
- const COMPACT_TOOLS = new Set([
5
- // Serena symbol operations
6
- "find_symbol",
7
- "find_referencing_symbols",
8
- "get_symbols_overview",
9
- "jet_brains_find_symbol",
10
- "jet_brains_find_referencing_symbols",
11
- "jet_brains_get_symbols_overview",
12
- "jet_brains_type_hierarchy",
13
-
14
- // Serena file operations
15
- "read_file",
16
- "create_text_file",
17
- "replace_content",
18
- "replace_lines",
19
- "delete_lines",
20
- "insert_at_line",
21
-
22
- // Serena search/navigation
23
- "search_for_pattern",
24
- "list_dir",
25
- "find_file",
26
-
27
- // Serena symbol editing
28
- "replace_symbol_body",
29
- "insert_after_symbol",
30
- "insert_before_symbol",
31
- "rename_symbol",
32
-
33
- // GitNexus
34
- "gitnexus_query",
35
- "gitnexus_context",
36
- "gitnexus_impact",
37
- "gitnexus_detect_changes",
38
- "gitnexus_list_repos",
39
-
40
- // Serena memory
41
- "read_memory",
42
- "write_memory",
43
- "list_memories",
44
-
45
- // Other verbose tools
46
- "execute_shell_command",
47
- "structured_return",
48
- ]);
49
-
50
- // Tools that should show more output even when compacted
51
- const PRESERVE_OUTPUT_TOOLS = new Set([
52
- "read_file",
53
- "read_memory",
54
- "execute_shell_command",
55
- "structured_return",
56
- ]);
57
-
58
- function isSerenaTool(toolName: string): boolean {
59
- return COMPACT_TOOLS.has(toolName);
60
- }
61
-
62
- function getTextContent(content: Array<{ type: string; text?: string }>): string {
63
- const item = content.find((c) => c.type === "text");
64
- return item?.text ?? "";
65
- }
66
-
67
- function truncateLines(text: string, maxLines: number, maxLineLen = 180): string {
68
- const lines = text.split("\n");
69
- const truncated = lines.map(line =>
70
- line.length > maxLineLen ? line.slice(0, maxLineLen) + "…" : line
71
- );
72
-
73
- if (truncated.length <= maxLines) return truncated.join("\n");
74
- return truncated.slice(0, maxLines).join("\n") + `\n… +${truncated.length - maxLines} more lines`;
75
- }
76
-
77
- function compactResult(
78
- toolName: string,
79
- content: Array<{ type: string; text?: string }>,
80
- maxLines: number = 6,
81
- ): Array<{ type: string; text: string }> {
82
- const textContent = getTextContent(content);
83
-
84
- if (!textContent) {
85
- return [{ type: "text", text: "✓ No output" }];
86
- }
87
-
88
- // For certain tools, show more output
89
- const effectiveMaxLines = PRESERVE_OUTPUT_TOOLS.has(toolName) ? 12 : maxLines;
90
-
91
- const compacted = truncateLines(textContent, effectiveMaxLines, 180);
92
-
93
- return [{ type: "text", text: compacted }];
94
- }
95
-
96
- export default function serenaCompactExtension(pi: ExtensionAPI): void {
97
- let toolsExpanded = false;
98
-
99
- // Track tools expanded state
100
- pi.on("session_start", async (_event, ctx) => {
101
- toolsExpanded = ctx.ui.getToolsExpanded();
102
- });
103
-
104
- pi.on("session_switch", async (_event, ctx) => {
105
- toolsExpanded = ctx.ui.getToolsExpanded();
106
- });
107
-
108
- // Compact Serena tool results
109
- pi.on("tool_result", async (event: ToolResultEvent) => {
110
- // Only handle Serena/MCP tools
111
- if (!isSerenaTool(event.toolName)) return undefined;
112
-
113
- // If tools are expanded, don't compact
114
- if (toolsExpanded) return undefined;
115
-
116
- // Compact the content
117
- const compacted = compactResult(event.toolName, event.content, 6);
118
-
119
- return { content: compacted };
120
- });
121
- }
@@ -1,16 +0,0 @@
1
- {
2
- "name": "pi-serena-compact",
3
- "version": "1.0.0",
4
- "description": "Compact output for Serena MCP tools in Pi",
5
- "keywords": ["pi", "pi-extension", "serena", "mcp"],
6
- "license": "MIT",
7
- "type": "module",
8
- "main": "index.ts",
9
- "peerDependencies": {
10
- "@mariozechner/pi-coding-agent": "^0.56.0",
11
- "@mariozechner/pi-tui": "^0.56.0"
12
- },
13
- "pi": {
14
- "extensions": ["./index.ts"]
15
- }
16
- }
@@ -1,19 +0,0 @@
1
- {
2
- "name": "@xtrm/pi-quality-gates",
3
- "version": "1.0.0",
4
- "description": "xtrm Pi extension: quality-gates",
5
- "type": "module",
6
- "exports": {
7
- ".": "./index.ts"
8
- },
9
- "keywords": [
10
- "pi",
11
- "extension",
12
- "xtrm"
13
- ],
14
- "author": "xtrm",
15
- "license": "MIT",
16
- "dependencies": {
17
- "@xtrm/pi-core": "^1.0.0"
18
- }
19
- }
@@ -1,108 +0,0 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
- import { SubprocessRunner } from "@xtrm/pi-core";
3
- import * as path from "node:path";
4
- import * as fs from "node:fs";
5
-
6
- const SERVICE_REGISTRY_FILES = [
7
- "service-registry.json",
8
- path.join(".claude", "skills", "service-registry.json"),
9
- ];
10
-
11
- const GLOBAL_SKILL_ROOTS = [
12
- path.join(process.env.HOME || "", ".agents", "skills"),
13
- path.join(process.env.HOME || "", ".claude", "skills"),
14
- ];
15
-
16
- export default function (pi: ExtensionAPI) {
17
- const getCwd = (ctx: any) => ctx.cwd || process.cwd();
18
-
19
- const resolveRegistryPath = (cwd: string): string | null => {
20
- for (const rel of SERVICE_REGISTRY_FILES) {
21
- const candidate = path.join(cwd, rel);
22
- if (fs.existsSync(candidate)) return candidate;
23
- }
24
- return null;
25
- };
26
-
27
- const resolveSkillScript = (cwd: string, skillName: string, scriptName: string): string | null => {
28
- const localPath = path.join(cwd, ".claude", "skills", skillName, "scripts", scriptName);
29
- if (fs.existsSync(localPath)) return localPath;
30
-
31
- for (const root of GLOBAL_SKILL_ROOTS) {
32
- if (!root) continue;
33
- const candidate = path.join(root, skillName, "scripts", scriptName);
34
- if (fs.existsSync(candidate)) return candidate;
35
- }
36
-
37
- return null;
38
- };
39
-
40
- // 1. Catalog Injection
41
- pi.on("before_agent_start", async (event, ctx) => {
42
- const cwd = getCwd(ctx);
43
- const registryPath = resolveRegistryPath(cwd);
44
- if (!registryPath) return undefined;
45
-
46
- const catalogerPath = resolveSkillScript(cwd, "using-service-skills", "cataloger.py");
47
- if (!catalogerPath) return undefined;
48
-
49
- const result = await SubprocessRunner.run("python3", [catalogerPath], {
50
- cwd,
51
- env: {
52
- ...process.env,
53
- CLAUDE_PROJECT_DIR: cwd,
54
- SERVICE_REGISTRY_PATH: registryPath,
55
- },
56
- });
57
-
58
- if (result.code === 0 && result.stdout.trim()) {
59
- return { systemPrompt: event.systemPrompt + "\n\n" + result.stdout.trim() };
60
- }
61
- return undefined;
62
- });
63
-
64
- const toClaudeToolName = (toolName: string): string => {
65
- if (toolName === "bash") return "Bash";
66
- if (toolName === "read_file") return "Read";
67
- if (toolName === "write" || toolName === "create_text_file") return "Write";
68
- if (toolName === "edit" || toolName === "replace_content" || toolName === "replace_lines" || toolName === "insert_at_line" || toolName === "delete_lines") return "Edit";
69
- if (toolName === "search_for_pattern") return "Grep";
70
- if (toolName === "find_file" || toolName === "list_dir") return "Glob";
71
- return toolName;
72
- };
73
-
74
- // 2. Drift Detection (skill activation is before_agent_start only — not per-tool)
75
- pi.on("tool_result", async (event, ctx) => {
76
- const cwd = getCwd(ctx);
77
- const registryPath = resolveRegistryPath(cwd);
78
- if (!registryPath) return undefined;
79
-
80
- const driftDetectorPath = resolveSkillScript(cwd, "updating-service-skills", "drift_detector.py");
81
- if (!driftDetectorPath) return undefined;
82
-
83
- const hookInput = JSON.stringify({
84
- tool_name: toClaudeToolName(event.toolName),
85
- tool_input: event.input,
86
- cwd,
87
- });
88
-
89
- const result = await SubprocessRunner.run("python3", [driftDetectorPath], {
90
- cwd,
91
- input: hookInput,
92
- env: {
93
- ...process.env,
94
- CLAUDE_PROJECT_DIR: cwd,
95
- SERVICE_REGISTRY_PATH: registryPath,
96
- },
97
- timeoutMs: 10000,
98
- });
99
-
100
- if (result.code === 0 && result.stdout.trim()) {
101
- const newContent = [...event.content];
102
- newContent.push({ type: "text", text: "\n\n" + result.stdout.trim() });
103
- return { content: newContent };
104
- }
105
-
106
- return undefined;
107
- });
108
- }
@@ -1,19 +0,0 @@
1
- {
2
- "name": "@xtrm/pi-session-flow",
3
- "version": "1.0.0",
4
- "description": "xtrm Pi extension: session-flow",
5
- "type": "module",
6
- "exports": {
7
- ".": "./index.ts"
8
- },
9
- "keywords": [
10
- "pi",
11
- "extension",
12
- "xtrm"
13
- ],
14
- "author": "xtrm",
15
- "license": "MIT",
16
- "dependencies": {
17
- "@xtrm/pi-core": "^1.0.0"
18
- }
19
- }
@@ -1,152 +0,0 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
- import * as fs from "node:fs";
3
- import * as path from "node:path";
4
- import { homedir } from "node:os";
5
- import { Logger } from "@xtrm/pi-core";
6
-
7
- const logger = new Logger({ namespace: "xtrm-loader" });
8
-
9
- /**
10
- * Recursively find markdown files in a directory.
11
- */
12
- function findMarkdownFiles(dir: string, basePath: string = ""): string[] {
13
- const results: string[] = [];
14
- if (!fs.existsSync(dir)) return results;
15
-
16
- const entries = fs.readdirSync(dir, { withFileTypes: true });
17
- for (const entry of entries) {
18
- const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;
19
- if (entry.isDirectory()) {
20
- results.push(...findMarkdownFiles(path.join(dir, entry.name), relativePath));
21
- } else if (entry.isFile() && entry.name.endsWith(".md")) {
22
- results.push(relativePath);
23
- }
24
- }
25
- return results;
26
- }
27
-
28
- function resolveUsingXtrmSkillPath(cwd: string): string | null {
29
- const candidates = [
30
- path.join(homedir(), ".agents", "skills", "using-xtrm", "SKILL.md"),
31
- path.join(homedir(), ".pi", "agent", "skills", "using-xtrm", "SKILL.md"),
32
- path.join(cwd, ".pi", "skills", "using-xtrm", "SKILL.md"),
33
- ];
34
-
35
- for (const candidate of candidates) {
36
- if (fs.existsSync(candidate)) return candidate;
37
- }
38
- return null;
39
- }
40
-
41
- /**
42
- * Load a skill file, stripping YAML frontmatter.
43
- */
44
- function loadSkillContent(skillPath: string): string | null {
45
- try {
46
- const content = fs.readFileSync(skillPath, "utf8");
47
- return content.replace(/^---[\s\S]*?---\n/, "").trim();
48
- } catch {
49
- return null;
50
- }
51
- }
52
-
53
- export default function (pi: ExtensionAPI) {
54
- let projectContext: string = "";
55
- let usingXtrmContent: string | null = null;
56
-
57
- pi.on("session_start", async (_event, ctx) => {
58
- const cwd = ctx.cwd;
59
- const contextParts: string[] = [];
60
-
61
- // 0. Load using-xtrm skill (global/project fallback paths)
62
- const usingXtrmPath = resolveUsingXtrmSkillPath(cwd);
63
- usingXtrmContent = usingXtrmPath ? loadSkillContent(usingXtrmPath) : null;
64
- if (usingXtrmPath && usingXtrmContent) {
65
- logger.info(`Loaded using-xtrm skill from ${usingXtrmPath}`);
66
- }
67
-
68
- // 1. Architecture & Roadmap
69
- const roadmapPaths = [
70
- path.join(cwd, "architecture", "project_roadmap.md"),
71
- path.join(cwd, "ROADMAP.md"),
72
- path.join(cwd, "architecture", "index.md"),
73
- ];
74
-
75
- for (const p of roadmapPaths) {
76
- if (fs.existsSync(p)) {
77
- const content = await fs.promises.readFile(p, "utf8");
78
- contextParts.push(`## Project Roadmap & Architecture (${path.relative(cwd, p)})\n\n${content}`);
79
- break; // Only load the first one found
80
- }
81
- }
82
-
83
- // 2. Project Rules (.claude/rules)
84
- const rulesDir = path.join(cwd, ".claude", "rules");
85
- if (fs.existsSync(rulesDir)) {
86
- const ruleFiles = findMarkdownFiles(rulesDir);
87
- if (ruleFiles.length > 0) {
88
- const rulesContent = (
89
- await Promise.all(
90
- ruleFiles.map(async (f) => {
91
- const content = await fs.promises.readFile(path.join(rulesDir, f), "utf8");
92
- return `### Rule: ${f}\n${content}`;
93
- }),
94
- )
95
- ).join("\n\n");
96
- contextParts.push(`## Project Rules\n\n${rulesContent}`);
97
- }
98
- }
99
-
100
- // 3. Project Skills (.claude/skills)
101
- const skillsDir = path.join(cwd, ".claude", "skills");
102
- if (fs.existsSync(skillsDir)) {
103
- const skillFiles = findMarkdownFiles(skillsDir);
104
- if (skillFiles.length > 0) {
105
- const skillsContent = skillFiles
106
- .map((f) => `- ${f} (Path: .claude/skills/${f})`)
107
- .join("\n");
108
- contextParts.push(
109
- `## Available Project Skills\n\nExisting service skills and workflows found in .claude/skills/:\n\n${skillsContent}\n\nUse the read tool to load any of these skills if relevant to the current task.`,
110
- );
111
- }
112
- }
113
-
114
- projectContext = contextParts.join("\n\n---\n\n");
115
-
116
- if (projectContext && ctx.hasUI) {
117
- ctx.ui.notify("XTRM-Loader: Project context and skills indexed", "info");
118
- }
119
- });
120
-
121
- pi.on("before_agent_start", async (event, ctx) => {
122
- const parts: string[] = [];
123
-
124
- // Prepend using-xtrm skill (session operating manual)
125
- if (usingXtrmContent) {
126
- parts.push("# XTRM Session Operating Manual\n\n" + usingXtrmContent);
127
- }
128
-
129
- // Inject .xtrm/memory.md if present (synthesized project context)
130
- const memoryPath = path.join(ctx.cwd, ".xtrm", "memory.md");
131
- if (fs.existsSync(memoryPath)) {
132
- try {
133
- const memoryContent = fs.readFileSync(memoryPath, "utf8").trim();
134
- if (memoryContent) {
135
- parts.push(memoryContent);
136
- logger.info(`Injected .xtrm/memory.md (${memoryContent.length} chars)`);
137
- }
138
- } catch { /* fail open */ }
139
- }
140
-
141
- // Append project context
142
- if (projectContext) {
143
- parts.push("# Project Intelligence Context\n\n" + projectContext);
144
- }
145
-
146
- if (parts.length === 0) return undefined;
147
-
148
- return {
149
- systemPrompt: event.systemPrompt + "\n\n" + parts.join("\n\n---\n\n"),
150
- };
151
- });
152
- }
@@ -1,19 +0,0 @@
1
- {
2
- "name": "@xtrm/pi-xtrm-loader",
3
- "version": "1.0.0",
4
- "description": "xtrm Pi extension: xtrm-loader",
5
- "type": "module",
6
- "exports": {
7
- ".": "./index.ts"
8
- },
9
- "keywords": [
10
- "pi",
11
- "extension",
12
- "xtrm"
13
- ],
14
- "author": "xtrm",
15
- "license": "MIT",
16
- "dependencies": {
17
- "@xtrm/pi-core": "^1.0.0"
18
- }
19
- }