ccdesk 0.2.2 → 0.2.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.
Files changed (131) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +7 -4
  3. package/dist/core/agent-edit.d.ts +6 -0
  4. package/dist/{server → core}/agent-edit.js +15 -21
  5. package/dist/core/backups.d.ts +19 -0
  6. package/dist/{server → core}/backups.js +64 -48
  7. package/dist/core/core.d.ts +96 -0
  8. package/dist/core/core.js +57 -0
  9. package/dist/core/index.d.ts +22 -0
  10. package/dist/core/index.js +38 -0
  11. package/dist/core/mcp-edit.d.ts +23 -0
  12. package/dist/{server → core}/mcp-edit.js +121 -100
  13. package/dist/core/mutations.d.ts +20 -0
  14. package/dist/{server → core}/mutations.js +8 -15
  15. package/dist/core/open.d.ts +28 -0
  16. package/dist/{server → core}/open.js +38 -13
  17. package/dist/core/parse-edit.d.ts +12 -0
  18. package/dist/core/parse-edit.js +64 -0
  19. package/dist/core/reference.d.ts +3 -0
  20. package/dist/core/reference.js +11 -0
  21. package/dist/core/scan/compare.d.ts +7 -0
  22. package/dist/{server → core}/scan/compare.js +2 -2
  23. package/dist/core/scan/context.d.ts +13 -0
  24. package/dist/{server → core}/scan/context.js +55 -32
  25. package/dist/core/scan/data.d.ts +14 -0
  26. package/dist/core/scan/data.js +26 -0
  27. package/dist/core/scan/env.d.ts +28 -0
  28. package/dist/{server → core}/scan/env.js +15 -4
  29. package/dist/core/scan/files.d.ts +68 -0
  30. package/dist/core/scan/files.js +270 -0
  31. package/dist/core/scan/git.d.ts +20 -0
  32. package/dist/core/scan/git.js +106 -0
  33. package/dist/core/scan/index.d.ts +5 -0
  34. package/dist/{server → core}/scan/index.js +119 -82
  35. package/dist/core/scan/instructions.d.ts +54 -0
  36. package/dist/{server → core}/scan/instructions.js +141 -73
  37. package/dist/core/scan/inventory.d.ts +38 -0
  38. package/dist/{server → core}/scan/inventory.js +134 -115
  39. package/dist/core/scan/mcp.d.ts +28 -0
  40. package/dist/{server → core}/scan/mcp.js +153 -95
  41. package/dist/core/scan/memory.d.ts +8 -0
  42. package/dist/{server → core}/scan/memory.js +8 -8
  43. package/dist/core/scan/path-test.d.ts +9 -0
  44. package/dist/core/scan/path-test.js +156 -0
  45. package/dist/core/scan/permissions.d.ts +31 -0
  46. package/dist/{server → core}/scan/permissions.js +5 -8
  47. package/dist/core/scan/plugins.d.ts +39 -0
  48. package/dist/{server → core}/scan/plugins.js +36 -27
  49. package/dist/core/scan/projects.d.ts +9 -0
  50. package/dist/{server → core}/scan/projects.js +7 -5
  51. package/dist/core/scan/sandbox.d.ts +14 -0
  52. package/dist/{server → core}/scan/sandbox.js +87 -59
  53. package/dist/core/scan/settings.d.ts +37 -0
  54. package/dist/{server → core}/scan/settings.js +98 -93
  55. package/dist/core/scan/tools.d.ts +10 -0
  56. package/dist/{server → core}/scan/tools.js +28 -20
  57. package/dist/core/scan/usage.d.ts +19 -0
  58. package/dist/{server → core}/scan/usage.js +122 -97
  59. package/dist/core/schema.d.ts +8 -0
  60. package/dist/core/schema.js +67 -0
  61. package/dist/core/secrets.d.ts +45 -0
  62. package/dist/core/secrets.js +207 -0
  63. package/dist/core/settings-edit.d.ts +9 -0
  64. package/dist/{server → core}/settings-edit.js +91 -112
  65. package/dist/core/watch.d.ts +45 -0
  66. package/dist/{server → core}/watch.js +54 -17
  67. package/dist/core/write.d.ts +117 -0
  68. package/dist/{server → core}/write.js +61 -8
  69. package/dist/server/args.d.ts +32 -0
  70. package/dist/server/args.js +106 -0
  71. package/dist/server/cli.d.ts +2 -0
  72. package/dist/server/cli.js +58 -83
  73. package/dist/server/commands.d.ts +8 -0
  74. package/dist/server/commands.js +39 -0
  75. package/dist/server/server.d.ts +12 -0
  76. package/dist/server/server.js +80 -195
  77. package/dist/server/start.d.ts +13 -0
  78. package/dist/server/start.js +21 -0
  79. package/dist/shared/compare.d.ts +25 -0
  80. package/dist/shared/memory.d.ts +6 -0
  81. package/dist/shared/memory.js +18 -2
  82. package/dist/shared/requests.d.ts +104 -0
  83. package/dist/shared/requests.js +73 -0
  84. package/dist/shared/scopes.d.ts +10 -0
  85. package/dist/shared/settings-catalog.json +2199 -0
  86. package/dist/shared/types.d.ts +535 -0
  87. package/dist/shared/types.js +11 -0
  88. package/dist/ui/assets/index-C9qqEI5Z.js +60 -0
  89. package/dist/ui/index.html +1 -1
  90. package/dist/view/diff.d.ts +16 -0
  91. package/dist/view/diff.js +85 -0
  92. package/dist/view/format.d.ts +17 -0
  93. package/dist/view/format.js +47 -0
  94. package/dist/view/index.d.ts +11 -0
  95. package/dist/view/index.js +13 -0
  96. package/dist/view/lines.d.ts +9 -0
  97. package/dist/view/lines.js +12 -0
  98. package/dist/view/path-test.d.ts +3 -0
  99. package/dist/view/path-test.js +7 -0
  100. package/dist/view/sections/catalog.d.ts +9 -0
  101. package/dist/view/sections/catalog.js +47 -0
  102. package/dist/view/sections/extensions.d.ts +1 -0
  103. package/dist/view/sections/extensions.js +48 -0
  104. package/dist/view/sections/hooks.d.ts +1 -0
  105. package/dist/view/sections/hooks.js +32 -0
  106. package/dist/view/sections/index.d.ts +6 -0
  107. package/dist/view/sections/index.js +27 -0
  108. package/dist/view/sections/instructions.d.ts +6 -0
  109. package/dist/view/sections/instructions.js +38 -0
  110. package/dist/view/sections/mcp.d.ts +3 -0
  111. package/dist/view/sections/mcp.js +38 -0
  112. package/dist/view/sections/memory.d.ts +1 -0
  113. package/dist/view/sections/memory.js +31 -0
  114. package/dist/view/sections/permissions.d.ts +17 -0
  115. package/dist/view/sections/permissions.js +87 -0
  116. package/dist/view/sections/settings.d.ts +1 -0
  117. package/dist/view/sections/settings.js +33 -0
  118. package/dist/view/sections/tools.d.ts +6 -0
  119. package/dist/view/sections/tools.js +57 -0
  120. package/dist/view/sections/types.d.ts +123 -0
  121. package/dist/view/sections/types.js +10 -0
  122. package/dist/view/settings.d.ts +12 -0
  123. package/dist/view/settings.js +31 -0
  124. package/dist/view/usage.d.ts +8 -0
  125. package/dist/view/usage.js +18 -0
  126. package/package.json +13 -2
  127. package/dist/server/scan/files.js +0 -480
  128. package/dist/server/scan/path-test.js +0 -136
  129. package/dist/server/schema.js +0 -15
  130. package/dist/server/secrets.js +0 -63
  131. package/dist/ui/assets/index-Dg9dxngR.js +0 -60
@@ -1,9 +1,8 @@
1
- import { constants } from "node:fs";
2
- import { access, stat } from "node:fs/promises";
3
1
  import { dirname, isAbsolute, join, matchesGlob, parse, resolve } from "node:path";
4
2
  import {} from "../../shared/types.js";
5
3
  import {} from "./env.js";
6
- import { isFile, isNetworkPath, isWithin, MAX_TEXT_BYTES, parseFrontmatter, readTextFile, resolvedPath, toStringList, walkMarkdown, } from "./files.js";
4
+ import { isFile, isNetworkPath, isWithin, MAX_TEXT_BYTES, readTextFile, resolvedPath, toStringList, walkMarkdown, } from "./files.js";
5
+ import { parseFrontmatter } from "./data.js";
7
6
  const MAX_IMPORT_HOPS = 4;
8
7
  export const AGENTS_MD_MODES = [
9
8
  "claude-md-or-agents-md",
@@ -11,6 +10,45 @@ export const AGENTS_MD_MODES = [
11
10
  "claude-md",
12
11
  "managed-only",
13
12
  ];
13
+ /** The CLAUDE.md and AGENTS.md files each folder can hold, in the order Claude Code reads them. */
14
+ export const CLAUDE_MD_NAMES = ["CLAUDE.md", ".claude/CLAUDE.md"];
15
+ export const AGENTS_MD_NAMES = ["AGENTS.md", ".claude/AGENTS.md"];
16
+ /**
17
+ * Whether AGENTS.md loads, given the instruction mode and whether a CLAUDE.md or CLAUDE.local.md
18
+ * is there (docs: memory#choose-which-instruction-files-load).
19
+ */
20
+ export function agentsMdLoads(mode, hasClaudeMd) {
21
+ return mode === "claude-md-and-agents-md" || (mode === "claude-md-or-agents-md" && !hasClaudeMd);
22
+ }
23
+ /**
24
+ * Whether a claudeMdExcludes glob matches a file by its own path or, for a link, its target's
25
+ * (docs: memory#exclude-specific-claude-md-files).
26
+ */
27
+ export function isExcluded(excludes, path, realPath) {
28
+ return excludes.some((glob) => [path, realPath].some((p) => p !== undefined && safeMatch(p, glob)));
29
+ }
30
+ /**
31
+ * Where a rule in `dir` really is when that is outside both the project and `dir`: a link's
32
+ * target, or the file a linked folder leads to. Undefined for a rule that stays inside.
33
+ */
34
+ export async function ruleTarget(file, dir, realCwd) {
35
+ if (file.realPath)
36
+ return file.realPath;
37
+ const real = await resolvedPath(file.path);
38
+ return isWithin(realCwd, real) || isWithin(await resolvedPath(dir), real) ? undefined : real;
39
+ }
40
+ /**
41
+ * Why a project rule linked from outside the project does not load, or null when it does: it waits
42
+ * for your approval of outside imports, and once approved loads only without a paths field
43
+ * (docs: memory#share-rules-across-projects-with-symlinks).
44
+ */
45
+ export function linkedRuleBlock(target, realCwd, approved, hasPaths) {
46
+ if (target === undefined || isWithin(realCwd, target))
47
+ return null;
48
+ if (!approved)
49
+ return "needs-approval";
50
+ return hasPaths ? "has-paths" : null;
51
+ }
14
52
  /** Directories from the filesystem root down to `cwd`, the order Claude Code concatenates them in. */
15
53
  export function ancestorsRootFirst(cwd) {
16
54
  const dirs = [];
@@ -31,25 +69,31 @@ export function ancestorsRootFirst(cwd) {
31
69
  */
32
70
  export async function resolveInstructions(options) {
33
71
  const { env, cwd, mode, excludes, externalImports, managedClaudeMd, problems } = options;
34
- /** A file that exists but cannot be read is reported, not taken for a missing one. */
35
- const readInstruction = async (path) => {
36
- const file = await readTextFile(env, path);
37
- if (file || !(await stat(path).catch(() => null))?.isFile())
38
- return file;
39
- const denied = await access(path, constants.R_OK).then(() => null, (error) => error.code ?? String(error));
40
- if (denied)
41
- problems.push({ path, error: `cannot be read (${denied})` });
42
- return null;
43
- };
44
72
  const ctx = {
45
73
  realCwd: await resolvedPath(resolve(cwd)),
46
74
  env,
47
75
  approved: externalImports === "approved",
76
+ problems,
48
77
  };
49
- const managedOnly = mode === "managed-only";
50
- const skippedByMode = `Skipped: instruction mode is ${mode}`;
78
+ const out = await readOwnFiles(ctx, managedClaudeMd);
79
+ const { claudeFiles, agentsFiles } = await readDirectoryFiles(ctx, cwd);
80
+ explainClaudeFiles(claudeFiles, cwd);
81
+ explainAgentsFiles(agentsFiles, claudeFiles, mode);
82
+ for (const dir of ancestorsRootFirst(cwd))
83
+ out.push(...claudeFiles.filter((f) => f.dir === dir), ...agentsFiles.filter((f) => f.dir === dir));
84
+ applyLoadRules(out, ctx, mode, excludes, externalImports);
85
+ addChecks(out);
86
+ return out;
87
+ }
88
+ /** A file that exists but cannot be read is reported, not taken for a missing one. */
89
+ function readInstruction(ctx, path) {
90
+ return readTextFile(ctx.env, path, ctx.problems);
91
+ }
92
+ /** The managed and user files, which come first and do not depend on the folder. */
93
+ async function readOwnFiles(ctx, managedClaudeMd) {
94
+ const { env } = ctx;
51
95
  const out = [];
52
- const managed = await readInstruction(join(env.managedDir, "CLAUDE.md"));
96
+ const managed = await readInstruction(ctx, join(env.managedDir, "CLAUDE.md"));
53
97
  if (managed)
54
98
  out.push(await instruction(managed, "claude-md", "managed", env.managedDir, ctx, "Organisation policy, always loaded"));
55
99
  if (managedClaudeMd) {
@@ -65,69 +109,94 @@ export async function resolveInstructions(options) {
65
109
  entry.imports = [];
66
110
  out.push(entry);
67
111
  }
68
- const user = await readInstruction(join(env.claudeDir, "CLAUDE.md"));
112
+ const user = await readInstruction(ctx, join(env.claudeDir, "CLAUDE.md"));
69
113
  if (user)
70
114
  out.push(await instruction(user, "claude-md", "user", env.claudeDir, ctx, "Your instructions for every project"));
71
115
  for (const path of await walkMarkdown(join(env.claudeDir, "rules"))) {
72
- const file = await readInstruction(path);
116
+ const file = await readInstruction(ctx, path);
73
117
  if (file)
74
118
  out.push(await rule(file, "user", env.claudeDir, ctx));
75
119
  }
76
- // Per directory, root first: CLAUDE.md, .claude/CLAUDE.md, rules, then CLAUDE.local.md last
77
- // ("your personal notes are the last thing Claude reads at that level"), then AGENTS.md.
120
+ return out;
121
+ }
122
+ /**
123
+ * The project and local files of `cwd` and every folder above it. Per directory, root first:
124
+ * CLAUDE.md, .claude/CLAUDE.md, rules, then CLAUDE.local.md last ("your personal notes are the last
125
+ * thing Claude reads at that level"), then AGENTS.md.
126
+ */
127
+ async function readDirectoryFiles(ctx, cwd) {
78
128
  const claudeFiles = [];
79
129
  const agentsFiles = [];
80
130
  for (const dir of ancestorsRootFirst(cwd)) {
81
- // ~/.claude/CLAUDE.md and ~/.claude/rules are the user files above, not the home's project files.
82
- const isConfigHome = join(dir, ".claude") === env.claudeDir;
83
- for (const name of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
84
- if (isConfigHome && name === ".claude/CLAUDE.md")
85
- continue;
86
- const file = await readInstruction(join(dir, name));
87
- if (file)
88
- claudeFiles.push(await instruction(file, "claude-md", "project", dir, ctx, ""));
89
- }
90
- if (!isConfigHome && dir !== env.claudeDir)
91
- for (const path of await walkMarkdown(join(dir, ".claude", "rules"))) {
92
- const file = await readInstruction(path);
93
- if (file)
94
- claudeFiles.push(await rule(file, "project", dir, ctx));
95
- }
96
- const local = await readInstruction(join(dir, "CLAUDE.local.md"));
97
- if (local)
98
- claudeFiles.push(await instruction(local, "claude-local-md", "local", dir, ctx, ""));
99
- for (const name of ["AGENTS.md", ".claude/AGENTS.md"]) {
100
- const file = await readInstruction(join(dir, name));
131
+ claudeFiles.push(...(await readClaudeFiles(ctx, dir)));
132
+ for (const name of AGENTS_MD_NAMES) {
133
+ const file = await readInstruction(ctx, join(dir, name));
101
134
  if (file)
102
135
  agentsFiles.push(await instruction(file, "agents-md", "project", dir, ctx, ""));
103
136
  }
104
137
  }
105
- const hasClaudeMd = claudeFiles.some((f) => f.kind !== "rule");
138
+ return { claudeFiles, agentsFiles };
139
+ }
140
+ /** One folder's CLAUDE.md files, rules and CLAUDE.local.md, in the order Claude Code reads them. */
141
+ async function readClaudeFiles(ctx, dir) {
142
+ const { env } = ctx;
143
+ const out = [];
144
+ // ~/.claude/CLAUDE.md and ~/.claude/rules are the user files above, not the home's project files.
145
+ const holdsClaudeDir = join(dir, ".claude") === env.claudeDir;
146
+ for (const name of CLAUDE_MD_NAMES) {
147
+ if (holdsClaudeDir && name === ".claude/CLAUDE.md")
148
+ continue;
149
+ const file = await readInstruction(ctx, join(dir, name));
150
+ if (file)
151
+ out.push(await instruction(file, "claude-md", "project", dir, ctx, ""));
152
+ }
153
+ if (!holdsClaudeDir && dir !== env.claudeDir)
154
+ for (const path of await walkMarkdown(join(dir, ".claude", "rules"))) {
155
+ const file = await readInstruction(ctx, path);
156
+ if (file)
157
+ out.push(await rule(file, "project", dir, ctx));
158
+ }
159
+ const local = await readInstruction(ctx, join(dir, "CLAUDE.local.md"));
160
+ if (local)
161
+ out.push(await instruction(local, "claude-local-md", "local", dir, ctx, ""));
162
+ return out;
163
+ }
164
+ /** Why each CLAUDE.md and CLAUDE.local.md loads; rules have their reason already. */
165
+ function explainClaudeFiles(claudeFiles, cwd) {
106
166
  for (const file of claudeFiles) {
107
167
  if (file.kind === "rule")
108
168
  continue;
109
- file.reason =
110
- file.kind === "claude-local-md"
111
- ? "Your private notes for this directory"
112
- : file.dir === resolve(cwd)
113
- ? "Instructions for this directory"
114
- : "Inherited from a parent directory";
169
+ if (file.kind === "claude-local-md")
170
+ file.reason = "Your private notes for this directory";
171
+ else if (file.dir === resolve(cwd))
172
+ file.reason = "Instructions for this directory";
173
+ else
174
+ file.reason = "Inherited from a parent directory";
115
175
  }
176
+ }
177
+ /** Whether each AGENTS.md loads next to the CLAUDE.md files found, and why. */
178
+ function explainAgentsFiles(agentsFiles, claudeFiles, mode) {
179
+ const hasClaudeMd = claudeFiles.some((f) => f.kind !== "rule");
116
180
  const includedElsewhere = new Set(claudeFiles.flatMap((f) => [f.realPath ?? f.path, ...f.imports.map((i) => i.resolved)]));
117
181
  for (const file of agentsFiles) {
118
- if (mode === "managed-only" || mode === "claude-md")
119
- skip(file, skippedByMode);
182
+ if (!agentsMdLoads(mode, false))
183
+ skip(file, skippedByMode(mode));
120
184
  else if (includedElsewhere.has(file.realPath ?? file.path))
121
185
  skip(file, "Already included through a CLAUDE.md import or symlink");
186
+ else if (!agentsMdLoads(mode, hasClaudeMd))
187
+ skip(file, "Ignored: a CLAUDE.md or CLAUDE.local.md exists here or above, so Claude Code reads that instead");
122
188
  else if (mode === "claude-md-and-agents-md")
123
189
  file.reason = "Loaded alongside CLAUDE.md (instruction mode claude-md-and-agents-md)";
124
- else if (hasClaudeMd)
125
- skip(file, "Ignored: a CLAUDE.md or CLAUDE.local.md exists here or above, so Claude Code reads that instead");
126
190
  else
127
191
  file.reason = "Loaded because there is no CLAUDE.md here or above";
128
192
  }
129
- for (const dir of ancestorsRootFirst(cwd))
130
- out.push(...claudeFiles.filter((f) => f.dir === dir), ...agentsFiles.filter((f) => f.dir === dir));
193
+ }
194
+ /**
195
+ * Skips what Claude Code leaves out of every file but managed ones: all of them in managed-only
196
+ * mode, ones matched by claudeMdExcludes, ones over 4 MiB, and project rules linked from outside
197
+ * the project that do not qualify.
198
+ */
199
+ function applyLoadRules(out, ctx, mode, excludes, externalImports) {
131
200
  const waiting = externalImports === "declined"
132
201
  ? "You declined imports from outside this project"
133
202
  : "Waits for you to approve imports from outside this project";
@@ -135,28 +204,27 @@ export async function resolveInstructions(options) {
135
204
  if (file.scope === "managed")
136
205
  continue;
137
206
  // Path-scoped rules still load on demand in managed-only mode (docs: memory#choose-which-instruction-files-load).
138
- if (managedOnly && file.status === "loaded")
139
- skip(file, skippedByMode);
140
- // Managed files cannot be excluded; a linked file is excluded by its own path or its target's
141
- // (docs: memory#exclude-specific-claude-md-files).
142
- const excluded = excludes.some((glob) => [file.path, file.realPath].some((p) => p !== undefined && safeMatch(p, glob)));
143
- if (excluded)
207
+ if (mode === "managed-only" && file.status === "loaded")
208
+ skip(file, skippedByMode(mode));
209
+ // Managed files cannot be excluded.
210
+ if (isExcluded(excludes, file.path, file.realPath))
144
211
  skip(file, "Skipped by claudeMdExcludes");
145
212
  if (file.status !== "skipped" && file.bytes > MAX_TEXT_BYTES)
146
213
  skip(file, "Skipped: Claude Code does not load an instruction file over 4 MiB");
147
214
  // A project's links outside it need your approval, like its imports; your own files do not.
148
215
  if (file.scope !== "project" && file.scope !== "local")
149
216
  continue;
150
- if (file.kind === "rule" && file.realPath && !isWithin(ctx.realCwd, file.realPath)) {
151
- if (!ctx.approved)
152
- skip(file, `${waiting}; this rule links outside it`);
153
- // docs: memory#share-rules-across-projects-with-symlinks
154
- else if (file.paths)
155
- skip(file, "Links outside this project, and such a rule loads only without a paths field");
156
- }
217
+ if (file.kind !== "rule")
218
+ continue;
219
+ const block = linkedRuleBlock(file.realPath, ctx.realCwd, ctx.approved, file.paths !== undefined);
220
+ if (block === "needs-approval")
221
+ skip(file, `${waiting}; this rule links outside it`);
222
+ else if (block === "has-paths")
223
+ skip(file, "Links outside this project, and such a rule loads only without a paths field");
157
224
  }
158
- addChecks(out);
159
- return out;
225
+ }
226
+ function skippedByMode(mode) {
227
+ return `Skipped: instruction mode is ${mode}`;
160
228
  }
161
229
  function skip(file, reason) {
162
230
  if (file.status === "skipped")
@@ -165,7 +233,7 @@ function skip(file, reason) {
165
233
  file.reason = reason;
166
234
  }
167
235
  /** An invalid pattern matches nothing. */
168
- function safeMatch(path, glob) {
236
+ export function safeMatch(path, glob) {
169
237
  try {
170
238
  return matchesGlob(path, glob);
171
239
  }
@@ -213,9 +281,9 @@ async function rule(file, scope, dir, ctx) {
213
281
  entry.status = "on-match";
214
282
  }
215
283
  // A rule reached through a linked folder is not a link itself, but its target can be outside.
216
- const real = await resolvedPath(file.path);
217
- if (!entry.realPath && !isWithin(ctx.realCwd, real) && !isWithin(await resolvedPath(dir), real))
218
- entry.realPath = real;
284
+ const target = await ruleTarget(file, dir, ctx.realCwd);
285
+ if (target)
286
+ entry.realPath = target;
219
287
  return entry;
220
288
  }
221
289
  async function instruction(file, kind, scope, dir, ctx, reason) {
@@ -248,7 +316,7 @@ async function collectImports(file, ctx, readExternal) {
248
316
  continue;
249
317
  seen.add(real);
250
318
  const external = !isWithin(ctx.realCwd, real);
251
- const imported = !external || readExternal ? await readTextFile(ctx.env, target) : null;
319
+ const imported = !external || readExternal ? await readTextFile(ctx.env, target, ctx.problems) : null;
252
320
  const ref = {
253
321
  raw,
254
322
  resolved: real,
@@ -0,0 +1,38 @@
1
+ import { type EffectiveSetting, type Entry, type Inventory, type Problem, type Scope, type SessionProfile, type SettingsLayer, type Trust } from "../../shared/types.ts";
2
+ import { type ScanEnv } from "./env.ts";
3
+ type Source = Scope | "plugin";
4
+ interface ReadOptions {
5
+ plugin?: string | undefined;
6
+ /** Joins the folders of a file in a subfolder into its name; commands use ":". */
7
+ separator?: string;
8
+ /** Receives files that are there but cannot be read. */
9
+ problems?: Problem[] | undefined;
10
+ }
11
+ export declare function readSkill(env: ScanEnv, folder: string, scope: Source, { plugin, problems }?: ReadOptions): Promise<Entry | null>;
12
+ interface InventoryInput {
13
+ env: ScanEnv;
14
+ projectDir: string;
15
+ /** The repository (or worktree) root, where the search for project skills stops. */
16
+ gitRoot: string | null;
17
+ layers: SettingsLayer[];
18
+ effective: EffectiveSetting[];
19
+ /** Managed settings as written, nothing hidden: for checks that must see header values. */
20
+ managed: Record<string, unknown> | null;
21
+ claudeJson: Record<string, unknown> | null;
22
+ trust: Trust;
23
+ profile: SessionProfile;
24
+ /** Receives files that are there but cannot be read or parsed. */
25
+ problems: Problem[];
26
+ }
27
+ /**
28
+ * What Claude Code requires of a subagent file; it skips one that falls short, and treats one
29
+ * without a name as documentation (docs: sub-agents#subagent-files-claude-code-skips).
30
+ */
31
+ export declare function agentProblems(text: string): string[];
32
+ /**
33
+ * Applies skillOverrides to your skills and command files; plugin skills are not affected
34
+ * (docs: skills#override-skill-visibility-from-settings).
35
+ */
36
+ export declare function applySkillOverrides(entries: Entry[], overrides: unknown): void;
37
+ export declare function readInventory(input: InventoryInput): Promise<Inventory>;
38
+ export {};