agentloom 0.1.1 → 0.1.3

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.
@@ -0,0 +1,16 @@
1
+ import type { Provider, ScopePaths } from "../types.js";
2
+ export declare function getProviderAgentsDir(paths: ScopePaths, provider: Provider): string;
3
+ export declare function getProviderCommandsDir(paths: ScopePaths, provider: Provider): string;
4
+ export declare function getProviderSkillsPaths(paths: ScopePaths, providers: Provider[]): string[];
5
+ export declare function getCursorMcpPath(paths: ScopePaths): string;
6
+ export declare function getClaudeMcpPath(paths: ScopePaths): string;
7
+ export declare function getClaudeSettingsPath(paths: ScopePaths): string;
8
+ export declare function getOpenCodeConfigPath(paths: ScopePaths): string;
9
+ export declare function getGeminiSettingsPath(paths: ScopePaths): string;
10
+ export declare function getCopilotMcpPath(paths: ScopePaths): string;
11
+ export declare function getCodexRootDir(paths: ScopePaths): string;
12
+ export declare function getCodexConfigPath(paths: ScopePaths): string;
13
+ export declare function getCodexAgentsDir(paths: ScopePaths): string;
14
+ export declare function getCodexPromptsDir(paths: ScopePaths): string;
15
+ export declare function getPiMcpPath(paths: ScopePaths): string;
16
+ export declare function getVsCodeSettingsPath(homeDir: string): string;
@@ -0,0 +1,154 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ export function getProviderAgentsDir(paths, provider) {
4
+ const workspaceRoot = paths.workspaceRoot;
5
+ const home = paths.homeDir;
6
+ switch (provider) {
7
+ case "cursor":
8
+ return paths.scope === "local"
9
+ ? path.join(workspaceRoot, ".cursor", "agents")
10
+ : path.join(home, ".cursor", "agents");
11
+ case "claude":
12
+ return paths.scope === "local"
13
+ ? path.join(workspaceRoot, ".claude", "agents")
14
+ : path.join(home, ".claude", "agents");
15
+ case "codex":
16
+ return path.join(getCodexRootDir(paths), "agents");
17
+ case "opencode":
18
+ return paths.scope === "local"
19
+ ? path.join(workspaceRoot, ".opencode", "agents")
20
+ : path.join(home, ".config", "opencode", "agents");
21
+ case "gemini":
22
+ return paths.scope === "local"
23
+ ? path.join(workspaceRoot, ".gemini", "agents")
24
+ : path.join(home, ".gemini", "agents");
25
+ case "copilot":
26
+ return paths.scope === "local"
27
+ ? path.join(workspaceRoot, ".github", "agents")
28
+ : path.join(home, ".vscode", "chatmodes");
29
+ case "pi":
30
+ return paths.scope === "local"
31
+ ? path.join(workspaceRoot, ".pi", "agents")
32
+ : path.join(home, ".pi", "agent", "agents");
33
+ default:
34
+ return path.join(workspaceRoot, ".agents", "unknown");
35
+ }
36
+ }
37
+ export function getProviderCommandsDir(paths, provider) {
38
+ const workspaceRoot = paths.workspaceRoot;
39
+ const home = paths.homeDir;
40
+ switch (provider) {
41
+ case "cursor":
42
+ return paths.scope === "local"
43
+ ? path.join(workspaceRoot, ".cursor", "commands")
44
+ : path.join(home, ".cursor", "commands");
45
+ case "claude":
46
+ return paths.scope === "local"
47
+ ? path.join(workspaceRoot, ".claude", "commands")
48
+ : path.join(home, ".claude", "commands");
49
+ case "codex":
50
+ return getCodexPromptsDir(paths);
51
+ case "opencode":
52
+ return paths.scope === "local"
53
+ ? path.join(workspaceRoot, ".opencode", "commands")
54
+ : path.join(home, ".config", "opencode", "commands");
55
+ case "gemini":
56
+ return paths.scope === "local"
57
+ ? path.join(workspaceRoot, ".gemini", "commands")
58
+ : path.join(home, ".gemini", "commands");
59
+ case "copilot":
60
+ return paths.scope === "local"
61
+ ? path.join(workspaceRoot, ".github", "prompts")
62
+ : path.join(home, ".github", "prompts");
63
+ case "pi":
64
+ return paths.scope === "local"
65
+ ? path.join(workspaceRoot, ".pi", "prompts")
66
+ : path.join(home, ".pi", "agent", "prompts");
67
+ default:
68
+ return path.join(workspaceRoot, ".agents", "unknown", "commands");
69
+ }
70
+ }
71
+ export function getProviderSkillsPaths(paths, providers) {
72
+ const targets = new Set();
73
+ const hasClaudeStyleProvider = providers.includes("claude") || providers.includes("copilot");
74
+ if (hasClaudeStyleProvider) {
75
+ targets.add(paths.scope === "local"
76
+ ? path.join(paths.workspaceRoot, ".claude", "skills")
77
+ : path.join(paths.homeDir, ".claude", "skills"));
78
+ }
79
+ if (providers.includes("cursor")) {
80
+ targets.add(paths.scope === "local"
81
+ ? path.join(paths.workspaceRoot, ".cursor", "skills")
82
+ : path.join(paths.homeDir, ".cursor", "skills"));
83
+ }
84
+ if (providers.includes("pi")) {
85
+ targets.add(paths.scope === "local"
86
+ ? path.join(paths.workspaceRoot, ".pi", "skills")
87
+ : path.join(paths.homeDir, ".pi", "agent", "skills"));
88
+ }
89
+ return [...targets];
90
+ }
91
+ export function getCursorMcpPath(paths) {
92
+ return paths.scope === "local"
93
+ ? path.join(paths.workspaceRoot, ".cursor", "mcp.json")
94
+ : path.join(paths.homeDir, ".cursor", "mcp.json");
95
+ }
96
+ export function getClaudeMcpPath(paths) {
97
+ return paths.scope === "local"
98
+ ? path.join(paths.workspaceRoot, ".mcp.json")
99
+ : path.join(paths.homeDir, ".mcp.json");
100
+ }
101
+ export function getClaudeSettingsPath(paths) {
102
+ return paths.scope === "local"
103
+ ? path.join(paths.workspaceRoot, ".claude", "settings.json")
104
+ : path.join(paths.homeDir, ".claude.json");
105
+ }
106
+ export function getOpenCodeConfigPath(paths) {
107
+ return paths.scope === "local"
108
+ ? path.join(paths.workspaceRoot, ".opencode", "opencode.json")
109
+ : path.join(paths.homeDir, ".config", "opencode", "opencode.json");
110
+ }
111
+ export function getGeminiSettingsPath(paths) {
112
+ return paths.scope === "local"
113
+ ? path.join(paths.workspaceRoot, ".gemini", "settings.json")
114
+ : path.join(paths.homeDir, ".gemini", "settings.json");
115
+ }
116
+ export function getCopilotMcpPath(paths) {
117
+ return paths.scope === "local"
118
+ ? path.join(paths.workspaceRoot, ".vscode", "mcp.json")
119
+ : path.join(paths.homeDir, ".vscode", "mcp.json");
120
+ }
121
+ export function getCodexRootDir(paths) {
122
+ return paths.scope === "local"
123
+ ? path.join(paths.workspaceRoot, ".codex")
124
+ : path.join(paths.homeDir, ".codex");
125
+ }
126
+ export function getCodexConfigPath(paths) {
127
+ return path.join(getCodexRootDir(paths), "config.toml");
128
+ }
129
+ export function getCodexAgentsDir(paths) {
130
+ return path.join(getCodexRootDir(paths), "agents");
131
+ }
132
+ export function getCodexPromptsDir(paths) {
133
+ return path.join(paths.homeDir, ".codex", "prompts");
134
+ }
135
+ export function getPiMcpPath(paths) {
136
+ return paths.scope === "local"
137
+ ? path.join(paths.workspaceRoot, ".pi", "mcp.json")
138
+ : path.join(paths.homeDir, ".pi", "agent", "mcp.json");
139
+ }
140
+ export function getVsCodeSettingsPath(homeDir) {
141
+ switch (os.platform()) {
142
+ case "darwin":
143
+ return path.join(homeDir, "Library", "Application Support", "Code", "User", "settings.json");
144
+ case "win32": {
145
+ const appData = process.env.APPDATA;
146
+ if (!appData) {
147
+ return path.join(homeDir, "AppData", "Roaming", "Code", "User", "settings.json");
148
+ }
149
+ return path.join(appData, "Code", "User", "settings.json");
150
+ }
151
+ default:
152
+ return path.join(homeDir, ".config", "Code", "User", "settings.json");
153
+ }
154
+ }
@@ -1,5 +1,5 @@
1
1
  import type { EntityType } from "../types.js";
2
- export type AggregateVerb = "add" | "find" | "update" | "sync" | "delete";
2
+ export type AggregateVerb = "add" | "find" | "update" | "sync" | "delete" | "init";
3
3
  export type EntityVerb = "add" | "list" | "delete" | "find" | "update" | "sync";
4
4
  export type McpServerVerb = "add" | "list" | "delete";
5
5
  export type CommandRoute = {
@@ -4,6 +4,7 @@ const AGGREGATE_VERBS = new Set([
4
4
  "update",
5
5
  "sync",
6
6
  "delete",
7
+ "init",
7
8
  ]);
8
9
  const ENTITY_NOUNS = new Set(["agent", "command", "mcp", "skill"]);
9
10
  const ENTITY_VERBS = new Set([
@@ -2,6 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import matter from "gray-matter";
4
4
  import { ensureDir, slugify } from "./fs.js";
5
+ import { getProviderSkillsPaths } from "./provider-paths.js";
5
6
  export const ROOT_SKILL_ARTIFACT_DIRS = [
6
7
  "references",
7
8
  "assets",
@@ -123,7 +124,7 @@ export function skillContentMatchesTarget(skill, targetDir) {
123
124
  return rootSkillArtifactsEqual(skill.sourcePath, targetDir);
124
125
  }
125
126
  export function applySkillProviderSideEffects(options) {
126
- const pathsToSymlink = resolveProviderSkillsPaths(options.paths, options.providers);
127
+ const pathsToSymlink = getProviderSkillsPaths(options.paths, options.providers);
127
128
  if (pathsToSymlink.length === 0)
128
129
  return;
129
130
  const canonicalSkillsDir = options.paths.skillsDir;
@@ -139,21 +140,6 @@ export function applySkillProviderSideEffects(options) {
139
140
  });
140
141
  }
141
142
  }
142
- function resolveProviderSkillsPaths(paths, providers) {
143
- const targets = new Set();
144
- const hasClaudeStyleProvider = providers.includes("claude") || providers.includes("copilot");
145
- if (hasClaudeStyleProvider) {
146
- targets.add(paths.scope === "local"
147
- ? path.join(paths.workspaceRoot, ".claude", "skills")
148
- : path.join(paths.homeDir, ".claude", "skills"));
149
- }
150
- if (providers.includes("cursor")) {
151
- targets.add(paths.scope === "local"
152
- ? path.join(paths.workspaceRoot, ".cursor", "skills")
153
- : path.join(paths.homeDir, ".cursor", "skills"));
154
- }
155
- return [...targets];
156
- }
157
143
  function enforceProviderSkillsSymlink(options) {
158
144
  const resolvedCanonical = realPathOrResolved(options.canonicalSkillsDir);
159
145
  const targetDir = options.targetSkillsDir;
@@ -5,4 +5,5 @@ type MaybeNotifyOptions = {
5
5
  };
6
6
  export declare function maybeNotifyVersionUpdate(options: MaybeNotifyOptions): Promise<void>;
7
7
  export declare function isNewerVersion(candidate: string, current: string): boolean;
8
+ export declare function promptAndUpdate(current: string, latest: string): Promise<"updated" | "declined" | "failed">;
8
9
  export {};
@@ -1,7 +1,9 @@
1
+ import { spawnSync } from "node:child_process";
1
2
  import fs from "node:fs";
2
3
  import https from "node:https";
3
4
  import os from "node:os";
4
5
  import path from "node:path";
6
+ import { confirm, isCancel } from "@clack/prompts";
5
7
  import { ensureDir, writeJsonAtomic } from "./fs.js";
6
8
  const UPDATE_CACHE_PATH = path.join(os.homedir(), ".agents", ".agentloom-version-cache.json");
7
9
  const CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
@@ -25,7 +27,7 @@ export async function maybeNotifyVersionUpdate(options) {
25
27
  if (cache.latestVersion &&
26
28
  isNewerVersion(cache.latestVersion, options.currentVersion) &&
27
29
  cache.lastNotifiedVersion !== cache.latestVersion) {
28
- printNotice(options.currentVersion, cache.latestVersion);
30
+ await promptAndUpdate(options.currentVersion, cache.latestVersion);
29
31
  cache.lastNotifiedVersion = cache.latestVersion;
30
32
  writeVersionCache(cache);
31
33
  }
@@ -44,7 +46,7 @@ export async function maybeNotifyVersionUpdate(options) {
44
46
  cache.latestVersion = latest;
45
47
  if (isNewerVersion(latest, options.currentVersion) &&
46
48
  cache.lastNotifiedVersion !== latest) {
47
- printNotice(options.currentVersion, latest);
49
+ await promptAndUpdate(options.currentVersion, latest);
48
50
  cache.lastNotifiedVersion = latest;
49
51
  }
50
52
  writeVersionCache(cache);
@@ -109,8 +111,24 @@ function fetchLatestVersion(packageName) {
109
111
  req.on("error", () => resolve(null));
110
112
  });
111
113
  }
112
- function printNotice(current, latest) {
113
- console.error(`\nUpdate available for agentloom: ${current} -> ${latest}\nRun: npm i -g agentloom\n`);
114
+ export async function promptAndUpdate(current, latest) {
115
+ const accepted = await confirm({
116
+ message: `Update available: ${current} → ${latest}. Update now?`,
117
+ initialValue: true,
118
+ });
119
+ if (isCancel(accepted) || !accepted)
120
+ return "declined";
121
+ console.log(`\nUpdating agentloom to ${latest}...\n`);
122
+ const result = spawnSync("npm", ["i", "-g", "agentloom"], {
123
+ stdio: "inherit",
124
+ });
125
+ if (result.status === 0) {
126
+ console.log(`\nUpdated to ${latest}. Please re-run your command.\n`);
127
+ process.exit(0);
128
+ return "updated"; // unreachable, but satisfies type checker
129
+ }
130
+ console.error(`\nUpdate failed. You can update manually: npm i -g agentloom\n`);
131
+ return "failed";
114
132
  }
115
133
  function readVersionCache() {
116
134
  try {
@@ -1,5 +1,4 @@
1
1
  import fs from "node:fs";
2
- import os from "node:os";
3
2
  import path from "node:path";
4
3
  import { cancel, isCancel, multiselect } from "@clack/prompts";
5
4
  import TOML from "@iarna/toml";
@@ -10,6 +9,7 @@ import { parseCommandsDir } from "../core/commands.js";
10
9
  import { ensureDir, isObject, readJsonIfExists, relativePosix, removeFileIfExists, slugify, toPosixPath, writeJsonAtomic, writeTextAtomic, } from "../core/fs.js";
11
10
  import { readManifest, writeManifest } from "../core/manifest.js";
12
11
  import { readCanonicalMcp, resolveMcpForProvider } from "../core/mcp.js";
12
+ import { getClaudeMcpPath, getClaudeSettingsPath, getCodexAgentsDir, getCodexConfigPath, getCodexRootDir, getCopilotMcpPath, getCursorMcpPath, getGeminiSettingsPath, getOpenCodeConfigPath, getPiMcpPath, getProviderAgentsDir, getProviderCommandsDir, getVsCodeSettingsPath, } from "../core/provider-paths.js";
13
13
  import { getGlobalSettingsPath, readSettings, updateLastScope, updateLastScopeBestEffort, } from "../core/settings.js";
14
14
  export async function resolveProvidersForSync(options) {
15
15
  const settings = readSettings(options.paths.settingsPath);
@@ -150,6 +150,7 @@ const PROVIDER_LABELS = {
150
150
  opencode: "OpenCode",
151
151
  gemini: "Gemini",
152
152
  copilot: "Copilot",
153
+ pi: "Pi",
153
154
  };
154
155
  const MULTISELECT_HELP_TEXT = "↑↓ move, space select, enter confirm";
155
156
  function withMultiselectHelp(message) {
@@ -226,38 +227,6 @@ function buildProviderAgentContent(provider, agent, providerConfig) {
226
227
  const fm = YAML.stringify(frontmatter).trimEnd();
227
228
  return `---\n${fm}\n---\n\n${agent.body.trimStart()}${agent.body.endsWith("\n") ? "" : "\n"}`;
228
229
  }
229
- function getProviderAgentsDir(paths, provider) {
230
- const workspaceRoot = paths.workspaceRoot;
231
- const home = paths.homeDir;
232
- switch (provider) {
233
- case "cursor":
234
- return paths.scope === "local"
235
- ? path.join(workspaceRoot, ".cursor", "agents")
236
- : path.join(home, ".cursor", "agents");
237
- case "claude":
238
- return paths.scope === "local"
239
- ? path.join(workspaceRoot, ".claude", "agents")
240
- : path.join(home, ".claude", "agents");
241
- case "codex":
242
- return paths.scope === "local"
243
- ? path.join(workspaceRoot, ".codex", "agents")
244
- : path.join(home, ".codex", "agents");
245
- case "opencode":
246
- return paths.scope === "local"
247
- ? path.join(workspaceRoot, ".opencode", "agents")
248
- : path.join(home, ".config", "opencode", "agents");
249
- case "gemini":
250
- return paths.scope === "local"
251
- ? path.join(workspaceRoot, ".gemini", "agents")
252
- : path.join(home, ".gemini", "agents");
253
- case "copilot":
254
- return paths.scope === "local"
255
- ? path.join(workspaceRoot, ".github", "agents")
256
- : path.join(home, ".vscode", "chatmodes");
257
- default:
258
- return path.join(workspaceRoot, ".agents", "unknown");
259
- }
260
- }
261
230
  function syncProviderCommands(options) {
262
231
  const providerDir = getProviderCommandsDir(options.paths, options.provider);
263
232
  for (const command of options.commands) {
@@ -292,45 +261,13 @@ function mapProviderCommandFileName(provider, fileName) {
292
261
  }
293
262
  return fileName;
294
263
  }
295
- function getProviderCommandsDir(paths, provider) {
296
- const workspaceRoot = paths.workspaceRoot;
297
- const home = paths.homeDir;
298
- switch (provider) {
299
- case "cursor":
300
- return paths.scope === "local"
301
- ? path.join(workspaceRoot, ".cursor", "commands")
302
- : path.join(home, ".cursor", "commands");
303
- case "claude":
304
- return paths.scope === "local"
305
- ? path.join(workspaceRoot, ".claude", "commands")
306
- : path.join(home, ".claude", "commands");
307
- case "codex":
308
- return path.join(home, ".codex", "prompts");
309
- case "opencode":
310
- return paths.scope === "local"
311
- ? path.join(workspaceRoot, ".opencode", "commands")
312
- : path.join(home, ".config", "opencode", "commands");
313
- case "gemini":
314
- return paths.scope === "local"
315
- ? path.join(workspaceRoot, ".gemini", "commands")
316
- : path.join(home, ".gemini", "commands");
317
- case "copilot":
318
- return paths.scope === "local"
319
- ? path.join(workspaceRoot, ".github", "prompts")
320
- : path.join(home, ".github", "prompts");
321
- default:
322
- return path.join(workspaceRoot, ".agents", "unknown", "commands");
323
- }
324
- }
325
264
  function syncProviderMcp(options) {
326
265
  for (const provider of options.providers) {
327
266
  if (provider === "codex")
328
267
  continue;
329
268
  const resolved = resolveMcpForProvider(options.mcp, provider);
330
269
  if (provider === "cursor") {
331
- const outputPath = options.paths.scope === "local"
332
- ? path.join(options.paths.workspaceRoot, ".cursor", "mcp.json")
333
- : path.join(options.paths.homeDir, ".cursor", "mcp.json");
270
+ const outputPath = getCursorMcpPath(options.paths);
334
271
  const payload = {
335
272
  mcpServers: mapMcpServers(resolved, ["url", "command", "args", "env"]),
336
273
  };
@@ -339,12 +276,8 @@ function syncProviderMcp(options) {
339
276
  continue;
340
277
  }
341
278
  if (provider === "claude") {
342
- const mcpPath = options.paths.scope === "local"
343
- ? path.join(options.paths.workspaceRoot, ".mcp.json")
344
- : path.join(options.paths.homeDir, ".mcp.json");
345
- const settingsPath = options.paths.scope === "local"
346
- ? path.join(options.paths.workspaceRoot, ".claude", "settings.json")
347
- : path.join(options.paths.homeDir, ".claude.json");
279
+ const mcpPath = getClaudeMcpPath(options.paths);
280
+ const settingsPath = getClaudeSettingsPath(options.paths);
348
281
  const claudeServers = mapMcpServers(resolved, [
349
282
  "type",
350
283
  "url",
@@ -366,9 +299,7 @@ function syncProviderMcp(options) {
366
299
  continue;
367
300
  }
368
301
  if (provider === "opencode") {
369
- const outputPath = options.paths.scope === "local"
370
- ? path.join(options.paths.workspaceRoot, ".opencode", "opencode.json")
371
- : path.join(options.paths.homeDir, ".config", "opencode", "opencode.json");
302
+ const outputPath = getOpenCodeConfigPath(options.paths);
372
303
  const existing = readJsonIfExists(outputPath) ?? {};
373
304
  const mcp = {};
374
305
  for (const [serverName, config] of Object.entries(resolved)) {
@@ -398,9 +329,7 @@ function syncProviderMcp(options) {
398
329
  continue;
399
330
  }
400
331
  if (provider === "gemini") {
401
- const outputPath = options.paths.scope === "local"
402
- ? path.join(options.paths.workspaceRoot, ".gemini", "settings.json")
403
- : path.join(options.paths.homeDir, ".gemini", "settings.json");
332
+ const outputPath = getGeminiSettingsPath(options.paths);
404
333
  const existing = readJsonIfExists(outputPath) ?? {};
405
334
  const experimental = isObject(existing.experimental)
406
335
  ? { ...existing.experimental }
@@ -429,9 +358,7 @@ function syncProviderMcp(options) {
429
358
  continue;
430
359
  }
431
360
  if (provider === "copilot") {
432
- const profileMcpPath = options.paths.scope === "local"
433
- ? path.join(options.paths.workspaceRoot, ".vscode", "mcp.json")
434
- : path.join(options.paths.homeDir, ".vscode", "mcp.json");
361
+ const profileMcpPath = getCopilotMcpPath(options.paths);
435
362
  const copilotServers = mapMcpServers(resolved, [
436
363
  "type",
437
364
  "url",
@@ -458,14 +385,21 @@ function syncProviderMcp(options) {
458
385
  options.generated.add(settingsPath);
459
386
  }
460
387
  }
388
+ if (provider === "pi") {
389
+ const outputPath = getPiMcpPath(options.paths);
390
+ const payload = {
391
+ mcpServers: mapMcpServers(resolved, ["url", "command", "args", "env"]),
392
+ };
393
+ maybeWriteJson(outputPath, payload, options.dryRun);
394
+ options.generated.add(outputPath);
395
+ continue;
396
+ }
461
397
  }
462
398
  }
463
399
  function syncCodex(options) {
464
- const codexDir = options.paths.scope === "local"
465
- ? path.join(options.paths.workspaceRoot, ".codex")
466
- : path.join(options.paths.homeDir, ".codex");
467
- const codexConfigPath = path.join(codexDir, "config.toml");
468
- const codexAgentsDir = path.join(codexDir, "agents");
400
+ const codexDir = getCodexRootDir(options.paths);
401
+ const codexConfigPath = getCodexConfigPath(options.paths);
402
+ const codexAgentsDir = getCodexAgentsDir(options.paths);
469
403
  const rawConfig = fs.existsSync(codexConfigPath)
470
404
  ? fs.readFileSync(codexConfigPath, "utf8")
471
405
  : "";
@@ -631,21 +565,6 @@ async function removeStaleGeneratedFiles(options) {
631
565
  }
632
566
  return stale;
633
567
  }
634
- function getVsCodeSettingsPath(homeDir) {
635
- switch (os.platform()) {
636
- case "darwin":
637
- return path.join(homeDir, "Library", "Application Support", "Code", "User", "settings.json");
638
- case "win32": {
639
- const appData = process.env.APPDATA;
640
- if (!appData) {
641
- return path.join(homeDir, "AppData", "Roaming", "Code", "User", "settings.json");
642
- }
643
- return path.join(appData, "Code", "User", "settings.json");
644
- }
645
- default:
646
- return path.join(homeDir, ".config", "Code", "User", "settings.json");
647
- }
648
- }
649
568
  function normalizeGeneratedByEntity(manifest) {
650
569
  const source = manifest.generatedByEntity;
651
570
  if (!source || typeof source !== "object") {
@@ -695,7 +614,8 @@ function isLegacyCommandOutputPath(normalizedPath) {
695
614
  normalizedPath.includes("/.opencode/commands/") ||
696
615
  normalizedPath.includes("/.gemini/commands/") ||
697
616
  normalizedPath.includes("/.github/prompts/") ||
698
- normalizedPath.includes("/.codex/prompts/"));
617
+ normalizedPath.includes("/.codex/prompts/") ||
618
+ normalizedPath.includes("/.pi/prompts/"));
699
619
  }
700
620
  function isLegacyAgentOutputPath(normalizedPath) {
701
621
  return (normalizedPath.includes("/.cursor/agents/") ||
@@ -704,7 +624,8 @@ function isLegacyAgentOutputPath(normalizedPath) {
704
624
  normalizedPath.includes("/.opencode/agents/") ||
705
625
  normalizedPath.includes("/.gemini/agents/") ||
706
626
  normalizedPath.includes("/.github/agents/") ||
707
- normalizedPath.includes("/.codex/agents/"));
627
+ normalizedPath.includes("/.codex/agents/") ||
628
+ normalizedPath.includes("/.pi/agents/"));
708
629
  }
709
630
  function isLegacyMcpOutputPath(normalizedPath) {
710
631
  return (normalizedPath.endsWith("/.cursor/mcp.json") ||
@@ -713,7 +634,9 @@ function isLegacyMcpOutputPath(normalizedPath) {
713
634
  normalizedPath.endsWith("/.opencode/opencode.json") ||
714
635
  normalizedPath.endsWith("/.gemini/settings.json") ||
715
636
  normalizedPath.endsWith("/.vscode/mcp.json") ||
716
- normalizedPath.endsWith("/code/user/settings.json"));
637
+ normalizedPath.endsWith("/code/user/settings.json") ||
638
+ normalizedPath.endsWith("/.pi/mcp.json") ||
639
+ normalizedPath.endsWith("/.pi/agent/mcp.json"));
717
640
  }
718
641
  function isLegacyCodexConfigPath(normalizedPath) {
719
642
  return normalizedPath.endsWith("/.codex/config.toml");
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const ALL_PROVIDERS: readonly ["cursor", "claude", "codex", "opencode", "gemini", "copilot"];
1
+ export declare const ALL_PROVIDERS: readonly ["cursor", "claude", "codex", "opencode", "gemini", "copilot", "pi"];
2
2
  export type Provider = (typeof ALL_PROVIDERS)[number];
3
3
  export type Scope = "local" | "global";
4
4
  export type EntityType = "agent" | "command" | "mcp" | "skill";
@@ -12,6 +12,7 @@ export interface AgentFrontmatter {
12
12
  opencode?: Record<string, unknown> | false;
13
13
  gemini?: Record<string, unknown> | false;
14
14
  copilot?: Record<string, unknown> | false;
15
+ pi?: Record<string, unknown> | false;
15
16
  [key: string]: unknown;
16
17
  }
17
18
  export interface CanonicalAgent {
package/dist/types.js CHANGED
@@ -5,4 +5,5 @@ export const ALL_PROVIDERS = [
5
5
  "opencode",
6
6
  "gemini",
7
7
  "copilot",
8
+ "pi",
8
9
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentloom",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Unified agent and MCP sync CLI for multi-provider AI tooling",
5
5
  "type": "module",
6
6
  "bin": {