@jcode.labs/ragmir 2.10.0 → 2.12.0

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 (64) hide show
  1. package/README.md +12 -1
  2. package/dist/chunk-stats.d.ts +8 -0
  3. package/dist/chunk-stats.d.ts.map +1 -0
  4. package/dist/chunk-stats.js +31 -0
  5. package/dist/chunk-stats.js.map +1 -0
  6. package/dist/cli.js +125 -8
  7. package/dist/cli.js.map +1 -1
  8. package/dist/context-resources.d.ts +4 -0
  9. package/dist/context-resources.d.ts.map +1 -0
  10. package/dist/context-resources.js +87 -0
  11. package/dist/context-resources.js.map +1 -0
  12. package/dist/doctor.d.ts.map +1 -1
  13. package/dist/doctor.js +15 -4
  14. package/dist/doctor.js.map +1 -1
  15. package/dist/evaluate.d.ts.map +1 -1
  16. package/dist/evaluate.js +8 -0
  17. package/dist/evaluate.js.map +1 -1
  18. package/dist/gitignore.d.ts +1 -1
  19. package/dist/gitignore.d.ts.map +1 -1
  20. package/dist/gitignore.js +3 -2
  21. package/dist/gitignore.js.map +1 -1
  22. package/dist/index.d.ts +6 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +4 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/ingest.d.ts.map +1 -1
  27. package/dist/ingest.js +7 -1
  28. package/dist/ingest.js.map +1 -1
  29. package/dist/knowledge-bases.d.ts +4 -0
  30. package/dist/knowledge-bases.d.ts.map +1 -0
  31. package/dist/knowledge-bases.js +113 -0
  32. package/dist/knowledge-bases.js.map +1 -0
  33. package/dist/mcp.d.ts +3 -1
  34. package/dist/mcp.d.ts.map +1 -1
  35. package/dist/mcp.js +38 -7
  36. package/dist/mcp.js.map +1 -1
  37. package/dist/package-manager.d.ts +2 -0
  38. package/dist/package-manager.d.ts.map +1 -1
  39. package/dist/package-manager.js +18 -1
  40. package/dist/package-manager.js.map +1 -1
  41. package/dist/preview.d.ts +3 -0
  42. package/dist/preview.d.ts.map +1 -0
  43. package/dist/preview.js +115 -0
  44. package/dist/preview.js.map +1 -0
  45. package/dist/query.d.ts.map +1 -1
  46. package/dist/query.js +70 -21
  47. package/dist/query.js.map +1 -1
  48. package/dist/research.d.ts.map +1 -1
  49. package/dist/research.js +2 -0
  50. package/dist/research.js.map +1 -1
  51. package/dist/setup.d.ts +3 -1
  52. package/dist/setup.d.ts.map +1 -1
  53. package/dist/setup.js +10 -5
  54. package/dist/setup.js.map +1 -1
  55. package/dist/skill.d.ts +16 -3
  56. package/dist/skill.d.ts.map +1 -1
  57. package/dist/skill.js +319 -20
  58. package/dist/skill.js.map +1 -1
  59. package/dist/types.d.ts +142 -0
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/version.d.ts +1 -1
  62. package/dist/version.js +1 -1
  63. package/package.json +3 -3
  64. package/skills/ragmir/SKILL.md +28 -0
package/dist/setup.js CHANGED
@@ -6,10 +6,10 @@ import { ingest } from "./ingest.js";
6
6
  import { initProject } from "./init.js";
7
7
  import { rgrCommand } from "./package-manager.js";
8
8
  import { enableSemanticEmbeddings } from "./semantic-config.js";
9
- import { installSkill } from "./skill.js";
9
+ import { installAgentSkills, } from "./skill.js";
10
10
  const CONFIGURATION_PROMPT = `You are helping configure Ragmir for this repository.
11
11
 
12
- Work from the repository root where \`rgr setup\` was run. Your goal is to improve \`.ragmir/config.json\` so Ragmir indexes useful repository knowledge without indexing secrets, generated files, or noisy bulk data.
12
+ Work from the knowledge-base root where \`rgr setup\` was run. Your goal is to improve \`.ragmir/config.json\` so Ragmir indexes useful repository knowledge without indexing secrets, generated files, or noisy bulk data. In a monorepo with nested Ragmir bases, keep an app base scoped to that app; only the root base should index shared or cross-app knowledge.
13
13
 
14
14
  Tasks:
15
15
  1. Inspect the repository structure and the current \`.ragmir/config.json\`.
@@ -24,7 +24,7 @@ Keep all proposed paths relative to the repository root. Do not add secrets or p
24
24
  export async function setupProject(options = {}) {
25
25
  const cwd = path.resolve(options.cwd ?? process.cwd());
26
26
  const created = await initProject(cwd);
27
- const installOptions = { cwd };
27
+ const installOptions = { cwd, scope: "project", mode: "link" };
28
28
  if (options.targetDir !== undefined) {
29
29
  installOptions.targetDir = options.targetDir;
30
30
  }
@@ -40,7 +40,11 @@ export async function setupProject(options = {}) {
40
40
  if (options.mcpArgs !== undefined) {
41
41
  installOptions.mcpArgs = options.mcpArgs;
42
42
  }
43
- const agentKit = await installSkill(installOptions);
43
+ if (options.forceAgentSkills !== undefined) {
44
+ installOptions.force = options.forceAgentSkills;
45
+ }
46
+ const agentSkills = await installAgentSkills(installOptions);
47
+ const agentKit = agentSkills.projectKit;
44
48
  const semantic = options.semantic ? await setupSemanticEmbeddings(cwd) : null;
45
49
  let report = await doctor(cwd);
46
50
  let ingested = null;
@@ -55,6 +59,7 @@ export async function setupProject(options = {}) {
55
59
  runCommand: command.display,
56
60
  created,
57
61
  agentKit,
62
+ agentInstallations: agentSkills.installations,
58
63
  semantic,
59
64
  ingested,
60
65
  doctor: report,
@@ -80,7 +85,7 @@ function setupNextSteps(report) {
80
85
  if (report.ready) {
81
86
  return [
82
87
  "Ask questions with the search or ask command shown by `rgr doctor`.",
83
- "Run `rgr install-agent --agents claude` or another targeted agent list for native skill discovery.",
88
+ "Restart or reload the selected agents so they discover the installed Ragmir skills.",
84
89
  "Wire the matching MCP helper from .ragmir/ when the agent should call Ragmir tools directly.",
85
90
  ];
86
91
  }
package/dist/setup.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
package/dist/skill.d.ts CHANGED
@@ -22,19 +22,19 @@ export interface InstallSkillResult {
22
22
  clineConfigPath: string;
23
23
  agentSetupPath: string;
24
24
  readmePath: string;
25
+ runnerPath: string;
25
26
  agentHelpers: AgentHelperFile[];
26
27
  mcpServerName: string;
27
28
  mcpCommand: string;
28
29
  mcpArgs: string[];
29
30
  written: string[];
30
31
  }
31
- export interface InstallAgentSkillsOptions {
32
- cwd?: string;
33
- agents?: readonly AgentTarget[];
32
+ export interface InstallAgentSkillsOptions extends InstallSkillOptions {
34
33
  scope?: AgentInstallScope;
35
34
  mode?: AgentInstallMode;
36
35
  homeDir?: string;
37
36
  env?: Record<string, string | undefined>;
37
+ force?: boolean;
38
38
  }
39
39
  export interface AgentSkillInstallation {
40
40
  agent: AgentTarget;
@@ -54,6 +54,18 @@ export interface AgentHelperFile {
54
54
  label: string;
55
55
  path: string;
56
56
  }
57
+ export type RagmirRunnerMode = "local-bin" | "workspace" | "installed-package" | "npm-cache";
58
+ export interface AgentIntegrationReport {
59
+ runnerPath: string;
60
+ runnerReady: boolean;
61
+ runnerMode: RagmirRunnerMode | null;
62
+ runnerRequiresDownload: boolean;
63
+ projectAgents: AgentTarget[];
64
+ userAgents: AgentTarget[];
65
+ nativeAgents: AgentTarget[];
66
+ ready: boolean;
67
+ warnings: string[];
68
+ }
57
69
  export declare const SKILL_NAMES: readonly ["ragmir", "ragmir-audio-summary", "ragmir-markdown-report", "ragmir-legal-dossier"];
58
70
  export declare const MCP_CONFIG_FILENAME = "mcp.json";
59
71
  export declare const AGENT_SETUP_FILENAME = "agent-setup.md";
@@ -63,4 +75,5 @@ export declare function bundledSkillPath(skillName?: string): string;
63
75
  export declare function parseAgentTargets(value: string | readonly string[] | undefined): AgentTarget[];
64
76
  export declare function installSkill(options?: InstallSkillOptions): Promise<InstallSkillResult>;
65
77
  export declare function installAgentSkills(options?: InstallAgentSkillsOptions): Promise<InstallAgentSkillsResult>;
78
+ export declare function inspectAgentIntegration(cwd?: string, homeDir?: string, env?: Record<string, string | undefined>): AgentIntegrationReport;
66
79
  //# sourceMappingURL=skill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"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"}
package/dist/skill.js CHANGED
@@ -1,9 +1,13 @@
1
- import { cp, mkdir, rm, symlink, writeFile } from "node:fs/promises";
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { cp, lstat, mkdir, readFile, realpath, rm, symlink, writeFile } from "node:fs/promises";
2
4
  import path from "node:path";
3
5
  import { fileURLToPath } from "node:url";
4
6
  import { DEFAULT_SKILL_TARGET_DIR, RAGMIR_DIR, RAGMIR_PROJECT_ROOT_ENV } from "./defaults.js";
5
7
  import { ensureRagmirGitignore } from "./gitignore.js";
6
- import { rgrCommand } from "./package-manager.js";
8
+ import { knowledgeBaseIdentity } from "./knowledge-bases.js";
9
+ import { RGR_RUNNER_FILENAME, RGR_RUNNER_PROBE_ARG, rgrCommand, } from "./package-manager.js";
10
+ import { VERSION } from "./version.js";
7
11
  const PACKAGE_ROOT = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
8
12
  const PRIMARY_SKILL_NAME = "ragmir";
9
13
  const AUDIO_SKILL_NAME = "ragmir-audio-summary";
@@ -11,6 +15,7 @@ const REPORT_SKILL_NAME = "ragmir-markdown-report";
11
15
  const LEGAL_SKILL_NAME = "ragmir-legal-dossier";
12
16
  const DEFAULT_MCP_SERVER_NAME = "ragmir";
13
17
  const MCP_SERVER_NAME_PATTERN = /^[A-Za-z0-9_-]+$/u;
18
+ const MANAGED_SKILL_METADATA_FILENAME = ".ragmir-managed.json";
14
19
  export const SKILL_NAMES = [
15
20
  PRIMARY_SKILL_NAME,
16
21
  AUDIO_SKILL_NAME,
@@ -53,8 +58,8 @@ const AGENT_DESTINATIONS = {
53
58
  codex: {
54
59
  label: "Codex",
55
60
  env: "CODEX_SKILLS_DIR",
56
- projectDir: path.join(".codex", "skills"),
57
- userDir: (homeDir) => path.join(homeDir, ".codex", "skills"),
61
+ projectDir: path.join(".agents", "skills"),
62
+ userDir: (homeDir) => path.join(homeDir, ".agents", "skills"),
58
63
  },
59
64
  kimi: {
60
65
  label: "Kimi Code CLI",
@@ -105,7 +110,7 @@ export async function installSkill(options = {}) {
105
110
  const targetDir = path.resolve(cwd, options.targetDir ?? DEFAULT_SKILL_TARGET_DIR);
106
111
  const agents = options.agents ? parseAgentTargets(options.agents) : [...SUPPORTED_AGENT_TARGETS];
107
112
  const agentSet = new Set(agents);
108
- const mcpServerName = normalizeMcpServerName(options.mcpServerName);
113
+ const mcpServerName = normalizeMcpServerName(options.mcpServerName ?? suggestedMcpServerName(cwd));
109
114
  const skillPath = path.join(targetDir, PRIMARY_SKILL_NAME);
110
115
  const audioSkillPath = path.join(targetDir, AUDIO_SKILL_NAME);
111
116
  const reportSkillPath = path.join(targetDir, REPORT_SKILL_NAME);
@@ -126,13 +131,15 @@ export async function installSkill(options = {}) {
126
131
  const clineConfigPath = agentConfigPaths.cline;
127
132
  const agentSetupPath = path.join(ragmirDir, AGENT_SETUP_FILENAME);
128
133
  const readmePath = path.join(ragmirDir, "README.md");
134
+ const runnerPath = path.join(ragmirDir, RGR_RUNNER_FILENAME);
129
135
  await mkdir(targetDir, { recursive: true });
130
136
  await mkdir(ragmirDir, { recursive: true });
131
137
  await copyBundledSkills(targetDir);
138
+ await writeFile(runnerPath, ragmirRunnerSource(VERSION, path.join(PACKAGE_ROOT, "dist", "cli.js")), { encoding: "utf8", mode: 0o755 });
132
139
  const serveCommand = await resolveMcpCommand(cwd, options);
133
140
  const doctorCommand = await rgrCommand(cwd, ["doctor"]);
134
141
  const installAgentCommand = await rgrCommand(cwd, ["install-agent", "--agents", agents.join(",")]);
135
- await writeFile(mcpConfigPath, `${JSON.stringify(mcpConfig(cwd, serveCommand, undefined, mcpServerName), null, 2)}\n`, "utf8");
142
+ await writeFile(mcpConfigPath, `${JSON.stringify(mcpConfig(cwd, serveCommand, { [RAGMIR_PROJECT_ROOT_ENV]: cwd }, mcpServerName), null, 2)}\n`, "utf8");
136
143
  const agentHelpers = [];
137
144
  for (const agent of SUPPORTED_AGENT_TARGETS) {
138
145
  const helperPath = agentConfigPaths[agent];
@@ -197,6 +204,7 @@ export async function installSkill(options = {}) {
197
204
  path.relative(cwd, audioSkillPath),
198
205
  path.relative(cwd, reportSkillPath),
199
206
  path.relative(cwd, legalSkillPath),
207
+ path.relative(cwd, runnerPath),
200
208
  path.relative(cwd, mcpConfigPath),
201
209
  ...agentHelpers.map((helper) => path.relative(cwd, helper.path)),
202
210
  path.relative(cwd, agentSetupPath),
@@ -218,6 +226,7 @@ export async function installSkill(options = {}) {
218
226
  clineConfigPath,
219
227
  agentSetupPath,
220
228
  readmePath,
229
+ runnerPath,
221
230
  agentHelpers,
222
231
  mcpServerName,
223
232
  mcpCommand: serveCommand.command,
@@ -232,7 +241,16 @@ export async function installAgentSkills(options = {}) {
232
241
  const homeDir = path.resolve(options.homeDir ?? process.env.HOME ?? process.cwd());
233
242
  const env = options.env ?? process.env;
234
243
  const agents = options.agents ?? SUPPORTED_AGENT_TARGETS;
235
- const projectKit = await installSkill({ cwd, agents });
244
+ const installOptions = { cwd, agents };
245
+ if (options.targetDir !== undefined)
246
+ installOptions.targetDir = options.targetDir;
247
+ if (options.mcpServerName !== undefined)
248
+ installOptions.mcpServerName = options.mcpServerName;
249
+ if (options.mcpCommand !== undefined)
250
+ installOptions.mcpCommand = options.mcpCommand;
251
+ if (options.mcpArgs !== undefined)
252
+ installOptions.mcpArgs = options.mcpArgs;
253
+ const projectKit = await installSkill(installOptions);
236
254
  const sourceDir = path.dirname(projectKit.skillPath);
237
255
  const installations = [];
238
256
  const written = [];
@@ -240,7 +258,7 @@ export async function installAgentSkills(options = {}) {
240
258
  const destination = AGENT_DESTINATIONS[agent];
241
259
  const targetDir = agentTargetDir(agent, scope, cwd, homeDir, env);
242
260
  await mkdir(targetDir, { recursive: true });
243
- const { mode, skillPaths } = await exposeAgentSkills(sourceDir, targetDir, requestedMode);
261
+ const { mode, skillPaths } = await exposeAgentSkills(sourceDir, targetDir, requestedMode, options.force ?? false);
244
262
  written.push(...skillPaths.map((skillPath) => displayPath(cwd, skillPath)));
245
263
  installations.push({
246
264
  agent,
@@ -251,6 +269,15 @@ export async function installAgentSkills(options = {}) {
251
269
  skillPaths,
252
270
  });
253
271
  }
272
+ if (scope === "project") {
273
+ const gitignoreEntries = installations.flatMap((installation) => installation.skillPaths.map((skillPath) => posixRelativePath(cwd, skillPath)));
274
+ if (await ensureRagmirGitignore(cwd, gitignoreEntries)) {
275
+ if (!projectKit.written.includes(".gitignore")) {
276
+ projectKit.written.push(".gitignore");
277
+ }
278
+ written.push(".gitignore");
279
+ }
280
+ }
254
281
  return {
255
282
  projectKit,
256
283
  installations,
@@ -282,10 +309,46 @@ function normalizeMcpServerName(value) {
282
309
  }
283
310
  return name;
284
311
  }
312
+ function suggestedMcpServerName(cwd) {
313
+ const identity = knowledgeBaseIdentity(cwd);
314
+ if (!identity || identity.id === ".") {
315
+ return DEFAULT_MCP_SERVER_NAME;
316
+ }
317
+ const suffix = sanitizeMcpServerSuffix(identity.id);
318
+ return suffix ? `${DEFAULT_MCP_SERVER_NAME}-${suffix}` : DEFAULT_MCP_SERVER_NAME;
319
+ }
320
+ function sanitizeMcpServerSuffix(value) {
321
+ let suffix = "";
322
+ let replacingInvalidRun = false;
323
+ for (const character of value.toLowerCase()) {
324
+ const code = character.charCodeAt(0);
325
+ const allowed = (code >= 97 && code <= 122) ||
326
+ (code >= 48 && code <= 57) ||
327
+ character === "_" ||
328
+ character === "-";
329
+ if (allowed) {
330
+ suffix += character;
331
+ replacingInvalidRun = false;
332
+ }
333
+ else if (!replacingInvalidRun) {
334
+ suffix += "-";
335
+ replacingInvalidRun = true;
336
+ }
337
+ }
338
+ let start = 0;
339
+ let end = suffix.length;
340
+ while (start < end && suffix[start] === "-") {
341
+ start += 1;
342
+ }
343
+ while (end > start && suffix[end - 1] === "-") {
344
+ end -= 1;
345
+ }
346
+ return suffix.slice(start, end);
347
+ }
285
348
  async function writeAgentMcpHelper(agent, input) {
286
349
  switch (agent) {
287
350
  case "claude":
288
- await writeFile(input.claudeConfigPath, `${JSON.stringify(claudeMcpServer(input.serveCommand), null, 2)}\n`, "utf8");
351
+ await writeFile(input.claudeConfigPath, `${JSON.stringify(claudeMcpServer(input.cwd, input.serveCommand), null, 2)}\n`, "utf8");
289
352
  return;
290
353
  case "codex":
291
354
  await writeFile(input.codexConfigPath, codexMcpConfig(input.cwd, input.serveCommand, input.mcpServerName), "utf8");
@@ -304,45 +367,96 @@ async function copyBundledSkills(targetDir) {
304
367
  force: true,
305
368
  })));
306
369
  }
307
- async function exposeAgentSkills(sourceDir, targetDir, requestedMode) {
370
+ async function exposeAgentSkills(sourceDir, targetDir, requestedMode, force) {
308
371
  if (requestedMode === "copy") {
309
- return copyAgentSkills(sourceDir, targetDir);
372
+ return copyAgentSkills(sourceDir, targetDir, force);
310
373
  }
311
374
  try {
312
- return await linkAgentSkills(sourceDir, targetDir);
375
+ return await linkAgentSkills(sourceDir, targetDir, force);
313
376
  }
314
377
  catch {
315
- return copyAgentSkills(sourceDir, targetDir);
378
+ return copyAgentSkills(sourceDir, targetDir, force);
316
379
  }
317
380
  }
318
- async function linkAgentSkills(sourceDir, targetDir) {
381
+ async function linkAgentSkills(sourceDir, targetDir, force) {
319
382
  const skillPaths = [];
320
383
  for (const skillName of SKILL_NAMES) {
321
384
  const source = path.join(sourceDir, skillName);
322
385
  const target = path.join(targetDir, skillName);
323
- await replaceWithDirectorySymlink(source, target);
386
+ await replaceWithDirectorySymlink(source, target, skillName, force);
324
387
  skillPaths.push(target);
325
388
  }
326
389
  return { mode: "link", skillPaths };
327
390
  }
328
- async function copyAgentSkills(sourceDir, targetDir) {
391
+ async function copyAgentSkills(sourceDir, targetDir, force) {
329
392
  const skillPaths = [];
330
393
  for (const skillName of SKILL_NAMES) {
331
394
  const source = path.join(sourceDir, skillName);
332
395
  const target = path.join(targetDir, skillName);
396
+ await assertManagedSkillTarget(source, target, skillName, force);
333
397
  await rm(target, { recursive: true, force: true });
334
398
  await cp(source, target, { recursive: true, force: true });
399
+ await writeFile(path.join(target, MANAGED_SKILL_METADATA_FILENAME), `${JSON.stringify({ managedBy: "ragmir", skillName }, null, 2)}\n`, "utf8");
335
400
  skillPaths.push(target);
336
401
  }
337
402
  return { mode: "copy", skillPaths };
338
403
  }
339
- async function replaceWithDirectorySymlink(source, target) {
404
+ async function replaceWithDirectorySymlink(source, target, skillName, force) {
340
405
  if (path.resolve(source) === path.resolve(target)) {
341
406
  return;
342
407
  }
408
+ await assertManagedSkillTarget(source, target, skillName, force);
343
409
  await rm(target, { recursive: true, force: true });
344
410
  await symlink(source, target, process.platform === "win32" ? "junction" : "dir");
345
411
  }
412
+ async function assertManagedSkillTarget(source, target, skillName, force) {
413
+ let targetStats;
414
+ try {
415
+ targetStats = await lstat(target);
416
+ }
417
+ catch (error) {
418
+ if (hasErrorCode(error, "ENOENT"))
419
+ return;
420
+ throw error;
421
+ }
422
+ if (force)
423
+ return;
424
+ if (targetStats.isSymbolicLink()) {
425
+ try {
426
+ if ((await realpath(target)) === (await realpath(source)))
427
+ return;
428
+ }
429
+ catch {
430
+ // A broken or unreadable link is not safe to replace implicitly.
431
+ }
432
+ }
433
+ else if (targetStats.isDirectory()) {
434
+ const metadata = await readManagedSkillMetadata(target);
435
+ if (metadata?.managedBy === "ragmir" && metadata.skillName === skillName)
436
+ return;
437
+ }
438
+ throw new Error(`Refusing to replace unmanaged agent skill at ${target}. Move it, or rerun with --force after reviewing its contents.`);
439
+ }
440
+ async function readManagedSkillMetadata(target) {
441
+ try {
442
+ const value = JSON.parse(await readFile(path.join(target, MANAGED_SKILL_METADATA_FILENAME), "utf8"));
443
+ if (typeof value === "object" &&
444
+ value !== null &&
445
+ "managedBy" in value &&
446
+ typeof value.managedBy === "string" &&
447
+ "skillName" in value &&
448
+ typeof value.skillName === "string") {
449
+ return { managedBy: value.managedBy, skillName: value.skillName };
450
+ }
451
+ }
452
+ catch {
453
+ return null;
454
+ }
455
+ return null;
456
+ }
457
+ function hasErrorCode(error, code) {
458
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
459
+ }
346
460
  function agentTargetDir(agent, scope, cwd, homeDir, env) {
347
461
  const destination = AGENT_DESTINATIONS[agent];
348
462
  const override = env[destination.env];
@@ -370,6 +484,185 @@ function displayPath(cwd, filePath) {
370
484
  }
371
485
  return filePath;
372
486
  }
487
+ function posixRelativePath(cwd, filePath) {
488
+ return path.relative(cwd, filePath).split(path.sep).join("/");
489
+ }
490
+ export function inspectAgentIntegration(cwd = process.cwd(), homeDir = process.env.HOME ?? process.cwd(), env = process.env) {
491
+ const projectRoot = path.resolve(cwd);
492
+ const resolvedHome = path.resolve(homeDir);
493
+ const runnerPath = path.join(projectRoot, RAGMIR_DIR, RGR_RUNNER_FILENAME);
494
+ const probe = probeRagmirRunner(projectRoot, runnerPath);
495
+ const projectAgents = detectedAgentTargets("project", projectRoot, resolvedHome, env);
496
+ const userAgents = detectedAgentTargets("user", projectRoot, resolvedHome, env);
497
+ const nativeAgents = [...new Set([...projectAgents, ...userAgents])];
498
+ const warnings = [];
499
+ if (!existsSync(runnerPath)) {
500
+ warnings.push("The generated Ragmir runner is missing. Run `rgr setup` or `rgr doctor --fix`.");
501
+ }
502
+ else if (!probe.runnerReady) {
503
+ warnings.push("The generated Ragmir runner could not verify a local CLI. Install @jcode.labs/ragmir in the project or rebuild the workspace package.");
504
+ }
505
+ if (probe.runnerRequiresDownload) {
506
+ warnings.push("The runner will fall back to the pinned npm package and may need a network download before first use.");
507
+ }
508
+ if (nativeAgents.length === 0) {
509
+ warnings.push("No native agent skill exposure was detected. Run `rgr install-agent --agents <list>`.");
510
+ }
511
+ return {
512
+ runnerPath,
513
+ runnerReady: probe.runnerReady,
514
+ runnerMode: probe.runnerMode,
515
+ runnerRequiresDownload: probe.runnerRequiresDownload,
516
+ projectAgents,
517
+ userAgents,
518
+ nativeAgents,
519
+ ready: probe.runnerReady && nativeAgents.length > 0,
520
+ warnings,
521
+ };
522
+ }
523
+ function detectedAgentTargets(scope, projectRoot, homeDir, env) {
524
+ return SUPPORTED_AGENT_TARGETS.filter((agent) => {
525
+ const targetDir = agentTargetDir(agent, scope, projectRoot, homeDir, env);
526
+ return SKILL_NAMES.every((skillName) => existsSync(path.join(targetDir, skillName, "SKILL.md")));
527
+ });
528
+ }
529
+ function probeRagmirRunner(projectRoot, runnerPath) {
530
+ if (!existsSync(runnerPath)) {
531
+ return { runnerReady: false, runnerMode: null, runnerRequiresDownload: false };
532
+ }
533
+ const result = spawnSync(process.execPath, [runnerPath, RGR_RUNNER_PROBE_ARG], {
534
+ cwd: projectRoot,
535
+ encoding: "utf8",
536
+ timeout: 5_000,
537
+ env: { ...process.env, [RAGMIR_PROJECT_ROOT_ENV]: projectRoot },
538
+ });
539
+ if (result.status !== 0) {
540
+ return { runnerReady: false, runnerMode: null, runnerRequiresDownload: false };
541
+ }
542
+ try {
543
+ const value = JSON.parse(result.stdout.trim());
544
+ if (typeof value === "object" &&
545
+ value !== null &&
546
+ "verified" in value &&
547
+ typeof value.verified === "boolean" &&
548
+ "mode" in value &&
549
+ isRagmirRunnerMode(value.mode) &&
550
+ "requiresDownload" in value &&
551
+ typeof value.requiresDownload === "boolean") {
552
+ return {
553
+ runnerReady: value.verified,
554
+ runnerMode: value.mode,
555
+ runnerRequiresDownload: value.requiresDownload,
556
+ };
557
+ }
558
+ }
559
+ catch {
560
+ return { runnerReady: false, runnerMode: null, runnerRequiresDownload: false };
561
+ }
562
+ return { runnerReady: false, runnerMode: null, runnerRequiresDownload: false };
563
+ }
564
+ function isRagmirRunnerMode(value) {
565
+ return (value === "local-bin" ||
566
+ value === "workspace" ||
567
+ value === "installed-package" ||
568
+ value === "npm-cache");
569
+ }
570
+ function ragmirRunnerSource(version, installedCliPath) {
571
+ const packageSpec = `@jcode.labs/ragmir@${version}`;
572
+ return `#!/usr/bin/env node
573
+ const { spawnSync } = require("node:child_process")
574
+ const { existsSync, readFileSync } = require("node:fs")
575
+ const path = require("node:path")
576
+
577
+ const PACKAGE_SPEC = ${JSON.stringify(packageSpec)}
578
+ const INSTALLED_CLI = ${JSON.stringify(installedCliPath)}
579
+ const PROBE_ARG = ${JSON.stringify(RGR_RUNNER_PROBE_ARG)}
580
+ const projectRoot = path.resolve(process.env.${RAGMIR_PROJECT_ROOT_ENV} || process.cwd())
581
+
582
+ function isRagmirWorkspaceCli(cliPath) {
583
+ if (!existsSync(cliPath)) return false
584
+ try {
585
+ const manifestPath = path.join(path.dirname(path.dirname(cliPath)), "package.json")
586
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"))
587
+ return manifest.name === "@jcode.labs/ragmir"
588
+ } catch {
589
+ return false
590
+ }
591
+ }
592
+
593
+ function resolveCommand() {
594
+ const localBin = path.join(
595
+ projectRoot,
596
+ "node_modules",
597
+ ".bin",
598
+ process.platform === "win32" ? "rgr.cmd" : "rgr",
599
+ )
600
+ if (existsSync(localBin)) {
601
+ return { mode: "local-bin", command: localBin, args: [], requiresDownload: false }
602
+ }
603
+
604
+ const workspaceCli = path.join(projectRoot, "packages", "ragmir-core", "dist", "cli.js")
605
+ if (isRagmirWorkspaceCli(workspaceCli)) {
606
+ return {
607
+ mode: "workspace",
608
+ command: process.execPath,
609
+ args: [workspaceCli],
610
+ requiresDownload: false,
611
+ }
612
+ }
613
+
614
+ if (isRagmirWorkspaceCli(INSTALLED_CLI)) {
615
+ return {
616
+ mode: "installed-package",
617
+ command: process.execPath,
618
+ args: [INSTALLED_CLI],
619
+ requiresDownload: false,
620
+ }
621
+ }
622
+
623
+ return {
624
+ mode: "npm-cache",
625
+ command: process.platform === "win32" ? "npx.cmd" : "npx",
626
+ args: ["--yes", "--package", PACKAGE_SPEC, "rgr"],
627
+ requiresDownload: true,
628
+ }
629
+ }
630
+
631
+ const selected = resolveCommand()
632
+ const commandArgs = process.argv.slice(2)
633
+
634
+ if (commandArgs[0] === PROBE_ARG) {
635
+ const probeArgs = selected.mode === "npm-cache" ? ["--version"] : [...selected.args, "--version"]
636
+ const probe = spawnSync(selected.command, probeArgs, {
637
+ cwd: projectRoot,
638
+ stdio: "ignore",
639
+ env: { ...process.env, ${RAGMIR_PROJECT_ROOT_ENV}: projectRoot },
640
+ })
641
+ const available = probe.status === 0
642
+ console.log(
643
+ JSON.stringify({
644
+ available,
645
+ verified: available && selected.mode !== "npm-cache",
646
+ mode: selected.mode,
647
+ requiresDownload: selected.requiresDownload,
648
+ }),
649
+ )
650
+ process.exitCode = available ? 0 : 1
651
+ } else {
652
+ const result = spawnSync(selected.command, [...selected.args, ...commandArgs], {
653
+ cwd: projectRoot,
654
+ stdio: "inherit",
655
+ env: { ...process.env, ${RAGMIR_PROJECT_ROOT_ENV}: projectRoot },
656
+ })
657
+ if (result.error) {
658
+ console.error(result.error.message)
659
+ process.exitCode = 1
660
+ } else {
661
+ process.exitCode = result.status ?? 1
662
+ }
663
+ }
664
+ `;
665
+ }
373
666
  function mcpConfig(cwd, serveCommand, env, serverName = DEFAULT_MCP_SERVER_NAME) {
374
667
  const serverConfig = {
375
668
  command: serveCommand.command,
@@ -386,11 +679,12 @@ function mcpConfig(cwd, serveCommand, env, serverName = DEFAULT_MCP_SERVER_NAME)
386
679
  }
387
680
  return config;
388
681
  }
389
- function claudeMcpServer(serveCommand) {
682
+ function claudeMcpServer(cwd, serveCommand) {
390
683
  return {
391
684
  type: "stdio",
392
685
  command: serveCommand.command,
393
686
  args: serveCommand.args,
687
+ env: { [RAGMIR_PROJECT_ROOT_ENV]: cwd },
394
688
  };
395
689
  }
396
690
  function codexMcpConfig(cwd, serveCommand, serverName = DEFAULT_MCP_SERVER_NAME) {
@@ -461,6 +755,10 @@ ${input.serveCommand}
461
755
 
462
756
  Use \`ragmir_route_prompt\` when an agent hook or skill needs to decide whether the current user
463
757
  prompt should call Ragmir before answering. The router is local and does not store prompt text.`,
758
+ `This helper is pinned to one knowledge-base root. In a monorepo, keep the generated server name
759
+ \`${input.mcpServerName}\` and generate a separate helper from each nested base. Call
760
+ \`ragmir_status\` and verify \`knowledgeBaseId\` before retrieval when the active base is unclear.`,
761
+ "Read `ragmir://context` for bounded base identity, readiness, freshness, and capabilities. Read `ragmir://sources` only when source coverage or index drift matters.",
464
762
  ];
465
763
  if (hasAgentHelper(input, "claude")) {
466
764
  sections.push(`Claude Code local MCP setup:
@@ -616,7 +914,7 @@ Default project-scope targets:
616
914
  | Agent | Project skill directory | User skill directory |
617
915
  | --- | --- | --- |
618
916
  | Claude Code | \`.claude/skills/\` | \`~/.claude/skills/\` |
619
- | Codex | \`.codex/skills/\` | \`~/.codex/skills/\` |
917
+ | Codex | \`.agents/skills/\` | \`~/.agents/skills/\` |
620
918
  | Kimi Code CLI | \`.kimi/skills/\` | \`~/.kimi/skills/\` |
621
919
  | OpenCode | \`.opencode/skills/\` | \`~/.config/opencode/skills/\` |
622
920
  | Cline | \`.cline/skills/\` | \`~/.cline/skills/\` |
@@ -625,7 +923,8 @@ Override paths with \`CLAUDE_SKILLS_DIR\`, \`CODEX_SKILLS_DIR\`, \`KIMI_SKILLS_D
625
923
  \`OPENCODE_SKILLS_DIR\`, or \`CLINE_SKILLS_DIR\`.
626
924
 
627
925
  Use \`--mode copy\` only when an agent runtime does not follow symlinked skill directories. When using
628
- copy mode, rerun \`install-agent\` after refreshing \`.ragmir/skills/\`.
926
+ copy mode, rerun \`install-agent\` after refreshing \`.ragmir/skills/\`. Ragmir refuses to replace
927
+ an unmanaged same-name skill by default; use \`--force\` only after reviewing that existing folder.
629
928
 
630
929
  ## Skill Folders
631
930