@skaile/workspaces 0.44.0 → 0.46.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 (142) hide show
  1. package/CHANGELOG.md +141 -0
  2. package/dist/{asset-feeds-EGSG4FUB.js → asset-feeds-DLRQWELS.js} +7 -7
  3. package/dist/{asset-feeds-EGSG4FUB.js.map → asset-feeds-DLRQWELS.js.map} +1 -1
  4. package/dist/asset-manager/index.js +7 -7
  5. package/dist/asset-manager/installer.js +6 -6
  6. package/dist/asset-manager/renderers.js +2 -2
  7. package/dist/asset-manager/src/index.d.ts +47 -0
  8. package/dist/asset-manager/src/index.d.ts.map +1 -1
  9. package/dist/{chunk-VPXV2Z5E.js → chunk-3VBQJZYL.js} +6 -6
  10. package/dist/chunk-3VBQJZYL.js.map +1 -0
  11. package/dist/{chunk-LMRO2QNF.js → chunk-3VT2I7IA.js} +72 -5
  12. package/dist/chunk-3VT2I7IA.js.map +1 -0
  13. package/dist/{chunk-CVWA4RIK.js → chunk-4VPRAG35.js} +5 -5
  14. package/dist/{chunk-CVWA4RIK.js.map → chunk-4VPRAG35.js.map} +1 -1
  15. package/dist/{chunk-JUZLVRI4.js → chunk-CNP2FHRM.js} +84 -19
  16. package/dist/chunk-CNP2FHRM.js.map +1 -0
  17. package/dist/{chunk-RGPBEGP2.js → chunk-CU5Z7GH3.js} +6 -2
  18. package/dist/chunk-CU5Z7GH3.js.map +1 -0
  19. package/dist/{chunk-CBZEIFU4.js → chunk-DDR4OSSM.js} +3 -3
  20. package/dist/{chunk-CBZEIFU4.js.map → chunk-DDR4OSSM.js.map} +1 -1
  21. package/dist/{chunk-PCXU2CVW.js → chunk-FAALG3QN.js} +4 -4
  22. package/dist/{chunk-PCXU2CVW.js.map → chunk-FAALG3QN.js.map} +1 -1
  23. package/dist/{chunk-5LHPKVGR.js → chunk-FX4BDEUN.js} +126 -9
  24. package/dist/chunk-FX4BDEUN.js.map +1 -0
  25. package/dist/{chunk-BLGHFVXE.js → chunk-G3GODNHM.js} +66 -4
  26. package/dist/chunk-G3GODNHM.js.map +1 -0
  27. package/dist/{chunk-ETDXTGDF.js → chunk-HOEP5CJQ.js} +3 -3
  28. package/dist/{chunk-ETDXTGDF.js.map → chunk-HOEP5CJQ.js.map} +1 -1
  29. package/dist/{chunk-5FVJXQDP.js → chunk-JXHULIOA.js} +3 -3
  30. package/dist/{chunk-5FVJXQDP.js.map → chunk-JXHULIOA.js.map} +1 -1
  31. package/dist/{chunk-ZAEJ33Y6.js → chunk-LLOXWWB6.js} +5 -5
  32. package/dist/{chunk-ZAEJ33Y6.js.map → chunk-LLOXWWB6.js.map} +1 -1
  33. package/dist/{chunk-GM3BV6JK.js → chunk-P6HRQPXC.js} +2 -2
  34. package/dist/{chunk-GM3BV6JK.js.map → chunk-P6HRQPXC.js.map} +1 -1
  35. package/dist/{chunk-NHLXS2CH.js → chunk-PPSRBFYE.js} +2 -2
  36. package/dist/{chunk-NHLXS2CH.js.map → chunk-PPSRBFYE.js.map} +1 -1
  37. package/dist/{chunk-7NQXVBCQ.js → chunk-TKTXIAG5.js} +5 -5
  38. package/dist/{chunk-7NQXVBCQ.js.map → chunk-TKTXIAG5.js.map} +1 -1
  39. package/dist/{chunk-XUXVH3JK.js → chunk-WRBF34YE.js} +3 -3
  40. package/dist/{chunk-XUXVH3JK.js.map → chunk-WRBF34YE.js.map} +1 -1
  41. package/dist/{chunk-COSTF7QW.js → chunk-WTFJFW7F.js} +50 -12
  42. package/dist/chunk-WTFJFW7F.js.map +1 -0
  43. package/dist/{chunk-XF2BBX6P.js → chunk-Z3ZRI2AE.js} +3 -3
  44. package/dist/{chunk-XF2BBX6P.js.map → chunk-Z3ZRI2AE.js.map} +1 -1
  45. package/dist/cli/index.js +1039 -704
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/cli/src/commands/asset-cmd.d.ts +1 -1
  48. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  49. package/dist/cli/src/commands/catalog.d.ts +11 -4
  50. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  51. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  52. package/dist/cli/src/commands/npx.d.ts.map +1 -1
  53. package/dist/cli/src/commands/project.d.ts.map +1 -1
  54. package/dist/cli/src/commands/skailify-lib.d.ts +108 -0
  55. package/dist/cli/src/commands/skailify-lib.d.ts.map +1 -0
  56. package/dist/cli/src/commands/source.d.ts +17 -4
  57. package/dist/cli/src/commands/source.d.ts.map +1 -1
  58. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  59. package/dist/cli/src/ensure-sources.d.ts.map +1 -1
  60. package/dist/connectors/config.js +4 -4
  61. package/dist/connectors/index.js +5 -5
  62. package/dist/core/index.js +3 -3
  63. package/dist/core/runtime-assets.js +2 -2
  64. package/dist/core/src/conformance.d.ts +33 -0
  65. package/dist/core/src/conformance.d.ts.map +1 -0
  66. package/dist/core/src/index.d.ts +3 -2
  67. package/dist/core/src/index.d.ts.map +1 -1
  68. package/dist/core/src/repo-manager.d.ts +24 -0
  69. package/dist/core/src/repo-manager.d.ts.map +1 -1
  70. package/dist/core/src/runtime-assets.d.ts.map +1 -1
  71. package/dist/core/src/workspace-config.d.ts.map +1 -1
  72. package/dist/core/workspace-config.js +1 -1
  73. package/dist/deploy/index.js +3 -3
  74. package/dist/discovery/index.js +2 -2
  75. package/dist/{ensure-sources-NSDMTAWN.js → ensure-sources-KLCGXVE6.js} +12 -13
  76. package/dist/ensure-sources-KLCGXVE6.js.map +1 -0
  77. package/dist/factory-assets/connectors/deploy.js +5 -5
  78. package/dist/factory-assets/connectors/devserver.js +5 -5
  79. package/dist/factory-assets/connectors/flow/adapter.js +5 -5
  80. package/dist/factory-assets/connectors/flow/engine.js +3 -3
  81. package/dist/factory-assets/connectors/flow/run-flow.js +6 -6
  82. package/dist/factory-assets/connectors/flow.js +5 -5
  83. package/dist/factory-assets/connectors/git/CONNECTOR.md +8 -0
  84. package/dist/factory-assets/connectors/git/driver.d.ts +33 -1
  85. package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
  86. package/dist/factory-assets/connectors/git.js +5 -5
  87. package/dist/factory-assets/connectors/gmail.js +5 -5
  88. package/dist/factory-assets/connectors/googledrive.js +5 -5
  89. package/dist/factory-assets/connectors/local.js +5 -5
  90. package/dist/factory-assets/connectors/mattermost.js +5 -5
  91. package/dist/factory-assets/connectors/memory.js +5 -5
  92. package/dist/factory-assets/connectors/minio.js +5 -5
  93. package/dist/factory-assets/connectors/postgres.js +5 -5
  94. package/dist/factory-assets/connectors/s3.js +5 -5
  95. package/dist/factory-assets/connectors/sharepoint.js +5 -5
  96. package/dist/factory-assets/connectors/sqlite.js +5 -5
  97. package/dist/factory-assets/connectors/static-server.js +5 -5
  98. package/dist/factory-assets/connectors/tunnel.js +5 -5
  99. package/dist/factory-assets/connectors/webdav.js +5 -5
  100. package/dist/factory-assets/connectors/xstate-store.js +5 -5
  101. package/dist/factory-assets/connectors/xstate.js +5 -5
  102. package/dist/factory-assets/skaile.manifest.yaml +3 -0
  103. package/dist/factory-assets/skills/skailify/SKILL.md +84 -0
  104. package/dist/{flows-WELXQ7IG.js → flows-PNDUCOJR.js} +3 -3
  105. package/dist/{flows-WELXQ7IG.js.map → flows-PNDUCOJR.js.map} +1 -1
  106. package/dist/library/index.js +6 -6
  107. package/dist/library/install.js +3 -3
  108. package/dist/{open-library-362BZ6OW.js → open-library-COHFCT4N.js} +9 -9
  109. package/dist/{open-library-362BZ6OW.js.map → open-library-COHFCT4N.js.map} +1 -1
  110. package/dist/{paths-4SSFMX5Z.js → paths-2SYXGTZJ.js} +6 -6
  111. package/dist/{paths-4SSFMX5Z.js.map → paths-2SYXGTZJ.js.map} +1 -1
  112. package/dist/{plugin-store-RBCDBO7K.js → plugin-store-UNENLB56.js} +5 -5
  113. package/dist/{plugin-store-RBCDBO7K.js.map → plugin-store-UNENLB56.js.map} +1 -1
  114. package/dist/runner/index.js +7 -7
  115. package/dist/runner/src/file-changed-coalescer.d.ts +48 -0
  116. package/dist/runner/src/file-changed-coalescer.d.ts.map +1 -0
  117. package/dist/runner/src/resources.d.ts.map +1 -1
  118. package/dist/sdk/asset-manager.js +7 -7
  119. package/dist/sdk/core.js +3 -3
  120. package/dist/sdk/flow.js +3 -3
  121. package/dist/sdk/index.js +7 -7
  122. package/dist/sdk/runner.js +7 -7
  123. package/dist/{setup-VGZTFQ32.js → setup-AYH6SR4U.js} +5 -5
  124. package/dist/{setup-VGZTFQ32.js.map → setup-AYH6SR4U.js.map} +1 -1
  125. package/dist/{store-client-XFZFKY3W.js → store-client-U4FMAIWX.js} +6 -6
  126. package/dist/{store-client-XFZFKY3W.js.map → store-client-U4FMAIWX.js.map} +1 -1
  127. package/dist/tui/index.js +7 -7
  128. package/dist/types/manifests.js +1 -1
  129. package/dist/types/src/manifests/skill.d.ts +1 -0
  130. package/dist/types/src/manifests/skill.d.ts.map +1 -1
  131. package/dist/workspace-plugin/adapters/mcp.js +1 -1
  132. package/dist/workspace-plugin/adapters/omp.js +3 -3
  133. package/dist/workspace-plugin/index.js +1 -1
  134. package/package.json +1 -1
  135. package/dist/chunk-5LHPKVGR.js.map +0 -1
  136. package/dist/chunk-BLGHFVXE.js.map +0 -1
  137. package/dist/chunk-COSTF7QW.js.map +0 -1
  138. package/dist/chunk-JUZLVRI4.js.map +0 -1
  139. package/dist/chunk-LMRO2QNF.js.map +0 -1
  140. package/dist/chunk-RGPBEGP2.js.map +0 -1
  141. package/dist/chunk-VPXV2Z5E.js.map +0 -1
  142. package/dist/ensure-sources-NSDMTAWN.js.map +0 -1
package/dist/cli/index.js CHANGED
@@ -1,19 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-PCXU2CVW.js';
2
+ import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-FAALG3QN.js';
3
3
  import { logErr, S, logOk, logInfo, colorRef, logWarn, kindColorPad, kindColor, formatRelativeTime, fitWidth } from '../chunk-GYPA2Q7F.js';
4
- import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-XF2BBX6P.js';
5
- import { AI_RESOURCES, aiResourceRoots } from '../chunk-ETDXTGDF.js';
4
+ import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-Z3ZRI2AE.js';
5
+ import { AI_RESOURCES, aiResourceRoots } from '../chunk-HOEP5CJQ.js';
6
6
  import { LocalSecretsProvider } from '../chunk-6BEGKO2Q.js';
7
- import { resolveLibraryDir, LocalCatalogSource } from '../chunk-ZAEJ33Y6.js';
8
- import '../chunk-5FVJXQDP.js';
7
+ import { resolveLibraryDir, LocalCatalogSource } from '../chunk-LLOXWWB6.js';
8
+ import '../chunk-JXHULIOA.js';
9
9
  import '../chunk-JXT46QFC.js';
10
10
  import '../chunk-UKJMQZV6.js';
11
11
  import '../chunk-R7FOF242.js';
12
- import { runFlow, resumeFlow } from '../chunk-7NQXVBCQ.js';
12
+ import { runFlow, resumeFlow } from '../chunk-TKTXIAG5.js';
13
13
  import '../chunk-4R6DROGN.js';
14
14
  import { validateFlowVersions, parseSkillFrontmatter } from '../chunk-GXC3TYMQ.js';
15
- import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-5LHPKVGR.js';
16
- import { buildClaudePluginFiles } from '../chunk-NHLXS2CH.js';
15
+ import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-FX4BDEUN.js';
16
+ import { buildClaudePluginFiles } from '../chunk-PPSRBFYE.js';
17
17
  import '../chunk-X5YPJV4N.js';
18
18
  import '../chunk-O7SG5PC2.js';
19
19
  import '../chunk-7QBNJTTQ.js';
@@ -28,59 +28,514 @@ import '../chunk-BMQKMOQY.js';
28
28
  import '../chunk-GAH4YRCI.js';
29
29
  import '../chunk-OCAQH66V.js';
30
30
  import '../chunk-LV2HPH3C.js';
31
- import '../chunk-LMRO2QNF.js';
31
+ import '../chunk-3VT2I7IA.js';
32
32
  import '../chunk-OVRSNIKJ.js';
33
- import '../chunk-CBZEIFU4.js';
33
+ import '../chunk-DDR4OSSM.js';
34
34
  import '../chunk-FYLIR4AV.js';
35
35
  import '../chunk-6E6PKKAD.js';
36
36
  import { loadFlow, loadAllFlows } from '../chunk-X46FY45B.js';
37
37
  import '../chunk-DEYYRFQU.js';
38
38
  import '../chunk-IFGTRL2I.js';
39
- import { AssetManager, NON_DEPLOYABLE_KINDS } from '../chunk-JUZLVRI4.js';
40
- import '../chunk-CVWA4RIK.js';
41
- import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-BLGHFVXE.js';
39
+ import { AssetManager, NON_DEPLOYABLE_KINDS, MissingManifestError } from '../chunk-CNP2FHRM.js';
40
+ import '../chunk-4VPRAG35.js';
41
+ import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor, checkAgentSkillConformance } from '../chunk-G3GODNHM.js';
42
42
  import { assetSearchDirs, detectDomains } from '../chunk-ZAP2BDHG.js';
43
- import '../chunk-VPXV2Z5E.js';
44
- import { globalCacheRoot, getGlobalCacheDir, resolveAgentDir, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-COSTF7QW.js';
45
- import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest } from '../chunk-DZCK7GRW.js';
43
+ import '../chunk-3VBQJZYL.js';
44
+ import { globalCacheRoot, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, sourceShortName, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-WTFJFW7F.js';
45
+ import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, saveSkPublishManifest } from '../chunk-DZCK7GRW.js';
46
46
  import { parseFrontmatter } from '../chunk-6IDBWPK2.js';
47
- import { parseAssetRef, ASSET_KINDS, isValidAssetName, ASSET_NAME_HINT, assetRefToStr } from '../chunk-GEEW6SY2.js';
47
+ import { parseAssetRef, ASSET_KINDS, isValidAssetName, slugifyAssetName, ASSET_NAME_HINT, assetRefToStr } from '../chunk-GEEW6SY2.js';
48
48
  import '../chunk-XGCXFX7X.js';
49
49
  import { SUPPORTED_DRIVER_TARGETS } from '../chunk-O4JH3KUE.js';
50
50
  import { DRIVER_DEFAULTS } from '../chunk-K5GBV4SA.js';
51
51
  import { openSqlite } from '../chunk-JB35MVBN.js';
52
52
  import '../chunk-KTBKW2FI.js';
53
53
  import '../chunk-UQ6LFBPZ.js';
54
- import '../chunk-XUXVH3JK.js';
55
- import '../chunk-RGPBEGP2.js';
54
+ import '../chunk-WRBF34YE.js';
55
+ import '../chunk-CU5Z7GH3.js';
56
56
  import '../chunk-CGYEHQOX.js';
57
57
  import '../chunk-NSBPE2FW.js';
58
- import * as fs11 from 'fs';
59
- import fs11__default, { readFileSync, existsSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
60
- import * as path13 from 'path';
61
- import path13__default, { resolve, join } from 'path';
58
+ import * as fs12 from 'fs';
59
+ import fs12__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
60
+ import * as path14 from 'path';
61
+ import path14__default, { resolve, join } from 'path';
62
62
  import { fileURLToPath } from 'url';
63
63
  import { Help, Command, Option } from 'commander';
64
- import { homedir } from 'os';
65
64
  import * as p6 from '@clack/prompts';
66
65
  import pc5 from 'picocolors';
66
+ import * as os from 'os';
67
+ import { homedir } from 'os';
68
+ import { parse, stringify } from 'yaml';
67
69
  import * as readline from 'readline';
68
70
  import { createInterface } from 'readline';
69
- import fs5 from 'fs/promises';
70
- import { parse as parse$1, stringify } from 'smol-toml';
71
+ import fs6 from 'fs/promises';
72
+ import { parse as parse$1, stringify as stringify$1 } from 'smol-toml';
71
73
  import { execSync, spawnSync } from 'child_process';
72
74
  import { createTRPCUntypedClient, httpLink, httpSubscriptionLink } from '@trpc/client';
73
- import { parse } from 'yaml';
74
75
 
76
+ async function runSearch(kind, query, opts) {
77
+ if (kind?.includes(":")) {
78
+ query = kind;
79
+ kind = void 0;
80
+ }
81
+ const showLocal = !opts.store;
82
+ const showStore = !opts.local;
83
+ if (showLocal) {
84
+ searchLocal(query, kind, opts, showStore);
85
+ }
86
+ if (showStore) {
87
+ await searchStore(query, kind, opts);
88
+ }
89
+ }
90
+ function searchLocal(query, kind, opts, showStore) {
91
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
92
+ const entries = am2.search(query, kind);
93
+ if (entries.length === 0) {
94
+ if (!showStore) {
95
+ logInfo(
96
+ query ? `No entries matching "${query}".` : "No assets found. Run `skaile source sync` first."
97
+ );
98
+ }
99
+ return;
100
+ }
101
+ if (showStore) {
102
+ console.log(`
103
+ ${S.heading("Local:")}`);
104
+ }
105
+ printLocalEntries(entries);
106
+ }
107
+ function printLocalEntries(entries) {
108
+ const byKind = /* @__PURE__ */ new Map();
109
+ for (const e of entries) {
110
+ if (!byKind.has(e.kind)) byKind.set(e.kind, []);
111
+ byKind.get(e.kind).push(e);
112
+ }
113
+ for (const [k, items] of byKind) {
114
+ const nameW = Math.max(4, ...items.map((e) => e.name.length));
115
+ console.log();
116
+ console.log(
117
+ ` ${kindColor(k)} ${S.heading(`${k.toUpperCase()}S`)} ${S.dim(`(${items.length})`)}`
118
+ );
119
+ console.log(` ${S.rule(nameW + 62)}`);
120
+ for (const e of items) {
121
+ const ver = e.version ? S.dim(` v${e.version}`) : "";
122
+ console.log(` ${S.cmd(e.name.padEnd(nameW))} ${e.description.slice(0, 60)}${ver}`);
123
+ }
124
+ }
125
+ console.log(`
126
+ ${S.dim(`${entries.length} total`)}
127
+ `);
128
+ }
129
+ async function searchStore(query, kind, opts) {
130
+ try {
131
+ const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-U4FMAIWX.js');
132
+ const config = getStoreConfig2();
133
+ const params = {};
134
+ if (query) params.q = query;
135
+ if (kind) params.kind = kind;
136
+ const storeRes = await storeFetch2(config, "/api/assets", { params });
137
+ if (storeRes.results.length > 0) {
138
+ console.log(`
139
+ ${S.heading("Store:")}`);
140
+ for (const asset of storeRes.results) {
141
+ const ref = `${asset.kind}:@${asset.publisher}/${asset.slug}`;
142
+ console.log(
143
+ ` \u2B21 ${kindColorPad(asset.kind)} ${colorRef(ref).padEnd(40)} ${S.dim(asset.description?.slice(0, 50) || "")} ${S.dim(`\u2193${asset.downloads}`)}`
144
+ );
145
+ }
146
+ } else if (opts.store) {
147
+ logInfo("No results in store");
148
+ }
149
+ } catch (e) {
150
+ if (opts.store) {
151
+ logErr(`Store search failed: ${e.message}`);
152
+ }
153
+ }
154
+ }
155
+ function makeSearchCommand() {
156
+ return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").action(async (kind, query, opts) => {
157
+ await runSearch(kind, query, opts);
158
+ });
159
+ }
160
+ function makeAddCommand() {
161
+ return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:@<publisher>/name#<version>)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Deploy to global dir (~/.claude)").option("--target <agent>", "Driver target", "claude-code").action(async (ref, opts) => {
162
+ const am2 = new AssetManager({
163
+ projectDir: path14__default.resolve(opts.projectDir),
164
+ global: opts.global,
165
+ driverTarget: opts.target
166
+ });
167
+ const spinner5 = p6.spinner();
168
+ spinner5.start(`Adding ${ref}`);
169
+ try {
170
+ const added = await am2.add(ref);
171
+ spinner5.stop("Done");
172
+ if (added.length === 0) {
173
+ const kind = parseAssetRef(ref).kind;
174
+ if (NON_DEPLOYABLE_KINDS.has(kind))
175
+ logInfo(
176
+ `Recorded in skaile.yaml. ${kind} assets are not deployed into the driver target \u2014 they are wired when skaile runs the agent.`
177
+ );
178
+ else logInfo("Nothing to deploy (already up to date).");
179
+ } else for (const a of added) logOk(a);
180
+ } catch (err) {
181
+ spinner5.stop("Failed");
182
+ logErr(String(err));
183
+ process.exit(1);
184
+ }
185
+ });
186
+ }
187
+ function makeRemoveCommand() {
188
+ return new Command("remove").description("Remove from skaile.yaml + undeploy").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Remove from global dir").option("--target <agent>", "Driver target", "claude-code").action((ref, opts) => {
189
+ const am2 = new AssetManager({
190
+ projectDir: path14__default.resolve(opts.projectDir),
191
+ global: opts.global,
192
+ driverTarget: opts.target
193
+ });
194
+ const ok = am2.remove(ref);
195
+ if (ok) logOk(`Removed ${ref}`);
196
+ else logErr(`Not deployed: ${ref}`);
197
+ });
198
+ }
199
+ function stateLabel(s) {
200
+ if (s === "installed") return S.ok(s);
201
+ if (s === "drift") return S.warn(s);
202
+ if (s === "invalid") return S.err(s);
203
+ return S.dim(s);
204
+ }
205
+ function makeListCommand() {
206
+ return new Command("list").description("List declared dependencies from skaile.yaml with state").argument("[kind]", "Filter by asset kind").option("--project-dir <path>", "Project directory", process.cwd()).option("-g, --global", "Inspect the global deployment dir for state").option("--json", "Output as JSON").addOption(
207
+ new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
208
+ ).action((kind, opts) => {
209
+ const am2 = new AssetManager({
210
+ projectDir: path14__default.resolve(opts.projectDir),
211
+ global: opts.global,
212
+ driverTarget: opts.target
213
+ });
214
+ let declared;
215
+ try {
216
+ declared = am2.listDeclared(kind);
217
+ } catch (err) {
218
+ if (err instanceof MissingManifestError)
219
+ logErr(`No ${S.cmd("skaile.yaml")} found. Run ${S.cmd("skaile init")} to create one.`);
220
+ else logErr(err instanceof Error ? err.message : String(err));
221
+ process.exit(1);
222
+ }
223
+ if (opts.json) {
224
+ console.log(JSON.stringify(declared, null, 2));
225
+ return;
226
+ }
227
+ if (declared.length === 0) {
228
+ logInfo("No dependencies declared in skaile.yaml.");
229
+ return;
230
+ }
231
+ const kindW = Math.max(4, ...declared.map((e) => e.kind.length));
232
+ const nameW = Math.max(4, ...declared.map((e) => e.name.length));
233
+ console.log();
234
+ console.log(
235
+ ` ${S.dim("KIND".padEnd(kindW))} ${S.dim("NAME".padEnd(nameW))} ${S.dim("STATE")}`
236
+ );
237
+ console.log(` ${S.rule(kindW + nameW + 4 + "installed".length)}`);
238
+ for (const e of declared) {
239
+ console.log(
240
+ ` ${kindColorPad(e.kind, kindW)} ${e.name.padEnd(nameW)} ${stateLabel(e.state)}`
241
+ );
242
+ }
243
+ console.log(`
244
+ ${S.dim(`${declared.length} declared`)}`);
245
+ const drift = declared.filter((e) => e.state === "drift").length;
246
+ if (drift > 0)
247
+ logInfo(`${drift} with drift \u2014 run ${S.cmd("skaile install")} to materialize.`);
248
+ const invalid = declared.filter((e) => e.state === "invalid").length;
249
+ if (invalid > 0)
250
+ logInfo(`${invalid} invalid \u2014 fix the ${S.cmd("skaile.yaml")} dependencies entry.`);
251
+ console.log();
252
+ });
253
+ }
254
+ function makeInfoCommand() {
255
+ return new Command("info").description("Show asset metadata, deps, deploy status").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
256
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
257
+ const entry = am2.info(ref);
258
+ if (!entry) {
259
+ logErr(
260
+ `'${ref}' not found. Run ${S.cmd("skaile source sync")} then ${S.cmd("skaile search")}.`
261
+ );
262
+ process.exit(1);
263
+ }
264
+ console.log();
265
+ console.log(` ${S.heading(entry.name)}`);
266
+ console.log(` ${S.rule(40)}`);
267
+ console.log(` kind: ${kindColor(entry.kind)}`);
268
+ if (entry.version) console.log(` version: ${entry.version}`);
269
+ if (entry.description) console.log(` description: ${entry.description}`);
270
+ if (entry.publisher) console.log(` repository: ${S.dim(entry.publisher)}`);
271
+ console.log(` source: ${S.dim(entry.source)}`);
272
+ if (entry.requires.length) {
273
+ console.log(` requires:`);
274
+ for (const d of entry.requires)
275
+ console.log(` ${S.dim("\xB7")} ${kindColor(d.kind)}:${d.name}`);
276
+ }
277
+ if (entry.dependencies.length) {
278
+ console.log(` dependencies:`);
279
+ for (const s of entry.dependencies) console.log(` ${S.dim("\xB7")} ${colorRef(s)}`);
280
+ }
281
+ console.log();
282
+ });
283
+ }
284
+ function makeCreateCommand() {
285
+ return new Command("create").description("Scaffold a new asset").argument("<name>", "Asset name").addOption(
286
+ new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...ASSET_KINDS])
287
+ ).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
288
+ const am2 = new AssetManager({ projectDir: process.cwd() });
289
+ const destDir = opts.dir ? path14__default.resolve(opts.dir) : process.cwd();
290
+ const result = am2.create(name, opts.kind, destDir);
291
+ if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
292
+ else {
293
+ logErr(result.path);
294
+ process.exit(1);
295
+ }
296
+ });
297
+ }
298
+ function makeDoctorCommand() {
299
+ return new Command("doctor").description("Scan for missing dependency chains").argument("[name]", "Check a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((name, opts) => {
300
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
301
+ const issues = am2.doctor();
302
+ if (issues.length === 0) {
303
+ logOk("No missing dependencies.");
304
+ return;
305
+ }
306
+ const assetW = Math.max(5, ...issues.map((i) => `${i.assetKind}:${i.assetName}`.length));
307
+ const depW = Math.max(11, ...issues.map((i) => `${i.depKind}:${i.depName}`.length));
308
+ console.log();
309
+ console.log(
310
+ ` ${S.dim("ASSET".padEnd(assetW))} ${S.dim("MISSING DEP".padEnd(depW))} ${S.dim("IN REPOS")}`
311
+ );
312
+ console.log(` ${S.rule(assetW + depW + 15)}`);
313
+ for (const i of issues) {
314
+ const asset = `${i.assetKind}:${i.assetName}`;
315
+ const dep = `${i.depKind}:${i.depName}`;
316
+ const status4 = i.inRepos ? S.warn("fixable") : S.err("not found");
317
+ console.log(` ${asset.padEnd(assetW)} ${dep.padEnd(depW)} ${status4}`);
318
+ }
319
+ console.log();
320
+ });
321
+ }
322
+ var DEFAULT_IMPORT_VERSION = "0.1.0";
323
+ var DEFAULT_IMPORT_STAGE = "alpha";
324
+ function claudeSkillRoots() {
325
+ const roots = [];
326
+ const override = process.env.SKAILE_CLAUDE_SKILLS_DIR;
327
+ if (override) roots.push(override);
328
+ roots.push(path14.join(os.homedir(), ".claude", "skills"));
329
+ return roots;
330
+ }
331
+ function resolveImportSource(nameOrPath) {
332
+ const asPath = path14.resolve(nameOrPath);
333
+ if (fs12.existsSync(asPath)) {
334
+ const dir = fs12.statSync(asPath).isDirectory() ? asPath : path14.dirname(asPath);
335
+ const skillFile = path14.join(dir, "SKILL.md");
336
+ if (fs12.existsSync(skillFile)) return { dir, skillFile, via: "path" };
337
+ }
338
+ if (!nameOrPath.includes(path14.sep) && !nameOrPath.startsWith(".")) {
339
+ for (const root of claudeSkillRoots()) {
340
+ const dir = path14.join(root, nameOrPath);
341
+ const skillFile = path14.join(dir, "SKILL.md");
342
+ if (fs12.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
343
+ }
344
+ }
345
+ return null;
346
+ }
347
+ function normalizeSkillContent(raw, opts = {}) {
348
+ const notes = [];
349
+ const { data, body } = parseFrontmatter(raw);
350
+ const rawName = typeof data.name === "string" && data.name.trim() ? data.name.trim() : void 0;
351
+ const sourceName = rawName ?? opts.fallbackName ?? "";
352
+ let name = sourceName;
353
+ let originalName;
354
+ if (!sourceName) {
355
+ throw new Error("skill has no `name` in frontmatter and no fallback was provided");
356
+ }
357
+ if (!isValidAssetName(sourceName)) {
358
+ name = slugifyAssetName(sourceName);
359
+ originalName = sourceName;
360
+ notes.push(`renamed "${sourceName}" \u2192 "${name}" (canonical kebab-case)`);
361
+ }
362
+ const existingMeta = data.metadata && typeof data.metadata === "object" && !Array.isArray(data.metadata) ? { ...data.metadata } : {};
363
+ if (existingMeta.version == null) {
364
+ existingMeta.version = opts.version ?? DEFAULT_IMPORT_VERSION;
365
+ notes.push(`stamped metadata.version: ${existingMeta.version}`);
366
+ }
367
+ if (existingMeta.stage == null) {
368
+ existingMeta.stage = opts.stage ?? DEFAULT_IMPORT_STAGE;
369
+ notes.push(`stamped metadata.stage: ${existingMeta.stage}`);
370
+ }
371
+ if (existingMeta.tags == null) {
372
+ const keywords = Array.isArray(data.keywords) ? data.keywords : [];
373
+ existingMeta.tags = keywords.filter((k) => typeof k === "string");
374
+ if (existingMeta.tags.length > 0) {
375
+ notes.push("promoted top-level keywords \u2192 metadata.tags");
376
+ }
377
+ }
378
+ const ordered = { name };
379
+ if (data.description != null) ordered.description = data.description;
380
+ ordered.metadata = existingMeta;
381
+ for (const [k, v] of Object.entries(data)) {
382
+ if (k === "name" || k === "description" || k === "metadata" || k === "keywords") continue;
383
+ ordered[k] = v;
384
+ }
385
+ const fm = stringify(ordered).trimEnd();
386
+ const content = `---
387
+ ${fm}
388
+ ---
389
+
390
+ ${body}
391
+ `;
392
+ const changed = notes.length > 0;
393
+ return { content, name, originalName, changed, notes };
394
+ }
395
+ var DOMAIN_TEMPLATE = (name, publisher, description) => {
396
+ const fm = stringify({ name, publisher, description }).trimEnd();
397
+ return `---
398
+ ${fm}
399
+ ---
400
+
401
+ # ${name}
402
+
403
+ ${description}
404
+ `;
405
+ };
406
+ function ensureDomain(libraryPath, domain, opts = {}) {
407
+ const dir = path14.join(libraryPath, domain);
408
+ const domainFile = path14.join(dir, "DOMAIN.md");
409
+ const publisher = opts.publisher ?? slugifyAssetName(domain);
410
+ if (fs12.existsSync(domainFile)) {
411
+ return { dir, publisher, created: false };
412
+ }
413
+ fs12.mkdirSync(dir, { recursive: true });
414
+ const description = opts.description ?? `The ${domain} domain.`;
415
+ fs12.writeFileSync(domainFile, DOMAIN_TEMPLATE(domain, publisher, description), "utf8");
416
+ return { dir, publisher, created: true };
417
+ }
418
+ function listDomains(libraryPath) {
419
+ if (!fs12.existsSync(libraryPath)) return [];
420
+ return fs12.readdirSync(libraryPath, { withFileTypes: true }).filter((e) => e.isDirectory() && fs12.existsSync(path14.join(libraryPath, e.name, "DOMAIN.md"))).map((e) => e.name).sort();
421
+ }
422
+ function upsertManifestAsset(libraryPath, input) {
423
+ const manifest = loadSkPublishManifest(libraryPath) ?? { assets: [] };
424
+ const assets = Array.isArray(manifest.assets) ? [...manifest.assets] : [];
425
+ const entry = { kind: input.kind, name: input.name, root: input.root };
426
+ if (input.version) entry.version = input.version;
427
+ if (input.publisher) entry.publisher = input.publisher;
428
+ if (input.description) entry.description = input.description;
429
+ if (input.keywords && input.keywords.length > 0) entry.keywords = input.keywords;
430
+ const idx = assets.findIndex((a) => a.kind === input.kind && a.name === input.name);
431
+ const added = idx < 0;
432
+ if (added) {
433
+ assets.push(entry);
434
+ } else {
435
+ assets[idx] = { ...assets[idx], ...entry };
436
+ }
437
+ const manifestPath = saveSkPublishManifest(libraryPath, { ...manifest, assets });
438
+ return { manifestPath, added };
439
+ }
440
+
441
+ // cli/src/commands/asset-cmd.ts
75
442
  function makeAssetCommand() {
76
443
  const cmd = new Command("asset").description("Author and install AI assets");
444
+ cmd.command("import <name-or-path>").description("Import + skailify an existing coding-agent skill into a library").option("--to <library>", "Target library (default: auto / personal)").option("--domain <name>", "Place under this domain's skills/ (created if missing)").option("--version <semver>", "Version to stamp when the skill ships none").option("--stage <stage>", "Lifecycle stage to stamp (default: alpha)").option("--no-normalize", "Copy verbatim \u2014 skip frontmatter normalization").option("--commit", "Auto-commit in git-backed libraries", false).action(
445
+ async (nameOrPath, opts) => {
446
+ const src = resolveImportSource(nameOrPath);
447
+ if (!src) {
448
+ logErr(
449
+ `No skill found for "${nameOrPath}". Pass a path to a SKILL.md dir, or a bare name present under ~/.claude/skills/.`
450
+ );
451
+ process.exit(1);
452
+ }
453
+ logInfo(`Source: ${S.dim(src.dir)} (${src.via})`);
454
+ const { manager, close } = await openLibraryManager();
455
+ try {
456
+ let target;
457
+ if (opts.to) {
458
+ target = await manager.requireLibrary(opts.to);
459
+ } else {
460
+ const all = await manager.listLibraries();
461
+ const def = all.find(
462
+ (l) => l.isDefault && (l.ownership === "owner" || l.ownership === "contributor")
463
+ );
464
+ target = def ?? (await manager.ensurePersonalLibrary(resolveLibraryDir())).library;
465
+ }
466
+ if (target.ownership === "reader") {
467
+ logErr(`Library "${target.name}" is read-only (ownership=reader). Choose --to.`);
468
+ process.exit(1);
469
+ }
470
+ const rawSkill = fs12.readFileSync(src.skillFile, "utf8");
471
+ const norm = opts.normalize ? normalizeSkillContent(rawSkill, {
472
+ fallbackName: path14.basename(src.dir),
473
+ version: opts.version,
474
+ stage: opts.stage
475
+ }) : { content: rawSkill, name: path14.basename(src.dir), changed: false, notes: [] };
476
+ if (!opts.normalize && !isValidAssetName(norm.name)) {
477
+ logWarn(
478
+ `Name "${norm.name}" is not canonical (kebab-case); \`skaile validate\` will reject this manifest entry. Drop --no-normalize to slugify it.`
479
+ );
480
+ }
481
+ let destParent = target.path;
482
+ let publisher;
483
+ if (opts.domain) {
484
+ const dom = ensureDomain(target.path, opts.domain);
485
+ if (dom.created) logOk(`Scaffolded domain ${S.cmd(opts.domain)} \u2192 ${dom.dir}`);
486
+ destParent = path14.join(dom.dir, "skills");
487
+ publisher = dom.publisher;
488
+ }
489
+ fs12.mkdirSync(destParent, { recursive: true });
490
+ const destDir = path14.join(destParent, norm.name);
491
+ if (fs12.existsSync(destDir)) {
492
+ logErr(`Destination already exists: ${destDir}`);
493
+ process.exit(1);
494
+ }
495
+ fs12.cpSync(src.dir, destDir, { recursive: true });
496
+ fs12.writeFileSync(path14.join(destDir, "SKILL.md"), norm.content, "utf8");
497
+ for (const note of norm.notes) logInfo(` \u2022 ${note}`);
498
+ const fm = parseFrontmatter(norm.content).data;
499
+ const descRaw = fm.description;
500
+ const description = typeof descRaw === "string" ? descRaw.trim() : void 0;
501
+ for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
502
+ logWarn(`conformance: ${f.field} \u2014 ${f.message}`);
503
+ }
504
+ const root = path14.relative(target.path, destDir);
505
+ const up = upsertManifestAsset(target.path, {
506
+ kind: "skill",
507
+ name: norm.name,
508
+ root,
509
+ version: opts.version,
510
+ publisher,
511
+ description
512
+ });
513
+ logOk(`${up.added ? "Added" : "Updated"} manifest entry skill:${norm.name}`);
514
+ if (target.backend === "git" && opts.commit) {
515
+ const { spawnSync: spawnSync2 } = await import('child_process');
516
+ spawnSync2("git", ["add", "--", destDir], { cwd: target.path, stdio: "inherit" });
517
+ const r = spawnSync2("git", ["commit", "-m", `skaile: import ${norm.name}`], {
518
+ cwd: target.path,
519
+ stdio: "inherit"
520
+ });
521
+ if (r.status !== 0) {
522
+ logWarn("Nothing committed (working tree clean or commit aborted).");
523
+ }
524
+ }
525
+ logOk(`Imported ${S.cmd(norm.name)} \u2192 ${target.name}`);
526
+ logInfo(`Verify: ${S.cmd(`skaile validate ${target.path}`)}`);
527
+ } finally {
528
+ close();
529
+ }
530
+ }
531
+ );
77
532
  cmd.command("migrate <path>").description("Move/copy/link a workspace asset into a library").option("--to <library>", "Target library (default: auto)").option("--domain <name>", "Place inside this domain (domain-structured libs)").option("--mode <mode>", "copy | move | link", "copy").option("--commit", "Auto-commit in git-backed libraries", false).action(
78
533
  async (srcPath, opts) => {
79
534
  if (!["copy", "move", "link"].includes(opts.mode)) {
80
535
  logErr(`Invalid --mode "${opts.mode}". Expected: copy | move | link.`);
81
536
  process.exit(1);
82
537
  }
83
- if (!fs11.existsSync(srcPath)) {
538
+ if (!fs12.existsSync(srcPath)) {
84
539
  logErr(`Source path does not exist: ${srcPath}`);
85
540
  process.exit(1);
86
541
  }
@@ -107,32 +562,35 @@ function makeAssetCommand() {
107
562
  );
108
563
  process.exit(1);
109
564
  }
110
- const basename2 = path13.basename(srcPath);
111
- const destDir = target.structure === "domain" && opts.domain ? path13.join(target.path, opts.domain) : target.path;
112
- fs11.mkdirSync(destDir, { recursive: true });
113
- const destPath = path13.join(destDir, basename2);
114
- if (fs11.existsSync(destPath)) {
565
+ const basename2 = path14.basename(srcPath);
566
+ const destDir = target.structure === "domain" && opts.domain ? path14.join(target.path, opts.domain) : target.path;
567
+ fs12.mkdirSync(destDir, { recursive: true });
568
+ const destPath = path14.join(destDir, basename2);
569
+ if (fs12.existsSync(destPath)) {
115
570
  logErr(`Destination already exists: ${destPath}`);
116
571
  process.exit(1);
117
572
  }
118
573
  switch (opts.mode) {
119
574
  case "copy":
120
- fs11.cpSync(srcPath, destPath, { recursive: true });
575
+ fs12.cpSync(srcPath, destPath, { recursive: true });
121
576
  break;
122
577
  case "move":
123
- fs11.renameSync(srcPath, destPath);
578
+ fs12.renameSync(srcPath, destPath);
124
579
  break;
125
580
  case "link":
126
- fs11.symlinkSync(path13.resolve(srcPath), destPath);
581
+ fs12.symlinkSync(path14.resolve(srcPath), destPath);
127
582
  break;
128
583
  }
129
584
  if (target.backend === "git" && opts.commit) {
130
585
  const { spawnSync: spawnSync2 } = await import('child_process');
131
- spawnSync2("git", ["add", "-A"], { cwd: target.path, stdio: "ignore" });
132
- spawnSync2("git", ["commit", "-m", `skaile: migrate ${basename2}`], {
586
+ spawnSync2("git", ["add", "--", destPath], { cwd: target.path, stdio: "inherit" });
587
+ const r = spawnSync2("git", ["commit", "-m", `skaile: migrate ${basename2}`], {
133
588
  cwd: target.path,
134
- stdio: "ignore"
589
+ stdio: "inherit"
135
590
  });
591
+ if (r.status !== 0) {
592
+ logWarn("Nothing committed (working tree clean or commit aborted).");
593
+ }
136
594
  }
137
595
  logOk(`Migrated ${basename2} \u2192 ${target.name} (${opts.mode})`);
138
596
  if (opts.mode === "move") {
@@ -157,7 +615,7 @@ function makeAssetCommand() {
157
615
  try {
158
616
  const def = await library.getAssetDef(ref);
159
617
  if (!def) {
160
- logErr(`No asset found for ref "${ref}". Try \`skaile asset list\`.`);
618
+ logErr(`No asset found for ref "${ref}". Try \`skaile search\`.`);
161
619
  process.exit(1);
162
620
  }
163
621
  const target = opts.target ?? process.cwd();
@@ -171,17 +629,17 @@ function makeAssetCommand() {
171
629
  }
172
630
  const manifestPath = def.manifest.path;
173
631
  const candidateSubpath = typeof manifestPath === "string" && manifestPath.length > 0 ? manifestPath : def.name;
174
- const srcPath = path13.join(lib.path, candidateSubpath);
175
- if (!fs11.existsSync(srcPath)) {
632
+ const srcPath = path14.join(lib.path, candidateSubpath);
633
+ if (!fs12.existsSync(srcPath)) {
176
634
  logErr(`Asset path not found: ${srcPath}`);
177
635
  process.exit(1);
178
636
  }
179
- const destPath = path13.join(target, candidateSubpath);
180
- fs11.mkdirSync(path13.dirname(destPath), { recursive: true });
637
+ const destPath = path14.join(target, candidateSubpath);
638
+ fs12.mkdirSync(path14.dirname(destPath), { recursive: true });
181
639
  if (opts.mode === "copy") {
182
- fs11.cpSync(srcPath, destPath, { recursive: true });
640
+ fs12.cpSync(srcPath, destPath, { recursive: true });
183
641
  } else {
184
- fs11.symlinkSync(path13.resolve(srcPath), destPath);
642
+ fs12.symlinkSync(path14.resolve(srcPath), destPath);
185
643
  }
186
644
  logOk(`Installed ${ref} \u2192 ${destPath} (${opts.mode})`);
187
645
  } finally {
@@ -189,29 +647,7 @@ function makeAssetCommand() {
189
647
  }
190
648
  }
191
649
  );
192
- cmd.command("list").description("List asset definitions across libraries").option("--library <name>", "Filter by library").option("--domain <name>", "Filter by domain").option("--kind <kind>", "Filter by kind").option("--json", "Output as JSON").action(async (opts) => {
193
- const { manager, library, close } = await openLibraryManager();
194
- try {
195
- let defs = await library.listAssetDefs(opts.kind ? { kind: opts.kind } : void 0);
196
- if (opts.library) {
197
- const lib = await manager.requireLibrary(opts.library);
198
- defs = defs.filter((d) => d.libraryId === lib.id);
199
- }
200
- if (opts.json) return console.log(JSON.stringify(defs, null, 2));
201
- if (defs.length === 0) {
202
- logInfo("No assets cached. Run `skaile library sync <name>` first.");
203
- return;
204
- }
205
- for (const d of defs) {
206
- console.log(` ${S.cmd(d.id.padEnd(40))} ${d.kind.padEnd(10)} ${d.description ?? ""}`);
207
- }
208
- console.log(`
209
- ${S.dim(`${defs.length} asset(s)`)}
210
- `);
211
- } finally {
212
- close();
213
- }
214
- });
650
+ cmd.addCommand(makeListCommand());
215
651
  cmd.command("show <ref>").description("Show details for an asset by canonical ref").action(async (ref) => {
216
652
  const { library, close } = await openLibraryManager();
217
653
  try {
@@ -237,354 +673,136 @@ function makeAuthCommand() {
237
673
  const health = await provider.testConnection();
238
674
  if (health.ok) {
239
675
  logOk(`Local provider: healthy (${health.latencyMs}ms)`);
240
- } else {
241
- logErr(`Local provider: ${health.error ?? "unhealthy"}`);
242
- }
243
- });
244
- cmd.command("set-key-strategy").description("Set the master key strategy (keychain, passphrase, or machine)").argument("<strategy>", `One of: ${VALID_STRATEGIES.join(", ")}`).option(
245
- "--passphrase <value>",
246
- "Passphrase value (required for passphrase strategy; alternative to SKAILE_SECRETS_PASSPHRASE env var)"
247
- ).action(async (strategy, opts) => {
248
- if (!VALID_STRATEGIES.includes(strategy)) {
249
- logErr(`Invalid strategy "${strategy}". Must be one of: ${VALID_STRATEGIES.join(", ")}`);
250
- process.exit(1);
251
- }
252
- if (strategy === "passphrase" && !opts.passphrase && !process.env.SKAILE_SECRETS_PASSPHRASE) {
253
- logErr(
254
- "Passphrase required. Provide via --passphrase or set SKAILE_SECRETS_PASSPHRASE:\n export SKAILE_SECRETS_PASSPHRASE='...'\n skaile auth set-key-strategy passphrase"
255
- );
256
- process.exit(1);
257
- }
258
- const provider = new LocalSecretsProvider();
259
- try {
260
- await provider.setKeyStrategy(strategy, opts.passphrase);
261
- logOk(`Key strategy set to: ${strategy}`);
262
- } catch (e) {
263
- logErr(`Failed to set strategy: ${e instanceof Error ? e.message : String(e)}`);
264
- process.exit(1);
265
- }
266
- });
267
- return cmd;
268
- }
269
- function collectCacheTargets(scope) {
270
- const out = [];
271
- out.push(path13__default.join(scope.projectDir, ".skaile", "cache"));
272
- out.push(path13__default.join(scope.projectDir, ".skaile", "store-cache"));
273
- out.push(path13__default.join(scope.projectDir, ".skaile", "repos"));
274
- if (scope.global) {
275
- out.push(globalCacheRoot());
276
- const home = process.env.SKAILE_HOME ?? path13__default.join(homedir(), ".skaile");
277
- out.push(path13__default.join(home, "repos"));
278
- out.push(path13__default.join(home, "catalog-cache"));
279
- }
280
- return out;
281
- }
282
- function dirSize(target) {
283
- if (!existsSync(target)) return 0;
284
- const st = lstatSync(target);
285
- if (st.isSymbolicLink()) return 0;
286
- if (!st.isDirectory()) return st.size;
287
- return dirSizeOfDir(target);
288
- }
289
- function dirSizeOfDir(dir) {
290
- let total = 0;
291
- for (const ent of readdirSync(dir, { withFileTypes: true })) {
292
- const child = path13__default.join(dir, ent.name);
293
- if (ent.isSymbolicLink()) continue;
294
- if (ent.isDirectory()) total += dirSizeOfDir(child);
295
- else if (ent.isFile()) total += statSync(child).size;
296
- }
297
- return total;
298
- }
299
- function removeCacheTargets(targets, opts) {
300
- const present = targets.filter((t) => existsSync(t));
301
- for (const t of present) rmSync(t, { recursive: true, force: true });
302
- return present;
303
- }
304
- function fmtBytes(n) {
305
- const u = ["B", "KB", "MB", "GB"];
306
- let i = 0;
307
- let v = n;
308
- while (v >= 1024 && i < u.length - 1) {
309
- v /= 1024;
310
- i++;
311
- }
312
- return `${v.toFixed(i === 0 ? 0 : 1)} ${u[i]}`;
313
- }
314
- function makeCacheCommand() {
315
- const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
316
- cmd.command("clean").description("Remove the project cache (.skaile/cache); --global also clears ~/.skaile/cache").option("--global", "Also clear the global cache (sources + catalog) and legacy dirs").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
317
- const targets = collectCacheTargets({
318
- projectDir: path13__default.resolve(opts.projectDir),
319
- global: opts.global
320
- }).filter((t) => existsSync(t));
321
- if (targets.length === 0) {
322
- logInfo("Cache is already empty.");
323
- return;
324
- }
325
- console.log();
326
- console.log(` ${S.heading("Will remove:")}`);
327
- for (const t of targets)
328
- console.log(` ${S.dim(t)} ${S.dim(`(${fmtBytes(dirSize(t))})`)}`);
329
- if (opts.dryRun) {
330
- console.log();
331
- logInfo("Dry run \u2014 no changes made.");
332
- return;
333
- }
334
- if (!opts.yes) {
335
- const ok = await p6.confirm({
336
- message: opts.global ? "Clear project AND global cache?" : "Clear project cache?"
337
- });
338
- if (p6.isCancel(ok) || !ok) {
339
- logInfo("Cancelled.");
340
- return;
341
- }
342
- }
343
- const removed = removeCacheTargets(targets);
344
- console.log();
345
- for (const r of removed) logOk(`Removed ${r}`);
346
- });
347
- cmd.command("dir").description("Print the resolved cache roots").option("--global", "Include the global cache root").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
348
- console.log(path13__default.join(path13__default.resolve(opts.projectDir), ".skaile", "cache"));
349
- if (opts.global) console.log(globalCacheRoot());
350
- });
351
- cmd.command("size").description("Show cache disk usage per directory").option("--global", "Include the global cache").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
352
- const targets = collectCacheTargets({
353
- projectDir: path13__default.resolve(opts.projectDir),
354
- global: opts.global
355
- });
356
- console.log();
357
- for (const t of targets) {
358
- if (!existsSync(t)) continue;
359
- console.log(` ${S.dim(fmtBytes(dirSize(t)).padStart(9))} ${t}`);
360
- }
361
- console.log();
362
- });
363
- return cmd;
364
- }
365
- async function runSearch(kind, query, opts) {
366
- if (kind?.includes(":")) {
367
- query = kind;
368
- kind = void 0;
369
- }
370
- const showLocal = !opts.store;
371
- const showStore = !opts.local;
372
- if (showLocal) {
373
- searchLocal(query, kind, opts, showStore);
374
- }
375
- if (showStore) {
376
- await searchStore(query, kind, opts);
377
- }
378
- }
379
- function searchLocal(query, kind, opts, showStore) {
380
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
381
- const entries = am2.search(query, kind);
382
- if (entries.length === 0) {
383
- if (!showStore) {
384
- logInfo(
385
- query ? `No entries matching "${query}".` : "No assets found. Run `skaile source sync` first."
386
- );
387
- }
388
- return;
389
- }
390
- if (showStore) {
391
- console.log(`
392
- ${S.heading("Local:")}`);
393
- }
394
- printLocalEntries(entries);
395
- }
396
- function printLocalEntries(entries) {
397
- const byKind = /* @__PURE__ */ new Map();
398
- for (const e of entries) {
399
- if (!byKind.has(e.kind)) byKind.set(e.kind, []);
400
- byKind.get(e.kind).push(e);
401
- }
402
- for (const [k, items] of byKind) {
403
- const nameW = Math.max(4, ...items.map((e) => e.name.length));
404
- console.log();
405
- console.log(
406
- ` ${kindColor(k)} ${S.heading(`${k.toUpperCase()}S`)} ${S.dim(`(${items.length})`)}`
407
- );
408
- console.log(` ${S.rule(nameW + 62)}`);
409
- for (const e of items) {
410
- const ver = e.version ? S.dim(` v${e.version}`) : "";
411
- console.log(` ${S.cmd(e.name.padEnd(nameW))} ${e.description.slice(0, 60)}${ver}`);
412
- }
413
- }
414
- console.log(`
415
- ${S.dim(`${entries.length} total`)}
416
- `);
417
- }
418
- async function searchStore(query, kind, opts) {
419
- try {
420
- const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-XFZFKY3W.js');
421
- const config = getStoreConfig2();
422
- const params = {};
423
- if (query) params.q = query;
424
- if (kind) params.kind = kind;
425
- const storeRes = await storeFetch2(config, "/api/assets", { params });
426
- if (storeRes.results.length > 0) {
427
- console.log(`
428
- ${S.heading("Store:")}`);
429
- for (const asset of storeRes.results) {
430
- const ref = `${asset.kind}:@${asset.publisher}/${asset.slug}`;
431
- console.log(
432
- ` \u2B21 ${kindColorPad(asset.kind)} ${colorRef(ref).padEnd(40)} ${S.dim(asset.description?.slice(0, 50) || "")} ${S.dim(`\u2193${asset.downloads}`)}`
433
- );
434
- }
435
- } else if (opts.store) {
436
- logInfo("No results in store");
437
- }
438
- } catch (e) {
439
- if (opts.store) {
440
- logErr(`Store search failed: ${e.message}`);
676
+ } else {
677
+ logErr(`Local provider: ${health.error ?? "unhealthy"}`);
441
678
  }
442
- }
443
- }
444
- function makeSearchCommand() {
445
- return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").action(async (kind, query, opts) => {
446
- await runSearch(kind, query, opts);
447
679
  });
448
- }
449
- function makeAddCommand() {
450
- return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:name[@repo])").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Deploy to global dir (~/.claude)").option("--target <agent>", "Driver target", "claude-code").action(async (ref, opts) => {
451
- const am2 = new AssetManager({
452
- projectDir: path13__default.resolve(opts.projectDir),
453
- global: opts.global,
454
- driverTarget: opts.target
455
- });
456
- const spinner5 = p6.spinner();
457
- spinner5.start(`Adding ${ref}`);
680
+ cmd.command("set-key-strategy").description("Set the master key strategy (keychain, passphrase, or machine)").argument("<strategy>", `One of: ${VALID_STRATEGIES.join(", ")}`).option(
681
+ "--passphrase <value>",
682
+ "Passphrase value (required for passphrase strategy; alternative to SKAILE_SECRETS_PASSPHRASE env var)"
683
+ ).action(async (strategy, opts) => {
684
+ if (!VALID_STRATEGIES.includes(strategy)) {
685
+ logErr(`Invalid strategy "${strategy}". Must be one of: ${VALID_STRATEGIES.join(", ")}`);
686
+ process.exit(1);
687
+ }
688
+ if (strategy === "passphrase" && !opts.passphrase && !process.env.SKAILE_SECRETS_PASSPHRASE) {
689
+ logErr(
690
+ "Passphrase required. Provide via --passphrase or set SKAILE_SECRETS_PASSPHRASE:\n export SKAILE_SECRETS_PASSPHRASE='...'\n skaile auth set-key-strategy passphrase"
691
+ );
692
+ process.exit(1);
693
+ }
694
+ const provider = new LocalSecretsProvider();
458
695
  try {
459
- const added = await am2.add(ref);
460
- spinner5.stop("Done");
461
- if (added.length === 0) {
462
- const kind = parseAssetRef(ref).kind;
463
- if (NON_DEPLOYABLE_KINDS.has(kind))
464
- logInfo(
465
- `Recorded in skaile.yaml. ${kind} assets are not deployed into the driver target \u2014 they are wired when skaile runs the agent.`
466
- );
467
- else logInfo("Nothing to deploy (already up to date).");
468
- } else for (const a of added) logOk(a);
469
- } catch (err) {
470
- spinner5.stop("Failed");
471
- logErr(String(err));
696
+ await provider.setKeyStrategy(strategy, opts.passphrase);
697
+ logOk(`Key strategy set to: ${strategy}`);
698
+ } catch (e) {
699
+ logErr(`Failed to set strategy: ${e instanceof Error ? e.message : String(e)}`);
472
700
  process.exit(1);
473
701
  }
474
702
  });
703
+ return cmd;
475
704
  }
476
- function makeRemoveCommand() {
477
- return new Command("remove").description("Remove from skaile.yaml + undeploy").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Remove from global dir").option("--target <agent>", "Driver target", "claude-code").action((ref, opts) => {
478
- const am2 = new AssetManager({
479
- projectDir: path13__default.resolve(opts.projectDir),
480
- global: opts.global,
481
- driverTarget: opts.target
482
- });
483
- const ok = am2.remove(ref);
484
- if (ok) logOk(`Removed ${ref}`);
485
- else logErr(`Not deployed: ${ref}`);
486
- });
705
+ function collectCacheTargets(scope) {
706
+ const out = [];
707
+ out.push(path14__default.join(scope.projectDir, ".skaile", "cache"));
708
+ out.push(path14__default.join(scope.projectDir, ".skaile", "store-cache"));
709
+ out.push(path14__default.join(scope.projectDir, ".skaile", "repos"));
710
+ if (scope.global) {
711
+ out.push(globalCacheRoot());
712
+ const home = process.env.SKAILE_HOME ?? path14__default.join(homedir(), ".skaile");
713
+ out.push(path14__default.join(home, "repos"));
714
+ out.push(path14__default.join(home, "catalog-cache"));
715
+ }
716
+ return out;
487
717
  }
488
- function makeListCommand() {
489
- return new Command("list").description("List deployed assets").argument("[kind]", "Filter by asset kind").option("--project-dir <path>", "Project directory", process.cwd()).option("-g, --global", "List global deployment").addOption(
490
- new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
491
- ).action((kind, opts) => {
492
- const am2 = new AssetManager({
493
- projectDir: path13__default.resolve(opts.projectDir),
494
- global: opts.global,
495
- driverTarget: opts.target
496
- });
497
- const deployed = am2.listDeployed(kind);
498
- if (deployed.length === 0) {
499
- logInfo("Nothing deployed.");
500
- return;
501
- }
502
- const kindW = Math.max(5, ...deployed.map((e) => e.kind.length));
503
- const nameW = Math.max(4, ...deployed.map((e) => e.name.length));
504
- console.log();
505
- console.log(` ${S.dim("KIND".padEnd(kindW))} ${S.dim("NAME".padEnd(nameW))}`);
506
- console.log(` ${S.rule(kindW + nameW + 4)}`);
507
- for (const e of deployed) {
508
- console.log(` ${kindColorPad(e.kind, kindW)} ${e.name.padEnd(nameW)}`);
509
- }
510
- console.log(`
511
- ${S.dim(`${deployed.length} deployed`)}
512
- `);
513
- });
718
+ function dirSize(target) {
719
+ if (!existsSync(target)) return 0;
720
+ const st = lstatSync(target);
721
+ if (st.isSymbolicLink()) return 0;
722
+ if (!st.isDirectory()) return st.size;
723
+ return dirSizeOfDir(target);
514
724
  }
515
- function makeInfoCommand() {
516
- return new Command("info").description("Show asset metadata, deps, deploy status").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
517
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
518
- const entry = am2.info(ref);
519
- if (!entry) {
520
- logErr(
521
- `'${ref}' not found. Run ${S.cmd("skaile source sync")} then ${S.cmd("skaile search")}.`
522
- );
523
- process.exit(1);
725
+ function dirSizeOfDir(dir) {
726
+ let total = 0;
727
+ for (const ent of readdirSync(dir, { withFileTypes: true })) {
728
+ const child = path14__default.join(dir, ent.name);
729
+ if (ent.isSymbolicLink()) continue;
730
+ if (ent.isDirectory()) total += dirSizeOfDir(child);
731
+ else if (ent.isFile()) total += statSync(child).size;
732
+ }
733
+ return total;
734
+ }
735
+ function removeCacheTargets(targets, opts) {
736
+ const present = targets.filter((t) => existsSync(t));
737
+ for (const t of present) rmSync(t, { recursive: true, force: true });
738
+ return present;
739
+ }
740
+ function fmtBytes(n) {
741
+ const u = ["B", "KB", "MB", "GB"];
742
+ let i = 0;
743
+ let v = n;
744
+ while (v >= 1024 && i < u.length - 1) {
745
+ v /= 1024;
746
+ i++;
747
+ }
748
+ return `${v.toFixed(i === 0 ? 0 : 1)} ${u[i]}`;
749
+ }
750
+ function makeCacheCommand() {
751
+ const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
752
+ cmd.command("clean").description("Remove the project cache (.skaile/cache); --global also clears ~/.skaile/cache").option("--global", "Also clear the global cache (sources + catalog) and legacy dirs").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
753
+ const targets = collectCacheTargets({
754
+ projectDir: path14__default.resolve(opts.projectDir),
755
+ global: opts.global
756
+ }).filter((t) => existsSync(t));
757
+ if (targets.length === 0) {
758
+ logInfo("Cache is already empty.");
759
+ return;
524
760
  }
525
761
  console.log();
526
- console.log(` ${S.heading(entry.name)}`);
527
- console.log(` ${S.rule(40)}`);
528
- console.log(` kind: ${kindColor(entry.kind)}`);
529
- if (entry.version) console.log(` version: ${entry.version}`);
530
- if (entry.description) console.log(` description: ${entry.description}`);
531
- if (entry.publisher) console.log(` repository: ${S.dim(entry.publisher)}`);
532
- console.log(` source: ${S.dim(entry.source)}`);
533
- if (entry.requires.length) {
534
- console.log(` requires:`);
535
- for (const d of entry.requires)
536
- console.log(` ${S.dim("\xB7")} ${kindColor(d.kind)}:${d.name}`);
762
+ console.log(` ${S.heading("Will remove:")}`);
763
+ for (const t of targets)
764
+ console.log(` ${S.dim(t)} ${S.dim(`(${fmtBytes(dirSize(t))})`)}`);
765
+ if (opts.dryRun) {
766
+ console.log();
767
+ logInfo("Dry run \u2014 no changes made.");
768
+ return;
537
769
  }
538
- if (entry.dependencies.length) {
539
- console.log(` dependencies:`);
540
- for (const s of entry.dependencies) console.log(` ${S.dim("\xB7")} ${colorRef(s)}`);
770
+ if (!opts.yes) {
771
+ const ok = await p6.confirm({
772
+ message: opts.global ? "Clear project AND global cache?" : "Clear project cache?"
773
+ });
774
+ if (p6.isCancel(ok) || !ok) {
775
+ logInfo("Cancelled.");
776
+ return;
777
+ }
541
778
  }
779
+ const removed = removeCacheTargets(targets);
542
780
  console.log();
781
+ for (const r of removed) logOk(`Removed ${r}`);
543
782
  });
544
- }
545
- function makeCreateCommand() {
546
- return new Command("create").description("Scaffold a new asset").argument("<name>", "Asset name").addOption(
547
- new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...ASSET_KINDS])
548
- ).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
549
- const am2 = new AssetManager({ projectDir: process.cwd() });
550
- const destDir = opts.dir ? path13__default.resolve(opts.dir) : process.cwd();
551
- const result = am2.create(name, opts.kind, destDir);
552
- if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
553
- else {
554
- logErr(result.path);
555
- process.exit(1);
556
- }
783
+ cmd.command("dir").description("Print the resolved cache roots").option("--global", "Include the global cache root").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
784
+ console.log(path14__default.join(path14__default.resolve(opts.projectDir), ".skaile", "cache"));
785
+ if (opts.global) console.log(globalCacheRoot());
557
786
  });
558
- }
559
- function makeDoctorCommand() {
560
- return new Command("doctor").description("Scan for missing dependency chains").argument("[name]", "Check a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((name, opts) => {
561
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
562
- const issues = am2.doctor();
563
- if (issues.length === 0) {
564
- logOk("No missing dependencies.");
565
- return;
566
- }
567
- const assetW = Math.max(5, ...issues.map((i) => `${i.assetKind}:${i.assetName}`.length));
568
- const depW = Math.max(11, ...issues.map((i) => `${i.depKind}:${i.depName}`.length));
787
+ cmd.command("size").description("Show cache disk usage per directory").option("--global", "Include the global cache").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
788
+ const targets = collectCacheTargets({
789
+ projectDir: path14__default.resolve(opts.projectDir),
790
+ global: opts.global
791
+ });
569
792
  console.log();
570
- console.log(
571
- ` ${S.dim("ASSET".padEnd(assetW))} ${S.dim("MISSING DEP".padEnd(depW))} ${S.dim("IN REPOS")}`
572
- );
573
- console.log(` ${S.rule(assetW + depW + 15)}`);
574
- for (const i of issues) {
575
- const asset = `${i.assetKind}:${i.assetName}`;
576
- const dep = `${i.depKind}:${i.depName}`;
577
- const status4 = i.inRepos ? S.warn("fixable") : S.err("not found");
578
- console.log(` ${asset.padEnd(assetW)} ${dep.padEnd(depW)} ${status4}`);
793
+ for (const t of targets) {
794
+ if (!existsSync(t)) continue;
795
+ console.log(` ${S.dim(fmtBytes(dirSize(t)).padStart(9))} ${t}`);
579
796
  }
580
797
  console.log();
581
798
  });
799
+ return cmd;
582
800
  }
583
801
  function makeCatalogCommand() {
584
802
  const catalog = new Command("catalog").description("Catalog source health and configuration");
585
803
  catalog.command("test").description("Probe the configured catalog source and report status").option("--project-dir <path>", "Project directory (for project-level config overlay)").option("--url <url>", "Override the catalog URL for this probe").option("--force", "Probe the network even in air-gapped mode (cache_ttl: 0)").action(async (opts) => {
586
804
  const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
587
- const projectDir = opts.projectDir ? path13__default.resolve(opts.projectDir) : void 0;
805
+ const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : void 0;
588
806
  const cfg = resolveConfig({ projectDir });
589
807
  const baseUrl = opts.url ?? cfg.catalog.url;
590
808
  if (isLocalCatalogUrl(baseUrl)) {
@@ -602,7 +820,7 @@ function makeCatalogCommand() {
602
820
  });
603
821
  catalog.command("info").description("Print the resolved catalog configuration (url, framing, cacheTtlMs)").option("--project-dir <path>", "Project directory (for project-level config overlay)").action(async (opts) => {
604
822
  const { resolveConfig } = await import('../library/index.js');
605
- const projectDir = opts.projectDir ? path13__default.resolve(opts.projectDir) : void 0;
823
+ const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : void 0;
606
824
  const cfg = resolveConfig({ projectDir });
607
825
  console.log(`url: ${cfg.catalog.url}`);
608
826
  console.log(`framing: ${cfg.catalog.framing}`);
@@ -611,7 +829,7 @@ function makeCatalogCommand() {
611
829
  return catalog;
612
830
  }
613
831
  async function runLocalCatalogTest(projectDir) {
614
- const { resolveCatalogSource } = await import('../open-library-362BZ6OW.js');
832
+ const { resolveCatalogSource } = await import('../open-library-COHFCT4N.js');
615
833
  let resolved;
616
834
  try {
617
835
  resolved = await resolveCatalogSource({ projectDir });
@@ -744,8 +962,8 @@ function findFlowFile(flowId, priorityRoots = []) {
744
962
  for (const root of [...priorityRoots, ...aiResourceRoots()]) {
745
963
  for (const { dir } of assetSearchDirs(root, "flows")) {
746
964
  for (const ext of [".flow.yaml", ".flow.json", ".json"]) {
747
- const candidate = path13__default.join(dir, `${flowId}${ext}`);
748
- if (fs11__default.existsSync(candidate)) return candidate;
965
+ const candidate = path14__default.join(dir, `${flowId}${ext}`);
966
+ if (fs12__default.existsSync(candidate)) return candidate;
749
967
  }
750
968
  }
751
969
  }
@@ -755,7 +973,7 @@ function findSkills(domain) {
755
973
  const found = [];
756
974
  for (const root of aiResourceRoots()) {
757
975
  for (const { dir, domain: dirDomain } of assetSearchDirs(root, "skills")) {
758
- if (fs11__default.existsSync(dir)) walkSkills(dir, dirDomain, found);
976
+ if (fs12__default.existsSync(dir)) walkSkills(dir, dirDomain, found);
759
977
  }
760
978
  }
761
979
  const seen = /* @__PURE__ */ new Set();
@@ -768,11 +986,11 @@ function findSkills(domain) {
768
986
  return deduped;
769
987
  }
770
988
  function walkSkills(dir, domain, out) {
771
- for (const entry of fs11__default.readdirSync(dir, { withFileTypes: true })) {
772
- const full = path13__default.join(dir, entry.name);
989
+ for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
990
+ const full = path14__default.join(dir, entry.name);
773
991
  if (entry.isDirectory()) {
774
- const skillMd = path13__default.join(full, "SKILL.md");
775
- if (fs11__default.existsSync(skillMd)) {
992
+ const skillMd = path14__default.join(full, "SKILL.md");
993
+ if (fs12__default.existsSync(skillMd)) {
776
994
  out.push({ name: entry.name, path: full, skillPath: skillMd, domain });
777
995
  } else {
778
996
  walkSkills(full, domain, out);
@@ -800,10 +1018,10 @@ function resolveFlowIds() {
800
1018
  }
801
1019
  }
802
1020
  function resolveSessionIds(projectDir) {
803
- const sessionsDir = path13__default.join(projectDir, ".skaile", "sessions");
804
- if (!fs11__default.existsSync(sessionsDir)) return [];
1021
+ const sessionsDir = path14__default.join(projectDir, ".skaile", "sessions");
1022
+ if (!fs12__default.existsSync(sessionsDir)) return [];
805
1023
  try {
806
- return fs11__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
1024
+ return fs12__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
807
1025
  } catch {
808
1026
  return [];
809
1027
  }
@@ -919,7 +1137,7 @@ function printResolvedPathsSection(config) {
919
1137
  console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
920
1138
  }
921
1139
  async function showConfig(opts) {
922
- const projectDir = opts.projectDir ? path13__default.resolve(opts.projectDir) : process.cwd();
1140
+ const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
923
1141
  const config = await resolveSettings(projectDir);
924
1142
  const wsDefaults = collectWorkspaceDefaults(projectDir);
925
1143
  printEffectiveSection(config);
@@ -932,13 +1150,13 @@ function makeConfigCommand() {
932
1150
  const cmd = new Command("config").description("Manage personal config (.skaile/settings.json)");
933
1151
  cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
934
1152
  cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").action(async (key, opts) => {
935
- const projectDir = opts.projectDir ? path13__default.resolve(opts.projectDir) : process.cwd();
1153
+ const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
936
1154
  const config = await resolveSettings(projectDir);
937
1155
  const value = config[key];
938
1156
  console.log(value ?? S.dim("(not set)"));
939
1157
  });
940
1158
  cmd.command("set <key> <value>").description("Set a personal config value (driver, model, provider, apiKey.<provider>)").option("--project-dir <path>", "Project directory").option("--global", "Write to ~/.skaile/settings.json instead of project-local").action(async (key, value, opts) => {
941
- const projectDir = opts.projectDir ? path13__default.resolve(opts.projectDir) : process.cwd();
1159
+ const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
942
1160
  const isApiKey = key.startsWith(API_KEY_PREFIX);
943
1161
  if (!PERSONAL_KEYS.has(key) && !isApiKey) {
944
1162
  logErr(
@@ -1053,11 +1271,11 @@ function makeConnectCommand() {
1053
1271
  process.exitCode = 1;
1054
1272
  return;
1055
1273
  }
1056
- await new Promise((resolve4) => {
1274
+ await new Promise((resolve5) => {
1057
1275
  client.onMessage((event) => {
1058
1276
  console.log(formatEvent(event));
1059
1277
  if (event.type === "finished" || event.type === "debug_result") {
1060
- resolve4();
1278
+ resolve5();
1061
1279
  }
1062
1280
  });
1063
1281
  client.send(parsed);
@@ -1101,12 +1319,12 @@ function makeConnectCommand() {
1101
1319
  client.send(cmd);
1102
1320
  rl.prompt();
1103
1321
  });
1104
- await new Promise((resolve4) => {
1105
- rl.on("close", resolve4);
1322
+ await new Promise((resolve5) => {
1323
+ rl.on("close", resolve5);
1106
1324
  client.onDisconnect(() => {
1107
1325
  logErr("Server disconnected");
1108
1326
  rl.close();
1109
- resolve4();
1327
+ resolve5();
1110
1328
  });
1111
1329
  });
1112
1330
  await client.disconnect();
@@ -1188,15 +1406,15 @@ function parseOpArgs(args) {
1188
1406
  async function promptText(label, defaultVal) {
1189
1407
  const rl = createInterface({ input: process.stdin, output: process.stdout });
1190
1408
  const hint = defaultVal ? ` [${defaultVal}]` : "";
1191
- return new Promise((resolve4) => {
1409
+ return new Promise((resolve5) => {
1192
1410
  rl.question(` ${label}${hint}: `, (answer) => {
1193
1411
  rl.close();
1194
- resolve4(answer.trim() || defaultVal || "");
1412
+ resolve5(answer.trim() || defaultVal || "");
1195
1413
  });
1196
1414
  });
1197
1415
  }
1198
1416
  async function promptSecret(label) {
1199
- return new Promise((resolve4) => {
1417
+ return new Promise((resolve5) => {
1200
1418
  process.stdout.write(` ${label} (hidden): `);
1201
1419
  const stdin = process.stdin;
1202
1420
  stdin.setRawMode?.(true);
@@ -1209,7 +1427,7 @@ async function promptSecret(label) {
1209
1427
  stdin.pause();
1210
1428
  stdin.removeListener("data", onData);
1211
1429
  process.stdout.write("\n");
1212
- resolve4(value);
1430
+ resolve5(value);
1213
1431
  } else if (char === "") {
1214
1432
  process.exit(1);
1215
1433
  } else if (char === "\x7F") {
@@ -1256,8 +1474,8 @@ function makeConnectorCommand() {
1256
1474
  async (driver, opts) => {
1257
1475
  const { installNpmPackages } = await import('../connectors/index.js');
1258
1476
  const { scanDirectory, factoryAssetRoots, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
1259
- const projectDir = path13__default.resolve(opts.projectDir);
1260
- const yamlPath = path13__default.join(projectDir, "skaile.yaml");
1477
+ const projectDir = path14__default.resolve(opts.projectDir);
1478
+ const yamlPath = path14__default.join(projectDir, "skaile.yaml");
1261
1479
  if (!existsSync(yamlPath)) {
1262
1480
  logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
1263
1481
  process.exit(1);
@@ -1317,8 +1535,8 @@ ${installResult.output}`);
1317
1535
  );
1318
1536
  cmd.command("remove <id>").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Remove a connector from skaile.yaml by its instance ID").action(async (id, opts) => {
1319
1537
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
1320
- const projectDir = path13__default.resolve(opts.projectDir);
1321
- const yamlPath = path13__default.join(projectDir, "skaile.yaml");
1538
+ const projectDir = path14__default.resolve(opts.projectDir);
1539
+ const yamlPath = path14__default.join(projectDir, "skaile.yaml");
1322
1540
  if (!existsSync(yamlPath)) {
1323
1541
  logErr("No skaile.yaml found in current directory.");
1324
1542
  process.exit(1);
@@ -1335,7 +1553,7 @@ ${installResult.output}`);
1335
1553
  cmd.command("status [id]").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Connect and report health status for one or all connectors").action(async (id, opts) => {
1336
1554
  const res = await import('../connectors/index.js');
1337
1555
  res.registerBuiltinConnectors();
1338
- const projectDir = path13__default.resolve(opts.projectDir);
1556
+ const projectDir = path14__default.resolve(opts.projectDir);
1339
1557
  const declarations = res.loadConnectorDeclarations(projectDir);
1340
1558
  if (declarations.length === 0) {
1341
1559
  console.log("No connectors configured in skaile.yaml.");
@@ -1359,7 +1577,7 @@ ${installResult.output}`);
1359
1577
  await manager.disconnectAll();
1360
1578
  });
1361
1579
  cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
1362
- const projectDir = path13__default.resolve(opts.projectDir);
1580
+ const projectDir = path14__default.resolve(opts.projectDir);
1363
1581
  const manager = await connectConnectors(projectDir);
1364
1582
  try {
1365
1583
  console.log(JSON.stringify(manager.listConnectors(), null, 2));
@@ -1368,7 +1586,7 @@ ${installResult.output}`);
1368
1586
  }
1369
1587
  });
1370
1588
  cmd.command("sync [id]").description("Re-sync a filesystem-face connector or all of them (git pull, S3 refresh, etc.)").option("--all", "Sync all connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
1371
- const projectDir = path13__default.resolve(opts.projectDir);
1589
+ const projectDir = path14__default.resolve(opts.projectDir);
1372
1590
  const manager = await connectConnectors(projectDir);
1373
1591
  try {
1374
1592
  if (opts.all) {
@@ -1392,7 +1610,7 @@ ${installResult.output}`);
1392
1610
  }
1393
1611
  });
1394
1612
  cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
1395
- const projectDir = path13__default.resolve(opts.projectDir);
1613
+ const projectDir = path14__default.resolve(opts.projectDir);
1396
1614
  const manager = await connectConnectors(projectDir);
1397
1615
  try {
1398
1616
  if (!manager.has(id)) {
@@ -1407,7 +1625,7 @@ ${installResult.output}`);
1407
1625
  }
1408
1626
  });
1409
1627
  cmd.command("read <id> <resource-path>").description("Read content from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
1410
- const projectDir = path13__default.resolve(opts.projectDir);
1628
+ const projectDir = path14__default.resolve(opts.projectDir);
1411
1629
  const manager = await connectConnectors(projectDir);
1412
1630
  try {
1413
1631
  const content = await manager.read(id, resourcePath);
@@ -1417,7 +1635,7 @@ ${installResult.output}`);
1417
1635
  }
1418
1636
  });
1419
1637
  cmd.command("write <id> <resource-path> <content>").description("Write content to a connector at a path").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, content, opts) => {
1420
- const projectDir = path13__default.resolve(opts.projectDir);
1638
+ const projectDir = path14__default.resolve(opts.projectDir);
1421
1639
  const manager = await connectConnectors(projectDir);
1422
1640
  try {
1423
1641
  await manager.write(id, resourcePath, { data: content });
@@ -1427,7 +1645,7 @@ ${installResult.output}`);
1427
1645
  }
1428
1646
  });
1429
1647
  cmd.command("entries <id> [resource-path]").description("List entries in a connector (files, keys, rows, etc)").option("--project-dir <path>", "Workspace directory", process.cwd()).option("--recursive", "Include nested entries").option("--limit <n>", "Maximum entries to return", parsePositiveIntOption).action(async (id, resourcePath, opts) => {
1430
- const projectDir = path13__default.resolve(opts.projectDir);
1648
+ const projectDir = path14__default.resolve(opts.projectDir);
1431
1649
  const manager = await connectConnectors(projectDir);
1432
1650
  try {
1433
1651
  const entries = await manager.list(id, resourcePath, {
@@ -1440,7 +1658,7 @@ ${installResult.output}`);
1440
1658
  }
1441
1659
  });
1442
1660
  cmd.command("search <id> <query>").description("Search within a connector for matching content").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, query, opts) => {
1443
- const projectDir = path13__default.resolve(opts.projectDir);
1661
+ const projectDir = path14__default.resolve(opts.projectDir);
1444
1662
  const manager = await connectConnectors(projectDir);
1445
1663
  try {
1446
1664
  const results = await manager.search(id, query);
@@ -1450,7 +1668,7 @@ ${installResult.output}`);
1450
1668
  }
1451
1669
  });
1452
1670
  cmd.command("delete <id> <resource-path>").description("Delete an entry from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
1453
- const projectDir = path13__default.resolve(opts.projectDir);
1671
+ const projectDir = path14__default.resolve(opts.projectDir);
1454
1672
  const manager = await connectConnectors(projectDir);
1455
1673
  try {
1456
1674
  const ok = await manager.delete(id, resourcePath);
@@ -1460,7 +1678,7 @@ ${installResult.output}`);
1460
1678
  }
1461
1679
  });
1462
1680
  cmd.command("run <id> <op> [args...]").description("Run a custom adapter operation (e.g. git log, sqlite query)").option("--project-dir <path>", "Workspace directory", process.cwd()).allowUnknownOption().action(async (id, op, args, opts) => {
1463
- const projectDir = path13__default.resolve(opts.projectDir);
1681
+ const projectDir = path14__default.resolve(opts.projectDir);
1464
1682
  const manager = await connectConnectors(projectDir);
1465
1683
  try {
1466
1684
  if (!manager.has(id)) {
@@ -1495,17 +1713,17 @@ async function runDebugQuery(query, parentOpts, args) {
1495
1713
  process.exitCode = 1;
1496
1714
  return;
1497
1715
  }
1498
- await new Promise((resolve4) => {
1716
+ await new Promise((resolve5) => {
1499
1717
  const timeout = setTimeout(() => {
1500
1718
  logErr("Timeout: no debug_result received within 5s");
1501
1719
  process.exitCode = 1;
1502
- resolve4();
1720
+ resolve5();
1503
1721
  }, 5e3);
1504
1722
  client.onMessage((event) => {
1505
1723
  if (event.type !== "debug_result") return;
1506
1724
  clearTimeout(timeout);
1507
1725
  printDebugResult(query, event.data);
1508
- resolve4();
1726
+ resolve5();
1509
1727
  });
1510
1728
  client.send({ type: "debug", query, args });
1511
1729
  });
@@ -1569,7 +1787,7 @@ function envRecord() {
1569
1787
  async function buildDeployContext(projectDir) {
1570
1788
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
1571
1789
  const config = resolveSkWorkspaceConfig2(projectDir);
1572
- const workspaceId = config.name ?? path13__default.basename(projectDir);
1790
+ const workspaceId = config.name ?? path14__default.basename(projectDir);
1573
1791
  let log;
1574
1792
  try {
1575
1793
  const { createLogger } = await import('../core/logging.js');
@@ -1601,13 +1819,13 @@ async function ensureTargetsRegistered(projectDir) {
1601
1819
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
1602
1820
  const config = resolveSkWorkspaceConfig2(projectDir);
1603
1821
  if (config.plugins && config.plugins.length > 0) {
1604
- const { ensurePluginsLoaded } = await import('../plugin-store-RBCDBO7K.js');
1822
+ const { ensurePluginsLoaded } = await import('../plugin-store-UNENLB56.js');
1605
1823
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
1606
1824
  for (const f of result.failed) logWarn(f.error);
1607
1825
  }
1608
1826
  }
1609
1827
  async function runUp(opts) {
1610
- const projectDir = path13__default.resolve(opts.projectDir);
1828
+ const projectDir = path14__default.resolve(opts.projectDir);
1611
1829
  await ensureTargetsRegistered(projectDir);
1612
1830
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
1613
1831
  const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
@@ -1639,12 +1857,12 @@ async function runUp(opts) {
1639
1857
  await holdUntilSignal(handle, controller);
1640
1858
  }
1641
1859
  function holdUntilSignal(handle, controller) {
1642
- return new Promise((resolve4) => {
1860
+ return new Promise((resolve5) => {
1643
1861
  const onSig = () => {
1644
1862
  process.removeListener("SIGINT", onSig);
1645
1863
  controller.abort();
1646
1864
  logInfo("Stopping\u2026");
1647
- handle.stop().then(() => logOk("Stopped.")).catch((e) => logErr(`stop failed: ${e instanceof Error ? e.message : String(e)}`)).finally(() => resolve4());
1865
+ handle.stop().then(() => logOk("Stopped.")).catch((e) => logErr(`stop failed: ${e instanceof Error ? e.message : String(e)}`)).finally(() => resolve5());
1648
1866
  };
1649
1867
  process.on("SIGINT", onSig);
1650
1868
  });
@@ -1675,7 +1893,7 @@ async function restoreFromHandle(projectDir) {
1675
1893
  return { target, handle, ctx };
1676
1894
  }
1677
1895
  async function runDown(opts) {
1678
- const projectDir = path13__default.resolve(opts.projectDir);
1896
+ const projectDir = path14__default.resolve(opts.projectDir);
1679
1897
  const restored = await restoreFromHandle(projectDir);
1680
1898
  if (!restored) return;
1681
1899
  await restored.handle.stop();
@@ -1684,7 +1902,7 @@ async function runDown(opts) {
1684
1902
  logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
1685
1903
  }
1686
1904
  async function runStatus(opts) {
1687
- const projectDir = path13__default.resolve(opts.projectDir);
1905
+ const projectDir = path14__default.resolve(opts.projectDir);
1688
1906
  const restored = await restoreFromHandle(projectDir);
1689
1907
  if (!restored) return;
1690
1908
  const health = await restored.handle.health();
@@ -1698,7 +1916,7 @@ async function runStatus(opts) {
1698
1916
  console.log();
1699
1917
  }
1700
1918
  async function runLogs(opts) {
1701
- const projectDir = path13__default.resolve(opts.projectDir);
1919
+ const projectDir = path14__default.resolve(opts.projectDir);
1702
1920
  const restored = await restoreFromHandle(projectDir);
1703
1921
  if (!restored) return;
1704
1922
  if (!restored.handle.logs) {
@@ -1722,7 +1940,7 @@ function makeDeployCommand() {
1722
1940
  }
1723
1941
  function makeDiffCommand() {
1724
1942
  return new Command("diff").description("Show changes between deployed and source versions").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
1725
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
1943
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
1726
1944
  const result = am2.diff(ref);
1727
1945
  if (result === null) {
1728
1946
  logInfo("No differences (or asset not found).");
@@ -1775,7 +1993,7 @@ function makeFlowCommand() {
1775
1993
  function makeHistoryCommand() {
1776
1994
  const cmd = new Command("history").description("Show recent add/remove/update actions");
1777
1995
  cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
1778
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
1996
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
1779
1997
  const limit = parseInt(limitStr, 10) || 20;
1780
1998
  const entries = am2.history(limit);
1781
1999
  if (entries.length === 0) {
@@ -1795,7 +2013,7 @@ function makeHistoryCommand() {
1795
2013
  console.log();
1796
2014
  });
1797
2015
  cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
1798
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
2016
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
1799
2017
  am2.clearHistory();
1800
2018
  logOk("History cleared.");
1801
2019
  });
@@ -1808,12 +2026,12 @@ var MCP_SERVER_ENTRY = {
1808
2026
  env: {}
1809
2027
  };
1810
2028
  function pluginDir(projectDir) {
1811
- return path13__default.join(projectDir, ".claude", "plugins", "skaile");
2029
+ return path14__default.join(projectDir, ".claude", "plugins", "skaile");
1812
2030
  }
1813
2031
  async function readJsonStrict(p9) {
1814
2032
  let raw;
1815
2033
  try {
1816
- raw = await fs5.readFile(p9, "utf-8");
2034
+ raw = await fs6.readFile(p9, "utf-8");
1817
2035
  } catch {
1818
2036
  return null;
1819
2037
  }
@@ -1826,32 +2044,32 @@ async function readJsonStrict(p9) {
1826
2044
  }
1827
2045
  }
1828
2046
  async function writeJson(p9, value) {
1829
- await fs5.mkdir(path13__default.dirname(p9), { recursive: true });
1830
- await fs5.writeFile(p9, `${JSON.stringify(value, null, 2)}
2047
+ await fs6.mkdir(path14__default.dirname(p9), { recursive: true });
2048
+ await fs6.writeFile(p9, `${JSON.stringify(value, null, 2)}
1831
2049
  `);
1832
2050
  }
1833
2051
  async function copyDir(src, dest) {
1834
- await fs5.mkdir(dest, { recursive: true });
1835
- const entries = await fs5.readdir(src, { withFileTypes: true });
2052
+ await fs6.mkdir(dest, { recursive: true });
2053
+ const entries = await fs6.readdir(src, { withFileTypes: true });
1836
2054
  for (const entry of entries) {
1837
- const srcPath = path13__default.join(src, entry.name);
1838
- const destPath = path13__default.join(dest, entry.name);
2055
+ const srcPath = path14__default.join(src, entry.name);
2056
+ const destPath = path14__default.join(dest, entry.name);
1839
2057
  if (entry.isDirectory()) await copyDir(srcPath, destPath);
1840
- else await fs5.copyFile(srcPath, destPath);
2058
+ else await fs6.copyFile(srcPath, destPath);
1841
2059
  }
1842
2060
  }
1843
2061
  async function install(projectDir, opts) {
1844
2062
  return opts?.full ? installFullPlugin(projectDir) : installMcp(projectDir);
1845
2063
  }
1846
2064
  async function installMcp(projectDir) {
1847
- const mcpPath = path13__default.join(projectDir, ".claude", "mcp.json");
2065
+ const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
1848
2066
  const existing = await readJsonStrict(mcpPath) ?? {};
1849
2067
  const mcpServers = { ...existing.mcpServers ?? {} };
1850
2068
  const previous = mcpServers[SKAILE_MCP_NAME];
1851
2069
  const matches = previous && JSON.stringify(previous) === JSON.stringify(MCP_SERVER_ENTRY);
1852
2070
  let warning;
1853
2071
  if (previous && !matches) {
1854
- warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path13__default.relative(projectDir, mcpPath)}`;
2072
+ warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path14__default.relative(projectDir, mcpPath)}`;
1855
2073
  }
1856
2074
  mcpServers[SKAILE_MCP_NAME] = MCP_SERVER_ENTRY;
1857
2075
  await writeJson(mcpPath, { ...existing, mcpServers });
@@ -1860,15 +2078,15 @@ async function installMcp(projectDir) {
1860
2078
  async function installFullPlugin(projectDir) {
1861
2079
  const dir = pluginDir(projectDir);
1862
2080
  for (const [rel, content] of Object.entries(buildClaudePluginFiles())) {
1863
- const dest = path13__default.join(dir, rel);
1864
- await fs5.mkdir(path13__default.dirname(dest), { recursive: true });
1865
- await fs5.writeFile(dest, content);
2081
+ const dest = path14__default.join(dir, rel);
2082
+ await fs6.mkdir(path14__default.dirname(dest), { recursive: true });
2083
+ await fs6.writeFile(dest, content);
1866
2084
  }
1867
- const projectSkillsDir = path13__default.join(projectDir, ".skaile", "skills");
2085
+ const projectSkillsDir = path14__default.join(projectDir, ".skaile", "skills");
1868
2086
  if (existsSync(projectSkillsDir)) {
1869
- await copyDir(projectSkillsDir, path13__default.join(dir, "skills"));
2087
+ await copyDir(projectSkillsDir, path14__default.join(dir, "skills"));
1870
2088
  }
1871
- const settingsPath = path13__default.join(projectDir, ".claude", "settings.json");
2089
+ const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
1872
2090
  const settings = await readJsonStrict(settingsPath) ?? {};
1873
2091
  const plugins = settings.plugins ?? [];
1874
2092
  if (!plugins.includes(dir)) plugins.push(dir);
@@ -1876,8 +2094,8 @@ async function installFullPlugin(projectDir) {
1876
2094
  return { changed: true, method: "plugin" };
1877
2095
  }
1878
2096
  async function uninstall(projectDir) {
1879
- const settingsPath = path13__default.join(projectDir, ".claude", "settings.json");
1880
- const mcpPath = path13__default.join(projectDir, ".claude", "mcp.json");
2097
+ const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
2098
+ const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
1881
2099
  const dir = pluginDir(projectDir);
1882
2100
  let changed = false;
1883
2101
  const settings = await readJsonStrict(settingsPath);
@@ -1891,7 +2109,7 @@ async function uninstall(projectDir) {
1891
2109
  }
1892
2110
  }
1893
2111
  if (existsSync(dir)) {
1894
- await fs5.rm(dir, { recursive: true, force: true });
2112
+ await fs6.rm(dir, { recursive: true, force: true });
1895
2113
  changed = true;
1896
2114
  }
1897
2115
  const mcp = await readJsonStrict(mcpPath);
@@ -1901,7 +2119,7 @@ async function uninstall(projectDir) {
1901
2119
  const updated = { ...mcp, mcpServers: rest };
1902
2120
  if (Object.keys(rest).length === 0) delete updated.mcpServers;
1903
2121
  if (Object.keys(updated).length === 0) {
1904
- await fs5.unlink(mcpPath);
2122
+ await fs6.unlink(mcpPath);
1905
2123
  } else {
1906
2124
  await writeJson(mcpPath, updated);
1907
2125
  }
@@ -1911,12 +2129,12 @@ async function uninstall(projectDir) {
1911
2129
  async function detectInstall(projectDir) {
1912
2130
  const dir = pluginDir(projectDir);
1913
2131
  const settings = await readJsonStrict(
1914
- path13__default.join(projectDir, ".claude", "settings.json")
2132
+ path14__default.join(projectDir, ".claude", "settings.json")
1915
2133
  );
1916
- if (existsSync(path13__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
2134
+ if (existsSync(path14__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
1917
2135
  return { method: "plugin", pluginPath: dir };
1918
2136
  }
1919
- const mcp = await readJsonStrict(path13__default.join(projectDir, ".claude", "mcp.json"));
2137
+ const mcp = await readJsonStrict(path14__default.join(projectDir, ".claude", "mcp.json"));
1920
2138
  if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
1921
2139
  return { method: "mcp" };
1922
2140
  }
@@ -1925,7 +2143,7 @@ async function detectInstall(projectDir) {
1925
2143
  async function enable(projectDir) {
1926
2144
  const detected = await detectInstall(projectDir);
1927
2145
  if (!detected) throw new Error("plugin not installed for claude-code");
1928
- const settingsPath = path13__default.join(projectDir, ".claude", "settings.json");
2146
+ const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
1929
2147
  const settings = await readJsonStrict(settingsPath) ?? {};
1930
2148
  if (detected.method === "plugin") {
1931
2149
  const disabled2 = settings.disabledPlugins ?? [];
@@ -1947,7 +2165,7 @@ async function enable(projectDir) {
1947
2165
  async function disable(projectDir) {
1948
2166
  const detected = await detectInstall(projectDir);
1949
2167
  if (!detected) throw new Error("plugin not installed for claude-code");
1950
- const settingsPath = path13__default.join(projectDir, ".claude", "settings.json");
2168
+ const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
1951
2169
  const settings = await readJsonStrict(settingsPath) ?? {};
1952
2170
  if (detected.method === "plugin") {
1953
2171
  const list2 = settings.disabledPlugins ?? [];
@@ -1967,12 +2185,12 @@ async function disable(projectDir) {
1967
2185
  return { changed: true };
1968
2186
  }
1969
2187
  async function status(projectDir) {
1970
- const settingsPath = path13__default.join(projectDir, ".claude", "settings.json");
1971
- const mcpPath = path13__default.join(projectDir, ".claude", "mcp.json");
2188
+ const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
2189
+ const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
1972
2190
  const dir = pluginDir(projectDir);
1973
2191
  const settings = await readJsonStrict(settingsPath);
1974
2192
  const mcp = await readJsonStrict(mcpPath);
1975
- const pluginInstalled = !!(existsSync(path13__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
2193
+ const pluginInstalled = !!(existsSync(path14__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
1976
2194
  const mcpInstalled = !!(mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers);
1977
2195
  if (!pluginInstalled && !mcpInstalled) {
1978
2196
  return {
@@ -1990,7 +2208,7 @@ async function status(projectDir) {
1990
2208
  installed: "yes",
1991
2209
  enabled: disabled2 ? "no" : "yes",
1992
2210
  method: "plugin",
1993
- location: path13__default.relative(projectDir, dir)
2211
+ location: path14__default.relative(projectDir, dir)
1994
2212
  };
1995
2213
  }
1996
2214
  const disabled = settings?.disabledMcpjsonServers?.includes(SKAILE_MCP_NAME) ?? false;
@@ -1999,7 +2217,7 @@ async function status(projectDir) {
1999
2217
  installed: "yes",
2000
2218
  enabled: disabled ? "no" : "yes",
2001
2219
  method: "mcp",
2002
- location: path13__default.relative(projectDir, mcpPath)
2220
+ location: path14__default.relative(projectDir, mcpPath)
2003
2221
  };
2004
2222
  }
2005
2223
  var SKAILE_MCP_NAME2 = "skaile-workspace";
@@ -2013,7 +2231,7 @@ function buildEntry(projectDir) {
2013
2231
  async function readConfig(p9) {
2014
2232
  let raw;
2015
2233
  try {
2016
- raw = await fs5.readFile(p9, "utf-8");
2234
+ raw = await fs6.readFile(p9, "utf-8");
2017
2235
  } catch {
2018
2236
  return null;
2019
2237
  }
@@ -2026,16 +2244,16 @@ async function readConfig(p9) {
2026
2244
  }
2027
2245
  }
2028
2246
  async function writeConfig(p9, value) {
2029
- await fs5.mkdir(path13__default.dirname(p9), { recursive: true });
2247
+ await fs6.mkdir(path14__default.dirname(p9), { recursive: true });
2030
2248
  const cleaned = {};
2031
2249
  for (const [k, v] of Object.entries(value)) {
2032
2250
  if (v === void 0) continue;
2033
2251
  cleaned[k] = v;
2034
2252
  }
2035
- await fs5.writeFile(p9, stringify(cleaned));
2253
+ await fs6.writeFile(p9, stringify$1(cleaned));
2036
2254
  }
2037
2255
  function configPath(projectDir) {
2038
- return path13__default.join(projectDir, ".codex", "config.toml");
2256
+ return path14__default.join(projectDir, ".codex", "config.toml");
2039
2257
  }
2040
2258
  async function install2(projectDir) {
2041
2259
  const p9 = configPath(projectDir);
@@ -2046,7 +2264,7 @@ async function install2(projectDir) {
2046
2264
  const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
2047
2265
  let warning;
2048
2266
  if (previous && !matches) {
2049
- warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path13__default.relative(projectDir, p9)}`;
2267
+ warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path14__default.relative(projectDir, p9)}`;
2050
2268
  }
2051
2269
  if (matches) return { changed: false, method: "toml" };
2052
2270
  servers[SKAILE_MCP_NAME2] = next;
@@ -2063,7 +2281,7 @@ async function uninstall2(projectDir) {
2063
2281
  const updated = { ...cfg, mcp_servers: rest };
2064
2282
  if (Object.keys(rest).length === 0) delete updated.mcp_servers;
2065
2283
  if (Object.keys(updated).length === 0) {
2066
- await fs5.unlink(p9);
2284
+ await fs6.unlink(p9);
2067
2285
  } else {
2068
2286
  await writeConfig(p9, updated);
2069
2287
  }
@@ -2087,43 +2305,43 @@ async function status2(projectDir) {
2087
2305
  installed: "yes",
2088
2306
  enabled: "n/a",
2089
2307
  method: "mcp",
2090
- location: path13__default.relative(projectDir, p9)
2308
+ location: path14__default.relative(projectDir, p9)
2091
2309
  };
2092
2310
  }
2093
2311
  async function install3(projectDir) {
2094
- const extDir = path13__default.join(projectDir, ".omp", "extensions");
2095
- const extPath = path13__default.join(extDir, "skaile.ts");
2096
- await fs5.mkdir(extDir, { recursive: true });
2312
+ const extDir = path14__default.join(projectDir, ".omp", "extensions");
2313
+ const extPath = path14__default.join(extDir, "skaile.ts");
2314
+ await fs6.mkdir(extDir, { recursive: true });
2097
2315
  const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
2098
2316
  const plugin = new WorkspacePlugin({ projectDir });
2099
2317
  const nextSrc = await plugin.buildOmpExtensionSource();
2100
2318
  let prevSrc = null;
2101
2319
  try {
2102
- prevSrc = await fs5.readFile(extPath, "utf-8");
2320
+ prevSrc = await fs6.readFile(extPath, "utf-8");
2103
2321
  } catch {
2104
2322
  }
2105
2323
  if (prevSrc === nextSrc) return { changed: false, method: "generated" };
2106
- await fs5.writeFile(extPath, nextSrc);
2324
+ await fs6.writeFile(extPath, nextSrc);
2107
2325
  return { changed: true, method: "generated" };
2108
2326
  }
2109
2327
  async function uninstall3(projectDir) {
2110
- const extPath = path13__default.join(projectDir, ".omp", "extensions", "skaile.ts");
2328
+ const extPath = path14__default.join(projectDir, ".omp", "extensions", "skaile.ts");
2111
2329
  try {
2112
- await fs5.unlink(extPath);
2330
+ await fs6.unlink(extPath);
2113
2331
  return { changed: true };
2114
2332
  } catch {
2115
2333
  return { changed: false };
2116
2334
  }
2117
2335
  }
2118
2336
  async function status3(projectDir) {
2119
- const extPath = path13__default.join(projectDir, ".omp", "extensions", "skaile.ts");
2337
+ const extPath = path14__default.join(projectDir, ".omp", "extensions", "skaile.ts");
2120
2338
  if (existsSync(extPath)) {
2121
2339
  return {
2122
2340
  backend: "omp",
2123
2341
  installed: "yes",
2124
2342
  enabled: "n/a",
2125
2343
  method: "extension",
2126
- location: path13__default.relative(projectDir, extPath)
2344
+ location: path14__default.relative(projectDir, extPath)
2127
2345
  };
2128
2346
  }
2129
2347
  return {
@@ -2186,7 +2404,7 @@ async function installCodex(projectDir) {
2186
2404
  console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
2187
2405
  }
2188
2406
  async function runInstall(opts) {
2189
- const projectDir = path13__default.resolve(opts.projectDir);
2407
+ const projectDir = path14__default.resolve(opts.projectDir);
2190
2408
  const targets = resolveDriver(opts.driver);
2191
2409
  let exitCode = 0;
2192
2410
  if (targets.includes("claude-code")) {
@@ -2220,7 +2438,7 @@ async function uninstallCodex(projectDir) {
2220
2438
  else logInfo(`codex: not installed`);
2221
2439
  }
2222
2440
  async function runUninstall(opts) {
2223
- const projectDir = path13__default.resolve(opts.projectDir);
2441
+ const projectDir = path14__default.resolve(opts.projectDir);
2224
2442
  const targets = resolveDriver(opts.driver);
2225
2443
  let exitCode = 0;
2226
2444
  if (targets.includes("claude-code")) {
@@ -2263,7 +2481,7 @@ async function toggleTarget(t, projectDir, action3) {
2263
2481
  });
2264
2482
  }
2265
2483
  async function runToggle(opts, action3) {
2266
- const projectDir = path13__default.resolve(opts.projectDir);
2484
+ const projectDir = path14__default.resolve(opts.projectDir);
2267
2485
  const requestedAll = opts.driver === "all";
2268
2486
  const targets = resolveDriver(opts.driver);
2269
2487
  const usageError = checkToggleSupported(targets, requestedAll, action3);
@@ -2275,7 +2493,7 @@ async function runToggle(opts, action3) {
2275
2493
  return exitCode;
2276
2494
  }
2277
2495
  async function runStatus2(opts) {
2278
- const projectDir = path13__default.resolve(opts.projectDir);
2496
+ const projectDir = path14__default.resolve(opts.projectDir);
2279
2497
  const targets = resolveDriver(opts.driver);
2280
2498
  const rows = [];
2281
2499
  let exitCode = 0;
@@ -2346,7 +2564,7 @@ async function runHook(event) {
2346
2564
  await plugin.shutdown();
2347
2565
  return;
2348
2566
  }
2349
- const store = new PluginStore(path13__default.join(projectDir, ".skaile", "plugin-state.json"));
2567
+ const store = new PluginStore(path14__default.join(projectDir, ".skaile", "plugin-state.json"));
2350
2568
  await store.load();
2351
2569
  const status4 = store.get("connector:status");
2352
2570
  if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
@@ -2468,12 +2686,12 @@ function makeLibraryCommand() {
2468
2686
  cmd.command("init <name>").description("Create a new local library at ~/.skaile/libraries/<name>").option("--git <url>", "Initialize as a git library tracking <url>").option("--owner", "Mark as owner (default for local)").option("--contributor", "Mark as contributor").option("--reader", "Mark as reader").action(
2469
2687
  async (name, opts) => {
2470
2688
  const libDir = resolveLibraryDir();
2471
- const libPath = path13.join(libDir, name);
2689
+ const libPath = path14.join(libDir, name);
2472
2690
  const ownership = opts.contributor ? "contributor" : opts.reader ? "reader" : "owner";
2473
2691
  const { manager, close } = await openLibraryManager();
2474
2692
  try {
2475
2693
  if (opts.git) {
2476
- fs11.mkdirSync(libPath, { recursive: true });
2694
+ fs12.mkdirSync(libPath, { recursive: true });
2477
2695
  await manager.addLibrary({
2478
2696
  name,
2479
2697
  path: libPath,
@@ -2482,7 +2700,7 @@ function makeLibraryCommand() {
2482
2700
  ownership
2483
2701
  });
2484
2702
  } else {
2485
- fs11.mkdirSync(libPath, { recursive: true });
2703
+ fs12.mkdirSync(libPath, { recursive: true });
2486
2704
  await manager.addLibrary({
2487
2705
  name,
2488
2706
  path: libPath,
@@ -2539,7 +2757,7 @@ function makeLibraryCommand() {
2539
2757
  target = def;
2540
2758
  }
2541
2759
  const am2 = new AssetManager({ projectDir: process.cwd() });
2542
- const destDir = opts.dir ? path13.join(target.path, opts.dir) : target.path;
2760
+ const destDir = opts.dir ? path14.join(target.path, opts.dir) : target.path;
2543
2761
  const res = am2.create(name, opts.kind ?? kind, destDir);
2544
2762
  if (res.ok) {
2545
2763
  logOk(`Created ${opts.kind ?? kind}: ${pc5.dim(res.path)}`);
@@ -2552,6 +2770,80 @@ function makeLibraryCommand() {
2552
2770
  }
2553
2771
  }
2554
2772
  );
2773
+ const domain = cmd.command("domain").description("Manage domains (publisher namespaces) inside a library");
2774
+ async function resolveTargetLibrary(manager, libraryName) {
2775
+ if (libraryName) return manager.requireLibrary(libraryName);
2776
+ const all = await manager.listLibraries();
2777
+ const def = all.find((l) => l.isDefault);
2778
+ if (def) return def;
2779
+ if (all.length === 1) return all[0];
2780
+ if (all.length === 0) {
2781
+ logErr("No libraries registered. Run `skaile library init <name>` first.");
2782
+ process.exit(1);
2783
+ }
2784
+ logErr("No default library set. Run `skaile library default <name>` or pass --library.");
2785
+ process.exit(1);
2786
+ }
2787
+ domain.command("create <name>").description("Scaffold a domain dir + DOMAIN.md inside a library").option("--library <name>", "Target library (default: the default-marked one)").option("--publisher <p>", "Publisher slug (default: the domain name kebab-cased)").option("--description <text>", "Domain description for DOMAIN.md").action(
2788
+ async (name, opts) => {
2789
+ const { manager, close } = await openLibraryManager();
2790
+ try {
2791
+ const target = await resolveTargetLibrary(manager, opts.library);
2792
+ if (target.ownership === "reader") {
2793
+ logErr(`Library "${target.name}" is read-only (ownership=reader).`);
2794
+ process.exit(1);
2795
+ }
2796
+ const res = ensureDomain(target.path, name, {
2797
+ publisher: opts.publisher,
2798
+ description: opts.description
2799
+ });
2800
+ if (target.structure !== "domain") {
2801
+ await manager.updateLibrary(target.id, { structure: "domain" });
2802
+ }
2803
+ if (res.created) {
2804
+ logOk(`Created domain ${S.cmd(name)} (publisher @${res.publisher}) \u2192 ${res.dir}`);
2805
+ } else {
2806
+ logInfo(`Domain ${S.cmd(name)} already exists at ${res.dir}`);
2807
+ }
2808
+ } finally {
2809
+ close();
2810
+ }
2811
+ }
2812
+ );
2813
+ domain.command("list").description("List domains in a library").option("--library <name>", "Target library (default: the default-marked one)").option("--json", "Output as JSON").action(async (opts) => {
2814
+ const { manager, close } = await openLibraryManager();
2815
+ try {
2816
+ const target = await resolveTargetLibrary(manager, opts.library);
2817
+ const domains = listDomains(target.path);
2818
+ if (opts.json) return console.log(JSON.stringify(domains, null, 2));
2819
+ if (domains.length === 0) {
2820
+ logInfo(
2821
+ `No domains in "${target.name}". Create one: \`skaile library domain create <name>\`.`
2822
+ );
2823
+ return;
2824
+ }
2825
+ for (const d of domains) console.log(` ${S.cmd(d)}`);
2826
+ console.log(`
2827
+ ${S.dim(`${domains.length} domain(s) in ${target.name}`)}
2828
+ `);
2829
+ } finally {
2830
+ close();
2831
+ }
2832
+ });
2833
+ domain.command("show <name>").description("Print a domain's DOMAIN.md").option("--library <name>", "Target library (default: the default-marked one)").action(async (name, opts) => {
2834
+ const { manager, close } = await openLibraryManager();
2835
+ try {
2836
+ const target = await resolveTargetLibrary(manager, opts.library);
2837
+ const domainFile = path14.join(target.path, name, "DOMAIN.md");
2838
+ if (!existsSync(domainFile)) {
2839
+ logErr(`Domain "${name}" not found in "${target.name}" (no ${domainFile}).`);
2840
+ process.exit(1);
2841
+ }
2842
+ console.log(fs12.readFileSync(domainFile, "utf8"));
2843
+ } finally {
2844
+ close();
2845
+ }
2846
+ });
2555
2847
  cmd.command("default <name>").description("Set <name> as the default library").action(async (name) => {
2556
2848
  const { manager, close } = await openLibraryManager();
2557
2849
  try {
@@ -2565,13 +2857,13 @@ function makeLibraryCommand() {
2565
2857
  const { manager, close } = await openLibraryManager();
2566
2858
  try {
2567
2859
  const lib = await manager.requireLibrary(oldName);
2568
- const parent = path13.dirname(lib.path);
2569
- const newPath = path13.join(parent, newName);
2570
- if (fs11.existsSync(newPath)) {
2860
+ const parent = path14.dirname(lib.path);
2861
+ const newPath = path14.join(parent, newName);
2862
+ if (fs12.existsSync(newPath)) {
2571
2863
  logErr(`Target directory already exists: ${newPath}`);
2572
2864
  process.exit(1);
2573
2865
  }
2574
- fs11.renameSync(lib.path, newPath);
2866
+ fs12.renameSync(lib.path, newPath);
2575
2867
  await manager.updateLibrary(lib.id, { name: newName, path: newPath });
2576
2868
  logOk(`Renamed ${oldName} \u2192 ${newName}`);
2577
2869
  } finally {
@@ -2755,9 +3047,9 @@ async function printOverallStatus(projectDir, asJson) {
2755
3047
  } catch {
2756
3048
  secretsStrategy = "unavailable";
2757
3049
  }
2758
- const resolvedProjectDir = path13.resolve(projectDir);
2759
- const hasWorkspaceConfig = existsSync(path13.join(resolvedProjectDir, "skaile.yaml"));
2760
- const hasLockFile = existsSync(path13.join(resolvedProjectDir, "skaile.lock.yaml"));
3050
+ const resolvedProjectDir = path14.resolve(projectDir);
3051
+ const hasWorkspaceConfig = existsSync(path14.join(resolvedProjectDir, "skaile.yaml"));
3052
+ const hasLockFile = existsSync(path14.join(resolvedProjectDir, "skaile.lock.yaml"));
2761
3053
  let assignments = [];
2762
3054
  if (hasWorkspaceConfig) {
2763
3055
  try {
@@ -3113,7 +3405,7 @@ function actOnHeader(row, action3) {
3113
3405
  return row.type === "domain-header" || row.type === "domain-info";
3114
3406
  }
3115
3407
  async function loadAssets() {
3116
- const { gatherAssetFeeds } = await import('../asset-feeds-EGSG4FUB.js');
3408
+ const { gatherAssetFeeds } = await import('../asset-feeds-DLRQWELS.js');
3117
3409
  const { entries, domains, notes } = await gatherAssetFeeds(am, am.projectDir);
3118
3410
  if (notes.length > 0) {
3119
3411
  state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
@@ -3211,14 +3503,14 @@ function reconcileCollapsedSets(rows) {
3211
3503
  async function loadSourcesAndLibraries() {
3212
3504
  try {
3213
3505
  const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir }, { getGlobalCacheDir: getGlobalCacheDir2 }] = await Promise.all([
3214
- import('../open-library-362BZ6OW.js'),
3506
+ import('../open-library-COHFCT4N.js'),
3215
3507
  import('../library/index.js'),
3216
3508
  import('../core/index.js')
3217
3509
  ]);
3218
3510
  const { manager, library, close } = await openLibraryManager2();
3219
3511
  try {
3220
3512
  const newRoot = getGlobalCacheDir2();
3221
- const legacyRoot = path13__default.join(skaileHomeDir(), "sources");
3513
+ const legacyRoot = path14__default.join(skaileHomeDir(), "sources");
3222
3514
  const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
3223
3515
  const libs = await manager.listLibraries();
3224
3516
  const defs = await library.listAssetDefs();
@@ -3598,10 +3890,10 @@ async function showInfo() {
3598
3890
  }
3599
3891
  console.log();
3600
3892
  console.log(pc5.dim(" Press any key to return..."));
3601
- await new Promise((resolve4) => {
3893
+ await new Promise((resolve5) => {
3602
3894
  const onData = () => {
3603
3895
  process.stdin.removeListener("data", onData);
3604
- resolve4();
3896
+ resolve5();
3605
3897
  };
3606
3898
  process.stdin.once("data", onData);
3607
3899
  });
@@ -3854,13 +4146,13 @@ async function run(projectDir) {
3854
4146
  }
3855
4147
  function makeManageCommand() {
3856
4148
  return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
3857
- await run(path13__default.resolve(opts.projectDir));
4149
+ await run(path14__default.resolve(opts.projectDir));
3858
4150
  });
3859
4151
  }
3860
4152
  function makeMcpServerCommand() {
3861
4153
  return new Command("mcp-server").description("Start skaile workspace MCP server (stdio transport)").option("--project-dir <path>", "Project directory (default: cwd)", process.cwd()).action(async (opts) => {
3862
- const path36 = await import('path');
3863
- const projectDir = path36.default.resolve(opts.projectDir);
4154
+ const path37 = await import('path');
4155
+ const projectDir = path37.default.resolve(opts.projectDir);
3864
4156
  const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
3865
4157
  registerLogStore(
3866
4158
  new LogStore({
@@ -3897,8 +4189,8 @@ function makeNpxCommand() {
3897
4189
  skills.command("add <url>").description(
3898
4190
  "Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
3899
4191
  ).requiredOption("--skill <name>", "Skill name to install from the repo").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").option("--global", "Deploy globally").action(async (url, opts) => {
3900
- const projectDir = path13__default.resolve(opts.projectDir);
3901
- const projYaml = path13__default.join(projectDir, "skaile.yaml");
4192
+ const projectDir = path14__default.resolve(opts.projectDir);
4193
+ const projYaml = path14__default.join(projectDir, "skaile.yaml");
3902
4194
  if (!existsSync(projYaml)) {
3903
4195
  logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
3904
4196
  process.exit(1);
@@ -3910,14 +4202,15 @@ function makeNpxCommand() {
3910
4202
  process.exit(1);
3911
4203
  }
3912
4204
  const spinner5 = p6.spinner();
3913
- const slug = sourceSlug(url);
3914
- const clonePath = path13__default.join(getGlobalCacheDir(), slug);
4205
+ const key = sourceCacheKey(url);
4206
+ const clonePath = path14__default.join(getGlobalCacheDir(), key);
3915
4207
  spinner5.start(`Cloning ${url}`);
3916
4208
  try {
3917
4209
  if (!existsSync(clonePath)) {
4210
+ mkdirSync(path14__default.dirname(clonePath), { recursive: true });
3918
4211
  execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
3919
4212
  }
3920
- spinner5.stop(`Cloned to ${slug}`);
4213
+ spinner5.stop(`Cloned to ${key}`);
3921
4214
  } catch (err) {
3922
4215
  spinner5.stop("Clone failed");
3923
4216
  logErr(err instanceof Error ? err.message : String(err));
@@ -3960,7 +4253,7 @@ function makeNpxCommand() {
3960
4253
  return npx;
3961
4254
  }
3962
4255
  function resolvePublisher(clonePath, url) {
3963
- const manifestPath = path13__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
4256
+ const manifestPath = path14__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
3964
4257
  if (existsSync(manifestPath)) {
3965
4258
  try {
3966
4259
  const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
@@ -3973,12 +4266,12 @@ function resolvePublisher(clonePath, url) {
3973
4266
  return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
3974
4267
  }
3975
4268
  function resolveSkillName(clonePath, requested) {
3976
- const skillsDir = path13__default.join(clonePath, "skills");
3977
- if (existsSync(path13__default.join(skillsDir, requested, "SKILL.md"))) return requested;
4269
+ const skillsDir = path14__default.join(clonePath, "skills");
4270
+ if (existsSync(path14__default.join(skillsDir, requested, "SKILL.md"))) return requested;
3978
4271
  if (!existsSync(skillsDir)) return requested;
3979
4272
  for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
3980
4273
  if (!entry.isDirectory()) continue;
3981
- const md = path13__default.join(skillsDir, entry.name, "SKILL.md");
4274
+ const md = path14__default.join(skillsDir, entry.name, "SKILL.md");
3982
4275
  if (!existsSync(md)) continue;
3983
4276
  try {
3984
4277
  const { data } = parseFrontmatter(readFileSync(md, "utf8"));
@@ -3988,15 +4281,12 @@ function resolveSkillName(clonePath, requested) {
3988
4281
  }
3989
4282
  return requested;
3990
4283
  }
3991
- function sourceSlug(url) {
3992
- return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
3993
- }
3994
4284
  function makeOutdatedCommand() {
3995
4285
  return new Command("outdated").description("Check for assets behind their repo").argument("[name]", "Check a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).addOption(
3996
4286
  new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
3997
4287
  ).action((name, opts) => {
3998
4288
  const am2 = new AssetManager({
3999
- projectDir: path13__default.resolve(opts.projectDir),
4289
+ projectDir: path14__default.resolve(opts.projectDir),
4000
4290
  driverTarget: opts.target
4001
4291
  });
4002
4292
  const entries = am2.outdated();
@@ -4025,7 +4315,7 @@ function makeOutdatedCommand() {
4025
4315
  function makePatchCommand() {
4026
4316
  const cmd = new Command("patch").description("Patch workflow for skill improvement");
4027
4317
  cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
4028
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
4318
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
4029
4319
  try {
4030
4320
  const dest = am2.patch(ref);
4031
4321
  logOk(`Extracted to ${S.dim(dest)}`);
@@ -4036,7 +4326,7 @@ function makePatchCommand() {
4036
4326
  }
4037
4327
  });
4038
4328
  cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
4039
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
4329
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
4040
4330
  try {
4041
4331
  const patchFile = am2.patchCommit(ref);
4042
4332
  logOk(`Patch saved to ${S.dim(patchFile)}`);
@@ -4047,7 +4337,7 @@ function makePatchCommand() {
4047
4337
  }
4048
4338
  });
4049
4339
  cmd.command("submit <ref>").description("Apply patch to repo clone and prepare for PR").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
4050
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
4340
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
4051
4341
  try {
4052
4342
  am2.patchSubmit(ref);
4053
4343
  logOk("Patch applied to repo clone and committed.");
@@ -4060,7 +4350,7 @@ function makePatchCommand() {
4060
4350
  }
4061
4351
  });
4062
4352
  cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
4063
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
4353
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
4064
4354
  am2.patchRemove(ref);
4065
4355
  logOk(`Patch removed for ${ref}`);
4066
4356
  });
@@ -4078,7 +4368,7 @@ function action2(fn) {
4078
4368
  };
4079
4369
  }
4080
4370
  async function reconcileAndReport(projectDir, plugins) {
4081
- const { reconcilePlugins } = await import('../plugin-store-RBCDBO7K.js');
4371
+ const { reconcilePlugins } = await import('../plugin-store-UNENLB56.js');
4082
4372
  if (plugins.length === 0) {
4083
4373
  logInfo("No plugins declared \u2014 nothing to reconcile.");
4084
4374
  return;
@@ -4092,10 +4382,10 @@ async function reconcileAndReport(projectDir, plugins) {
4092
4382
  }
4093
4383
  }
4094
4384
  async function runInstall2(spec, opts) {
4095
- const projectDir = path13__default.resolve(opts.projectDir);
4385
+ const projectDir = path14__default.resolve(opts.projectDir);
4096
4386
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
4097
- const { specName } = await import('../plugin-store-RBCDBO7K.js');
4098
- const yamlPath = path13__default.join(projectDir, "skaile.yaml");
4387
+ const { specName } = await import('../plugin-store-UNENLB56.js');
4388
+ const yamlPath = path14__default.join(projectDir, "skaile.yaml");
4099
4389
  const editor = WorkspaceYamlEditor2.load(yamlPath);
4100
4390
  const replaced = editor.addPlugin(spec, specName);
4101
4391
  editor.save();
@@ -4104,10 +4394,10 @@ async function runInstall2(spec, opts) {
4104
4394
  await reconcileAndReport(projectDir, editor.getPlugins());
4105
4395
  }
4106
4396
  async function runRemove(name, opts) {
4107
- const projectDir = path13__default.resolve(opts.projectDir);
4397
+ const projectDir = path14__default.resolve(opts.projectDir);
4108
4398
  const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
4109
- const { specName } = await import('../plugin-store-RBCDBO7K.js');
4110
- const yamlPath = path13__default.join(projectDir, "skaile.yaml");
4399
+ const { specName } = await import('../plugin-store-UNENLB56.js');
4400
+ const yamlPath = path14__default.join(projectDir, "skaile.yaml");
4111
4401
  const editor = WorkspaceYamlEditor2.load(yamlPath);
4112
4402
  const removed = editor.removePlugin(name, specName);
4113
4403
  if (!removed) {
@@ -4119,7 +4409,7 @@ async function runRemove(name, opts) {
4119
4409
  await reconcileAndReport(projectDir, editor.getPlugins());
4120
4410
  }
4121
4411
  async function runList(opts) {
4122
- const projectDir = path13__default.resolve(opts.projectDir);
4412
+ const projectDir = path14__default.resolve(opts.projectDir);
4123
4413
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
4124
4414
  const config = resolveSkWorkspaceConfig2(projectDir);
4125
4415
  const declared = config.plugins ?? [];
@@ -4134,7 +4424,7 @@ async function runList(opts) {
4134
4424
  const registry = createPluginRegistry();
4135
4425
  if (declared.length > 0) {
4136
4426
  try {
4137
- const { loadPlugins } = await import('../plugin-store-RBCDBO7K.js');
4427
+ const { loadPlugins } = await import('../plugin-store-UNENLB56.js');
4138
4428
  const result = await loadPlugins(projectDir, declared, registry);
4139
4429
  for (const f of result.failed) logWarn(f.error);
4140
4430
  } catch (err) {
@@ -4173,7 +4463,7 @@ function makePresetCommand() {
4173
4463
  cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
4174
4464
  const presetName = name ?? "my-preset";
4175
4465
  const filename = `${presetName}.preset.yaml`;
4176
- const outPath = path13__default.join(path13__default.resolve(opts.dir), filename);
4466
+ const outPath = path14__default.join(path14__default.resolve(opts.dir), filename);
4177
4467
  if (existsSync(outPath)) {
4178
4468
  logErr(`File already exists: ${outPath}`);
4179
4469
  logInfo("Choose a different name or remove the existing file.");
@@ -4221,7 +4511,7 @@ async function reportNestedPresetRefs(preset) {
4221
4511
  }
4222
4512
  async function checkPresetCycles(preset, resolved) {
4223
4513
  const { detectCycles } = await import('../discovery/index.js');
4224
- const presetRef = path13__default.basename(resolved, ".preset.yaml");
4514
+ const presetRef = path14__default.basename(resolved, ".preset.yaml");
4225
4515
  const edges = [];
4226
4516
  for (const item of preset.items) {
4227
4517
  if (item.ref) {
@@ -4272,7 +4562,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
4272
4562
  }
4273
4563
  }
4274
4564
  async function runPresetValidate(filePath) {
4275
- const resolved = path13__default.resolve(filePath);
4565
+ const resolved = path14__default.resolve(filePath);
4276
4566
  const preset = await loadPresetForValidation(resolved);
4277
4567
  await reportNestedPresetRefs(preset);
4278
4568
  await checkPresetCycles(preset, resolved);
@@ -4366,8 +4656,8 @@ async function runRefInstall(ref, opts) {
4366
4656
  const spinner5 = p6.spinner();
4367
4657
  spinner5.start(`Installing ${ref}`);
4368
4658
  try {
4369
- const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-362BZ6OW.js');
4370
- const catalog = await openCatalogSource2({ projectDir: path13__default.resolve(opts.projectDir) });
4659
+ const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-COHFCT4N.js');
4660
+ const catalog = await openCatalogSource2({ projectDir: path14__default.resolve(opts.projectDir) });
4371
4661
  if (!supportsInstallManifest(catalog)) {
4372
4662
  throw new Error(
4373
4663
  "pointer-only install (skaile install <ref>) requires a tRPC-framed Catalog. The configured catalog uses REST framing, which does not serve install manifests. Set catalog.url to https://skaile.store, or catalog.framing: trpc, in ~/.skaile/config.yaml."
@@ -4396,9 +4686,9 @@ async function runRefInstall(ref, opts) {
4396
4686
  }
4397
4687
  }
4398
4688
  async function runYamlInstall(opts) {
4399
- const projectDir = path13__default.resolve(opts.projectDir);
4689
+ const projectDir = path14__default.resolve(opts.projectDir);
4400
4690
  try {
4401
- const { ensureSourcesCloned } = await import('../ensure-sources-NSDMTAWN.js');
4691
+ const { ensureSourcesCloned } = await import('../ensure-sources-KLCGXVE6.js');
4402
4692
  const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
4403
4693
  if (hydrate.cloned.length > 0) {
4404
4694
  logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
@@ -4429,6 +4719,7 @@ async function runYamlInstall(opts) {
4429
4719
  }
4430
4720
  if (result.missing.length > 0) {
4431
4721
  for (const m of result.missing) logErr(`Missing: ${m}`);
4722
+ process.exitCode = 1;
4432
4723
  }
4433
4724
  if (result.lockWritten) {
4434
4725
  logInfo(`Lock file written: ${S.dim("skaile.lock.yaml")}`);
@@ -4441,7 +4732,7 @@ async function runYamlInstall(opts) {
4441
4732
  }
4442
4733
  function makeCheckCommand() {
4443
4734
  return new Command("check").description("Check for unmet requirements").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
4444
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
4735
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
4445
4736
  const issues = am2.doctor();
4446
4737
  if (issues.length === 0) {
4447
4738
  logOk("All dependencies satisfied.");
@@ -4458,10 +4749,10 @@ function makeCheckCommand() {
4458
4749
  function makeCleanCommand() {
4459
4750
  return new Command("clean").description("Remove all skaile-managed assets from the workspace").option("--all", "Full reset: also remove history, patches, repos, and lock file").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").action(async (opts) => {
4460
4751
  const am2 = new AssetManager({
4461
- projectDir: path13__default.resolve(opts.projectDir),
4752
+ projectDir: path14__default.resolve(opts.projectDir),
4462
4753
  driverTarget: opts.target
4463
4754
  });
4464
- const lock = readLock(path13__default.resolve(opts.projectDir, "skaile.lock.yaml"));
4755
+ const lock = readLock(path14__default.resolve(opts.projectDir, "skaile.lock.yaml"));
4465
4756
  if (!lock || Object.keys(lock.assets).length === 0) {
4466
4757
  logInfo("Nothing to clean (no skaile-managed assets found).");
4467
4758
  return;
@@ -4514,14 +4805,14 @@ function makeCleanCommand() {
4514
4805
  }
4515
4806
  function makeRebuildCommand() {
4516
4807
  return new Command("rebuild").description("Re-snapshot inline-snapshot composition items and bump prompt version").argument("[agent]", "Agent name or path (defaults to current project agent)").option("--project-dir <dir>", "Project directory", process.cwd()).action(async (agentArg, opts) => {
4517
- const projectDir = path13__default.resolve(opts.projectDir);
4808
+ const projectDir = path14__default.resolve(opts.projectDir);
4518
4809
  let agentDir;
4519
4810
  if (agentArg) {
4520
4811
  if (agentArg.includes("/") || agentArg.includes("\\")) {
4521
- agentDir = path13__default.resolve(projectDir, agentArg);
4812
+ agentDir = path14__default.resolve(projectDir, agentArg);
4522
4813
  } else {
4523
4814
  const resolved = resolveAgentDir(projectDir);
4524
- agentDir = resolved ?? path13__default.resolve(projectDir, agentArg);
4815
+ agentDir = resolved ?? path14__default.resolve(projectDir, agentArg);
4525
4816
  }
4526
4817
  } else {
4527
4818
  const resolved = resolveAgentDir(projectDir);
@@ -4599,7 +4890,7 @@ function makeFlowEventHandler() {
4599
4890
  }
4600
4891
  function makeRunCommand() {
4601
4892
  const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--driver <name>", "Driver backend (claude-sdk, codex, omp)").option("--provider <name>", "LLM provider").option("--model <name>", "Model override").option("--label <label>", "Human-readable session label").option("--dry-run", "Print plan without executing").option("--skill <name>", "Skill name (for single-shot mode)").action(async (positional, opts) => {
4602
- const projectDir = path13__default.resolve(opts.projectDir);
4893
+ const projectDir = path14__default.resolve(opts.projectDir);
4603
4894
  const cliDriver = opts.driver;
4604
4895
  const dryRun = opts.dryRun ?? false;
4605
4896
  let flowId = positional[0];
@@ -4634,12 +4925,12 @@ function makeRunCommand() {
4634
4925
  const priorityRoots = [];
4635
4926
  let dir = projectDir;
4636
4927
  for (let i = 0; i < 6; i++) {
4637
- const candidate = path13__default.join(dir, "ai-assets");
4638
- if (fs11__default.existsSync(candidate)) {
4928
+ const candidate = path14__default.join(dir, "ai-assets");
4929
+ if (fs12__default.existsSync(candidate)) {
4639
4930
  priorityRoots.push(candidate);
4640
4931
  break;
4641
4932
  }
4642
- dir = path13__default.dirname(dir);
4933
+ dir = path14__default.dirname(dir);
4643
4934
  }
4644
4935
  const flowPath = findFlowFile(flowId, priorityRoots);
4645
4936
  if (!flowPath) {
@@ -4694,7 +4985,7 @@ function makeRunCommand() {
4694
4985
  }
4695
4986
  function makeResumeCommand() {
4696
4987
  const cmd = new Command("resume").description("Resume current session").option("--project-dir <path>", "Project directory", process.cwd()).option("--session <run-id>", "Target session by runId").option("--dry-run", "Print plan without executing").action(async (opts) => {
4697
- const projectDir = path13__default.resolve(opts.projectDir);
4988
+ const projectDir = path14__default.resolve(opts.projectDir);
4698
4989
  const sessionId = opts.session;
4699
4990
  const dryRun = opts.dryRun ?? false;
4700
4991
  const session = sessionId ? await loadSessionById(projectDir, sessionId) : await loadSession(projectDir);
@@ -4721,7 +5012,7 @@ function makeResumeCommand() {
4721
5012
  }
4722
5013
  function makeStatusCommand() {
4723
5014
  return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
4724
- const projectDir = path13__default.resolve(opts.projectDir);
5015
+ const projectDir = path14__default.resolve(opts.projectDir);
4725
5016
  const session = await loadSession(projectDir);
4726
5017
  if (!session) {
4727
5018
  logInfo("No active session.");
@@ -4746,7 +5037,7 @@ function makeStatusCommand() {
4746
5037
  }
4747
5038
  function makeClearCommand() {
4748
5039
  return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
4749
- const projectDir = path13__default.resolve(opts.projectDir);
5040
+ const projectDir = path14__default.resolve(opts.projectDir);
4750
5041
  await clearSession(projectDir);
4751
5042
  logOk("Session cleared.");
4752
5043
  });
@@ -4755,8 +5046,8 @@ function makeReplCommand() {
4755
5046
  return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>", "Driver backend (claude-sdk, omp)").option("--provider <name>", "LLM provider").option("--model <name>", "Model override").option("--resume", "Resume last session").option("--resume-session <id>", "Resume specific session").action(async (opts) => {
4756
5047
  const { findWorkspaceRoot: findWorkspaceRoot2 } = await import('../core/index.js');
4757
5048
  const { startRepl } = await import('../tui/index.js');
4758
- const os = await import('os');
4759
- const userCwd = path13__default.resolve(opts.projectDir ?? process.cwd());
5049
+ const os2 = await import('os');
5050
+ const userCwd = path14__default.resolve(opts.projectDir ?? process.cwd());
4760
5051
  const workspaceRoot = findWorkspaceRoot2(userCwd);
4761
5052
  let projectDir;
4762
5053
  let agentCwd;
@@ -4778,13 +5069,13 @@ function makeReplCommand() {
4778
5069
  p6.cancel("Cancelled.");
4779
5070
  process.exit(0);
4780
5071
  }
4781
- const tmpDir = fs11__default.mkdtempSync(path13__default.join(os.tmpdir(), "skaile-repl-"));
5072
+ const tmpDir = fs12__default.mkdtempSync(path14__default.join(os2.tmpdir(), "skaile-repl-"));
4782
5073
  projectDir = tmpDir;
4783
5074
  agentCwd = userCwd;
4784
5075
  logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
4785
5076
  if (!driverOverride) {
4786
- const claudeDir = path13__default.join(os.homedir(), ".claude");
4787
- if (fs11__default.existsSync(claudeDir)) {
5077
+ const claudeDir = path14__default.join(os2.homedir(), ".claude");
5078
+ if (fs12__default.existsSync(claudeDir)) {
4788
5079
  driverOverride = "claude-sdk";
4789
5080
  logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} backend`);
4790
5081
  } else {
@@ -4835,7 +5126,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
4835
5126
  const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
4836
5127
  const config = resolveSkWorkspaceConfig2(projectDir);
4837
5128
  if (!config.plugins || config.plugins.length === 0) return;
4838
- const { ensurePluginsLoaded } = await import('../plugin-store-RBCDBO7K.js');
5129
+ const { ensurePluginsLoaded } = await import('../plugin-store-UNENLB56.js');
4839
5130
  const { pluginRegistry } = await import('../plugin-registry/index.js');
4840
5131
  const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
4841
5132
  if (result.loaded.length > 0) {
@@ -4851,21 +5142,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
4851
5142
  async function runCompileTest(opts) {
4852
5143
  const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-F4NZ66VD.js');
4853
5144
  const { tmpdir } = await import('os');
4854
- const { dirname: dirname3, join: join5, resolve: resolve4 } = await import('path');
5145
+ const { dirname: dirname5, join: join6, resolve: resolve5 } = await import('path');
4855
5146
  const { fileURLToPath: fileURLToPath2 } = await import('url');
4856
- const { unlinkSync, existsSync: existsSync13 } = await import('fs');
5147
+ const { unlinkSync, existsSync: existsSync14 } = await import('fs');
4857
5148
  const { spawn } = await import('child_process');
4858
5149
  const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
4859
- const { MONOREPO_ROOT } = await import('../paths-4SSFMX5Z.js');
5150
+ const { MONOREPO_ROOT } = await import('../paths-2SYXGTZJ.js');
4860
5151
  if (MONOREPO_ROOT === null) {
4861
5152
  logErr2("--compile-test is only available inside the skaile-dev workspace.");
4862
5153
  logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
4863
5154
  process.exitCode = 2;
4864
5155
  return;
4865
5156
  }
4866
- const outfile = join5(tmpdir(), `skaile-compile-test-${Date.now()}`);
5157
+ const outfile = join6(tmpdir(), `skaile-compile-test-${Date.now()}`);
4867
5158
  const __thisFile = fileURLToPath2(import.meta.url);
4868
- const entryPoint = resolve4(dirname3(__thisFile), "..", "index.ts");
5159
+ const entryPoint = resolve5(dirname5(__thisFile), "..", "index.ts");
4869
5160
  logInfo2(`Building compiled binary...`);
4870
5161
  logInfo2(`Entry: ${S2.dim(entryPoint)}`);
4871
5162
  logInfo2(`Output: ${S2.dim(outfile)}`);
@@ -4915,7 +5206,7 @@ async function runCompileTest(opts) {
4915
5206
  } catch {
4916
5207
  }
4917
5208
  try {
4918
- if (existsSync13(outfile)) unlinkSync(outfile);
5209
+ if (existsSync14(outfile)) unlinkSync(outfile);
4919
5210
  } catch {
4920
5211
  }
4921
5212
  }
@@ -5168,19 +5459,19 @@ function buildTailSelect(q) {
5168
5459
  return { sql, params };
5169
5460
  }
5170
5461
  function sleepUnlessAborted(ms, signal) {
5171
- return new Promise((resolve4) => {
5462
+ return new Promise((resolve5) => {
5172
5463
  if (signal?.aborted) {
5173
- resolve4();
5464
+ resolve5();
5174
5465
  return;
5175
5466
  }
5176
5467
  const timer = setTimeout(() => {
5177
5468
  signal?.removeEventListener("abort", onAbort);
5178
- resolve4();
5469
+ resolve5();
5179
5470
  }, ms);
5180
5471
  const onAbort = () => {
5181
5472
  clearTimeout(timer);
5182
5473
  signal?.removeEventListener("abort", onAbort);
5183
- resolve4();
5474
+ resolve5();
5184
5475
  };
5185
5476
  signal?.addEventListener("abort", onAbort, { once: true });
5186
5477
  });
@@ -5257,7 +5548,7 @@ async function remoteTail(opts) {
5257
5548
  ]
5258
5549
  });
5259
5550
  const filter = makeFilter(opts.query);
5260
- return new Promise((resolve4, reject) => {
5551
+ return new Promise((resolve5, reject) => {
5261
5552
  let settled = false;
5262
5553
  const finish = (err) => {
5263
5554
  if (settled) return;
@@ -5268,11 +5559,11 @@ async function remoteTail(opts) {
5268
5559
  }
5269
5560
  opts.signal?.removeEventListener("abort", onAbort);
5270
5561
  if (err) reject(err);
5271
- else resolve4();
5562
+ else resolve5();
5272
5563
  };
5273
5564
  const onAbort = () => finish();
5274
5565
  if (opts.signal?.aborted) {
5275
- resolve4();
5566
+ resolve5();
5276
5567
  return;
5277
5568
  }
5278
5569
  opts.signal?.addEventListener("abort", onAbort, { once: true });
@@ -5326,7 +5617,7 @@ function resolveMode(opts) {
5326
5617
  if (opts.forceLocal && opts.forceRemote) {
5327
5618
  throw new Error("Cannot use both --local and --remote");
5328
5619
  }
5329
- const startDir = path13__default.resolve(opts.projectDir ?? process.cwd());
5620
+ const startDir = path14__default.resolve(opts.projectDir ?? process.cwd());
5330
5621
  const localDb = findLogsDb(startDir);
5331
5622
  if (opts.forceLocal) {
5332
5623
  if (!localDb) {
@@ -5359,14 +5650,14 @@ function resolveMode(opts) {
5359
5650
  function findLogsDb(startDir) {
5360
5651
  let dir = startDir;
5361
5652
  for (let i = 0; i < MAX_WALK_LEVELS; i++) {
5362
- const candidate = path13__default.join(dir, ".skaile", "logs.db");
5653
+ const candidate = path14__default.join(dir, ".skaile", "logs.db");
5363
5654
  if (existsSync(candidate)) {
5364
5655
  try {
5365
5656
  if (statSync(candidate).isFile()) return candidate;
5366
5657
  } catch {
5367
5658
  }
5368
5659
  }
5369
- const parent = path13__default.dirname(dir);
5660
+ const parent = path14__default.dirname(dir);
5370
5661
  if (parent === dir) return void 0;
5371
5662
  dir = parent;
5372
5663
  }
@@ -5392,7 +5683,7 @@ function readApiToken() {
5392
5683
  }
5393
5684
  function readGlobalSettings() {
5394
5685
  try {
5395
- const settingsPath = path13__default.join(homedir(), ".skaile", "settings.json");
5686
+ const settingsPath = path14__default.join(homedir(), ".skaile", "settings.json");
5396
5687
  if (!existsSync(settingsPath)) return {};
5397
5688
  return JSON.parse(readFileSync(settingsPath, "utf8"));
5398
5689
  } catch {
@@ -5541,7 +5832,7 @@ function parsePositiveInt(value, flag) {
5541
5832
  function makeSessionCommand() {
5542
5833
  const cmd = new Command("session").description("Manage sessions");
5543
5834
  cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
5544
- const projectDir = path13__default.resolve(opts.projectDir);
5835
+ const projectDir = path14__default.resolve(opts.projectDir);
5545
5836
  const sessions = await listSessions(projectDir);
5546
5837
  const current = await loadSession(projectDir);
5547
5838
  if (sessions.length === 0) {
@@ -5569,7 +5860,7 @@ function makeSessionCommand() {
5569
5860
  console.log();
5570
5861
  });
5571
5862
  cmd.command("show <run-id>").description("Show a specific session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
5572
- const projectDir = path13__default.resolve(opts.projectDir);
5863
+ const projectDir = path14__default.resolve(opts.projectDir);
5573
5864
  const session = await loadSessionById(projectDir, runId);
5574
5865
  if (!session) {
5575
5866
  logErr(`Session not found: ${runId}`);
@@ -5578,12 +5869,12 @@ function makeSessionCommand() {
5578
5869
  console.log(JSON.stringify(session, null, 2));
5579
5870
  });
5580
5871
  cmd.command("switch <run-id>").description("Switch the current session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
5581
- const projectDir = path13__default.resolve(opts.projectDir);
5872
+ const projectDir = path14__default.resolve(opts.projectDir);
5582
5873
  await setCurrentSession(projectDir, runId);
5583
5874
  logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
5584
5875
  });
5585
5876
  cmd.command("delete <run-id>").description("Delete a session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
5586
- const projectDir = path13__default.resolve(opts.projectDir);
5877
+ const projectDir = path14__default.resolve(opts.projectDir);
5587
5878
  await deleteSession(projectDir, runId);
5588
5879
  logOk(`Deleted session: ${S.dim(runId.slice(0, 8))}`);
5589
5880
  });
@@ -5637,12 +5928,12 @@ function showOverview(am2) {
5637
5928
  }
5638
5929
  function showAsset(am2, kind, name) {
5639
5930
  const entry = am2.info(`${kind}:${name}`);
5640
- if (entry?.source && fs11__default.existsSync(entry.source)) {
5931
+ if (entry?.source && fs12__default.existsSync(entry.source)) {
5641
5932
  console.log();
5642
5933
  console.log(` ${kindColor(entry.kind)} ${S.heading(entry.name)}`);
5643
5934
  console.log(` ${S.rule(40)}`);
5644
5935
  console.log();
5645
- console.log(fs11__default.readFileSync(entry.source, "utf-8"));
5936
+ console.log(fs12__default.readFileSync(entry.source, "utf-8"));
5646
5937
  return;
5647
5938
  }
5648
5939
  logErr(`Asset not found: ${kind}:${name}`);
@@ -5651,7 +5942,7 @@ function showAsset(am2, kind, name) {
5651
5942
  function makeShowCommand() {
5652
5943
  return new Command("show").description("Show deployed assets overview, or print asset content").argument("[kind]", "Asset kind (skill, agent, prompt, flow, bundle, contract)").argument("[name]", "Asset name").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").action((kind, name, opts) => {
5653
5944
  const am2 = new AssetManager({
5654
- projectDir: path13__default.resolve(opts.projectDir),
5945
+ projectDir: path14__default.resolve(opts.projectDir),
5655
5946
  driverTarget: opts.target
5656
5947
  });
5657
5948
  if (!kind) {
@@ -5688,11 +5979,8 @@ function addSourceManifestCommands(src) {
5688
5979
  }
5689
5980
 
5690
5981
  // cli/src/commands/source.ts
5691
- function sourceClonePath(name) {
5692
- return path13.join(getGlobalCacheDir(), name);
5693
- }
5694
- function deriveSlug(url) {
5695
- return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
5982
+ function sourceClonePath(key) {
5983
+ return path14.join(getGlobalCacheDir(), key);
5696
5984
  }
5697
5985
  function normalizeSourceUrl(input) {
5698
5986
  const s = input.trim();
@@ -5703,9 +5991,14 @@ function normalizeSourceUrl(input) {
5703
5991
  return s;
5704
5992
  }
5705
5993
  function sourceMatchesKey(entry, key) {
5706
- if (entry.url === key || deriveSlug(entry.url) === key) return true;
5994
+ if (entry.url === key) return true;
5995
+ if (sourceCacheKey(entry.url) === key || sourceShortName(entry.url) === key) return true;
5707
5996
  return entry.url === normalizeSourceUrl(key);
5708
5997
  }
5998
+ function findCacheKeyCollision(sources, url) {
5999
+ const key = sourceCacheKey(url);
6000
+ return sources.find((s) => s.url !== url && sourceCacheKey(s.url) === key);
6001
+ }
5709
6002
  function requireProjectYamlPath() {
5710
6003
  const root = findWorkspaceRoot(process.cwd());
5711
6004
  if (!root) {
@@ -5714,7 +6007,7 @@ function requireProjectYamlPath() {
5714
6007
  );
5715
6008
  process.exit(1);
5716
6009
  }
5717
- return path13.join(root, workspaceConfigFilename());
6010
+ return path14.join(root, workspaceConfigFilename());
5718
6011
  }
5719
6012
  function readProjectSources(yamlPath) {
5720
6013
  if (!existsSync(yamlPath)) return [];
@@ -5726,12 +6019,12 @@ function readProjectSources(yamlPath) {
5726
6019
  }
5727
6020
  }
5728
6021
  function ensureClone(entry, opts = {}) {
5729
- const slug = deriveSlug(entry.url);
5730
- const dest = sourceClonePath(slug);
6022
+ const dest = sourceClonePath(sourceCacheKey(entry.url));
5731
6023
  if (existsSync(dest)) {
5732
6024
  if (!opts.force) return false;
5733
6025
  rmSync(dest, { recursive: true, force: true });
5734
6026
  }
6027
+ mkdirSync(path14.dirname(dest), { recursive: true });
5735
6028
  const args = ["clone", entry.url, dest];
5736
6029
  if (entry.pin) args.splice(1, 0, "--branch", entry.pin);
5737
6030
  const clone = spawnSync("git", args, { stdio: "inherit" });
@@ -5744,11 +6037,11 @@ function ensureClone(entry, opts = {}) {
5744
6037
  async function refreshManifestCache(entry, includeDev = false) {
5745
6038
  const { manager, library, close } = await openLibraryManager();
5746
6039
  try {
5747
- const slug = deriveSlug(entry.url);
5748
- const dest = sourceClonePath(slug);
5749
- const existing = (await manager.listLibraries()).find((l) => l.name === slug);
6040
+ const name = sourceShortName(entry.url);
6041
+ const dest = sourceClonePath(sourceCacheKey(entry.url));
6042
+ const existing = (await manager.listLibraries()).find((l) => l.name === name);
5750
6043
  const lib = existing ?? await manager.addLibrary({
5751
- name: slug,
6044
+ name,
5752
6045
  path: dest,
5753
6046
  backend: "git",
5754
6047
  backendConfig: { url: entry.url, branch: entry.pin ?? "main", authHint: "ssh" },
@@ -5762,7 +6055,8 @@ async function refreshManifestCache(entry, includeDev = false) {
5762
6055
  close();
5763
6056
  }
5764
6057
  }
5765
- async function dropManifestCache(name, purgeClone) {
6058
+ async function dropManifestCache(url, purgeClone) {
6059
+ const name = sourceShortName(url);
5766
6060
  const { manager, close } = await openLibraryManager();
5767
6061
  try {
5768
6062
  const existing = (await manager.listLibraries()).find((l) => l.name === name);
@@ -5773,7 +6067,7 @@ async function dropManifestCache(name, purgeClone) {
5773
6067
  close();
5774
6068
  }
5775
6069
  if (purgeClone) {
5776
- const dest = sourceClonePath(name);
6070
+ const dest = sourceClonePath(sourceCacheKey(url));
5777
6071
  if (existsSync(dest)) rmSync(dest, { recursive: true, force: true });
5778
6072
  }
5779
6073
  }
@@ -5787,19 +6081,27 @@ function makeSourceCommand() {
5787
6081
  async (source, opts) => {
5788
6082
  const url = normalizeSourceUrl(source);
5789
6083
  const yamlPath = requireProjectYamlPath();
6084
+ const collision = findCacheKeyCollision(readProjectSources(yamlPath), url);
6085
+ if (collision) {
6086
+ logErr(
6087
+ `"${url}" maps to the same cache key (${sourceCacheKey(url)}) as already-registered "${collision.url}". Remove that source first (skaile source remove) or re-use its exact URL to update it.`
6088
+ );
6089
+ process.exitCode = 1;
6090
+ return;
6091
+ }
5790
6092
  if (opts.name) {
5791
6093
  logWarn(
5792
6094
  "the --name flag is deprecated; the source entry now stores only the URL (the cache slug is derived from it)."
5793
6095
  );
5794
6096
  }
5795
6097
  const pin = opts.pin ?? opts.branch;
5796
- const slug = deriveSlug(url);
6098
+ const slug = sourceShortName(url);
5797
6099
  const entry = { url };
5798
6100
  if (pin) entry.pin = pin;
5799
6101
  const editor = WorkspaceYamlEditor.load(yamlPath);
5800
6102
  editor.setSource(entry);
5801
6103
  editor.save();
5802
- const dest = sourceClonePath(slug);
6104
+ const dest = sourceClonePath(sourceCacheKey(url));
5803
6105
  const preexisting = existsSync(dest);
5804
6106
  const cloned = ensureClone(entry, { force: opts.force });
5805
6107
  if (!cloned) {
@@ -5812,7 +6114,7 @@ function makeSourceCommand() {
5812
6114
  const result = await refreshManifestCache(entry, opts.dev);
5813
6115
  logOk(`Indexed ${result.assetsUpdated} of ${result.assetsFound} asset(s) from "${slug}".`);
5814
6116
  for (const err of result.errors) logWarn(err);
5815
- logOk(`Source "${slug}" registered in ${path13.relative(process.cwd(), yamlPath)}.`);
6117
+ logOk(`Source "${slug}" registered in ${path14.relative(process.cwd(), yamlPath)}.`);
5816
6118
  }
5817
6119
  );
5818
6120
  cmd.command("list").description("List sources registered in this project's skaile.yaml").option("--json", "Output as JSON").action(async (opts) => {
@@ -5826,8 +6128,8 @@ function makeSourceCommand() {
5826
6128
  console.log();
5827
6129
  console.log(S.heading(" Sources"));
5828
6130
  for (const s of sources) {
5829
- const slug = deriveSlug(s.url);
5830
- const cached = existsSync(sourceClonePath(slug)) ? "" : S.warn(" (not cached)");
6131
+ const slug = sourceShortName(s.url);
6132
+ const cached = existsSync(sourceClonePath(sourceCacheKey(s.url))) ? "" : S.warn(" (not cached)");
5831
6133
  console.log(` ${S.cmd(slug.padEnd(24))} ${S.dim(s.url)}${cached}`);
5832
6134
  }
5833
6135
  console.log(`
@@ -5841,14 +6143,15 @@ function makeSourceCommand() {
5841
6143
  logErr(`No source matching "${key}" in ${yamlPath}.`);
5842
6144
  process.exit(1);
5843
6145
  }
5844
- const slug = deriveSlug(entry.url);
6146
+ const slug = sourceShortName(entry.url);
6147
+ const clonePath = sourceClonePath(sourceCacheKey(entry.url));
5845
6148
  console.log(
5846
6149
  JSON.stringify(
5847
6150
  {
5848
6151
  ...entry,
5849
6152
  slug,
5850
- clonePath: sourceClonePath(slug),
5851
- cached: existsSync(sourceClonePath(slug))
6153
+ clonePath,
6154
+ cached: existsSync(clonePath)
5852
6155
  },
5853
6156
  null,
5854
6157
  2
@@ -5863,10 +6166,10 @@ function makeSourceCommand() {
5863
6166
  logErr(`No source matching "${key}" in ${yamlPath}.`);
5864
6167
  process.exit(1);
5865
6168
  }
5866
- const slug = deriveSlug(match.url);
6169
+ const slug = sourceShortName(match.url);
5867
6170
  editor.removeSource(match.url);
5868
6171
  editor.save();
5869
- await dropManifestCache(slug, opts.purge);
6172
+ await dropManifestCache(match.url, opts.purge);
5870
6173
  logOk(
5871
6174
  opts.purge ? `Removed source "${slug}" and purged its clone.` : `Removed source "${slug}" from skaile.yaml (clone left in ~/.skaile/cache/sources/).`
5872
6175
  );
@@ -5890,7 +6193,11 @@ function makeSourceCommand() {
5890
6193
  } else {
5891
6194
  const selected = await p6.multiselect({
5892
6195
  message: "Select sources to sync",
5893
- options: sources.map((s) => ({ value: s.url, label: deriveSlug(s.url), hint: s.url })),
6196
+ options: sources.map((s) => ({
6197
+ value: s.url,
6198
+ label: sourceShortName(s.url),
6199
+ hint: s.url
6200
+ })),
5894
6201
  required: true
5895
6202
  });
5896
6203
  if (p6.isCancel(selected)) {
@@ -5901,8 +6208,8 @@ function makeSourceCommand() {
5901
6208
  targets = sources.filter((s) => picked.has(s.url));
5902
6209
  }
5903
6210
  for (const entry of targets) {
5904
- const slug = deriveSlug(entry.url);
5905
- const dest = sourceClonePath(slug);
6211
+ const slug = sourceShortName(entry.url);
6212
+ const dest = sourceClonePath(sourceCacheKey(entry.url));
5906
6213
  if (!existsSync(dest)) {
5907
6214
  ensureClone(entry);
5908
6215
  logOk(`${slug}: cloned to ${dest}.`);
@@ -5940,10 +6247,10 @@ function makeStoreCommand() {
5940
6247
  if (opts.email) {
5941
6248
  const readline2 = await import('readline');
5942
6249
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
5943
- const password = await new Promise((resolve4) => {
6250
+ const password = await new Promise((resolve5) => {
5944
6251
  rl.question("Password: ", (answer) => {
5945
6252
  rl.close();
5946
- resolve4(answer);
6253
+ resolve5(answer);
5947
6254
  });
5948
6255
  });
5949
6256
  try {
@@ -6098,7 +6405,7 @@ function printTree(node, prefix = "", isLast = true) {
6098
6405
  }
6099
6406
  function makeTreeCommand() {
6100
6407
  return new Command("tree").description("Show full dependency tree").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
6101
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
6408
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
6102
6409
  const root = am2.tree();
6103
6410
  if (root.children.length === 0) {
6104
6411
  logInfo("No dependencies in lock file. Run `skaile install` first.");
@@ -6116,7 +6423,7 @@ function makeUpdateCommand() {
6116
6423
  try {
6117
6424
  const catalogSpinner = p6.spinner();
6118
6425
  catalogSpinner.start("Refreshing catalog cache");
6119
- const remote = await openCatalogSource({ projectDir: path13__default.resolve(opts.projectDir) });
6426
+ const remote = await openCatalogSource({ projectDir: path14__default.resolve(opts.projectDir) });
6120
6427
  const result2 = await remote.refresh();
6121
6428
  catalogSpinner.stop(
6122
6429
  `Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
@@ -6128,7 +6435,7 @@ function makeUpdateCommand() {
6128
6435
  }
6129
6436
  }
6130
6437
  if (opts.catalogOnly) return;
6131
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
6438
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
6132
6439
  const spinner5 = p6.spinner();
6133
6440
  spinner5.start("Re-deploying assets");
6134
6441
  const result = await am2.install();
@@ -6162,12 +6469,12 @@ function findManifestCandidates(rootPath) {
6162
6469
  function walk(dir) {
6163
6470
  let entries;
6164
6471
  try {
6165
- entries = fs11__default.readdirSync(dir, { withFileTypes: true });
6472
+ entries = fs12__default.readdirSync(dir, { withFileTypes: true });
6166
6473
  } catch {
6167
6474
  return;
6168
6475
  }
6169
6476
  for (const entry of entries) {
6170
- const fullPath = path13__default.join(dir, entry.name);
6477
+ const fullPath = path14__default.join(dir, entry.name);
6171
6478
  if (entry.isDirectory()) {
6172
6479
  if (!SKIP_DIRS.has(entry.name)) walk(fullPath);
6173
6480
  } else if (entry.isFile()) {
@@ -6208,7 +6515,7 @@ function checkManifestIdentity(kind, parsed) {
6208
6515
  return null;
6209
6516
  }
6210
6517
  function parseManifestCandidate(c, absRoot) {
6211
- const content = fs11__default.readFileSync(c.filePath, "utf-8");
6518
+ const content = fs12__default.readFileSync(c.filePath, "utf-8");
6212
6519
  if (c.filePath.endsWith(".md")) {
6213
6520
  const parsed = parseMdFrontmatter(content);
6214
6521
  if (parsed === null) {
@@ -6220,23 +6527,38 @@ function parseManifestCandidate(c, absRoot) {
6220
6527
  const parsed = c.filePath.endsWith(".json") ? JSON.parse(content) : parse(content);
6221
6528
  return { kind: "value", parsed };
6222
6529
  } catch (e) {
6223
- const relPath = path13__default.relative(absRoot, c.filePath);
6530
+ const relPath = path14__default.relative(absRoot, c.filePath);
6224
6531
  logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
6225
6532
  return { kind: "error" };
6226
6533
  }
6227
6534
  }
6228
- function validateManifestCandidate(c, parsed, absRoot, registry) {
6229
- const relPath = path13__default.relative(absRoot, c.filePath);
6535
+ function validateManifestCandidate(c, parsed, absRoot, registry, strictConformance) {
6536
+ const relPath = path14__default.relative(absRoot, c.filePath);
6230
6537
  let errors = 0;
6538
+ let warnings = 0;
6231
6539
  const identityError = checkManifestIdentity(c.kind, parsed);
6232
6540
  if (identityError) {
6233
6541
  logErr(`${relPath} [${c.kind}] \u2014 ${identityError}`);
6234
6542
  errors++;
6235
6543
  }
6544
+ if (c.kind === "skill" && parsed && typeof parsed === "object") {
6545
+ const dirName = path14__default.basename(path14__default.dirname(c.filePath));
6546
+ const findings = checkAgentSkillConformance(parsed, { dirName });
6547
+ for (const f of findings) {
6548
+ const line = `${relPath} [skill conformance] \u2014 ${f.field}: ${f.message}`;
6549
+ if (strictConformance) {
6550
+ logErr(line);
6551
+ errors++;
6552
+ } else {
6553
+ logWarn(line);
6554
+ warnings++;
6555
+ }
6556
+ }
6557
+ }
6236
6558
  const provider = registry.getProvider(c.kind);
6237
6559
  if (!provider) {
6238
6560
  logWarn(`${relPath} [${c.kind}] \u2014 kind "${c.kind}" is not registered, skipping validation`);
6239
- return { errors, warnings: 1 };
6561
+ return { errors, warnings: warnings + 1 };
6240
6562
  }
6241
6563
  const result = provider.validateManifest(parsed);
6242
6564
  if (!result.ok) {
@@ -6245,11 +6567,11 @@ function validateManifestCandidate(c, parsed, absRoot, registry) {
6245
6567
  }
6246
6568
  errors += result.errors.length;
6247
6569
  }
6248
- return { errors, warnings: 0 };
6570
+ return { errors, warnings };
6249
6571
  }
6250
- function validateManifests(rootPath) {
6251
- const absRoot = path13__default.resolve(rootPath);
6252
- if (!fs11__default.existsSync(absRoot)) {
6572
+ function validateManifests(rootPath, strictConformance) {
6573
+ const absRoot = path14__default.resolve(rootPath);
6574
+ if (!fs12__default.existsSync(absRoot)) {
6253
6575
  logErr(`Path does not exist: ${absRoot}`);
6254
6576
  return { total: 0, errors: 1, warnings: 0 };
6255
6577
  }
@@ -6264,7 +6586,13 @@ function validateManifests(rootPath) {
6264
6586
  errors++;
6265
6587
  continue;
6266
6588
  }
6267
- const delta = validateManifestCandidate(c, parseResult.parsed, absRoot, registry);
6589
+ const delta = validateManifestCandidate(
6590
+ c,
6591
+ parseResult.parsed,
6592
+ absRoot,
6593
+ registry,
6594
+ strictConformance
6595
+ );
6268
6596
  errors += delta.errors;
6269
6597
  warnings += delta.warnings;
6270
6598
  }
@@ -6275,12 +6603,12 @@ function findWorkspaceManifests(rootPath) {
6275
6603
  function walk(dir) {
6276
6604
  let entries;
6277
6605
  try {
6278
- entries = fs11__default.readdirSync(dir, { withFileTypes: true });
6606
+ entries = fs12__default.readdirSync(dir, { withFileTypes: true });
6279
6607
  } catch {
6280
6608
  return;
6281
6609
  }
6282
6610
  for (const entry of entries) {
6283
- const full = path13__default.join(dir, entry.name);
6611
+ const full = path14__default.join(dir, entry.name);
6284
6612
  if (entry.isDirectory()) {
6285
6613
  if (!SKIP_DIRS.has(entry.name)) walk(full);
6286
6614
  } else if (entry.isFile() && /(^|\.)skaile\.yaml$/.test(entry.name)) {
@@ -6343,14 +6671,14 @@ function validateWorkspaceAssets(parsed, relPath) {
6343
6671
  return errors;
6344
6672
  }
6345
6673
  function validateWorkspaceManifests(rootPath) {
6346
- const absRoot = path13__default.resolve(rootPath);
6674
+ const absRoot = path14__default.resolve(rootPath);
6347
6675
  const files = findWorkspaceManifests(absRoot);
6348
6676
  let errors = 0;
6349
6677
  for (const file of files) {
6350
- const relPath = path13__default.relative(absRoot, file);
6678
+ const relPath = path14__default.relative(absRoot, file);
6351
6679
  let parsed;
6352
6680
  try {
6353
- parsed = parse(fs11__default.readFileSync(file, "utf-8")) ?? {};
6681
+ parsed = parse(fs12__default.readFileSync(file, "utf-8")) ?? {};
6354
6682
  } catch (e) {
6355
6683
  logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
6356
6684
  errors++;
@@ -6364,34 +6692,34 @@ function validateWorkspaceManifests(rootPath) {
6364
6692
  var EXCLUDED_DOMAINS = /* @__PURE__ */ new Set(["skaileup-shared", "external", "docs"]);
6365
6693
  function collectAssetVersions() {
6366
6694
  const assets = [];
6367
- if (!fs11__default.existsSync(AI_RESOURCES)) return assets;
6368
- const domains = fs11__default.readdirSync(AI_RESOURCES, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DOMAINS.has(d.name));
6695
+ if (!fs12__default.existsSync(AI_RESOURCES)) return assets;
6696
+ const domains = fs12__default.readdirSync(AI_RESOURCES, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DOMAINS.has(d.name));
6369
6697
  for (const d of domains) {
6370
- const domainDir = path13__default.join(AI_RESOURCES, d.name);
6371
- const skillsDir = path13__default.join(domainDir, "skills");
6372
- if (fs11__default.existsSync(skillsDir)) {
6698
+ const domainDir = path14__default.join(AI_RESOURCES, d.name);
6699
+ const skillsDir = path14__default.join(domainDir, "skills");
6700
+ if (fs12__default.existsSync(skillsDir)) {
6373
6701
  collectSkillVersions(skillsDir, d.name, assets);
6374
6702
  }
6375
- const agentsDir = path13__default.join(domainDir, "agents");
6376
- if (fs11__default.existsSync(agentsDir)) {
6703
+ const agentsDir = path14__default.join(domainDir, "agents");
6704
+ if (fs12__default.existsSync(agentsDir)) {
6377
6705
  collectAgentVersions(agentsDir, d.name, assets);
6378
6706
  }
6379
- const flowsDir = path13__default.join(domainDir, "flows");
6380
- if (fs11__default.existsSync(flowsDir)) {
6707
+ const flowsDir = path14__default.join(domainDir, "flows");
6708
+ if (fs12__default.existsSync(flowsDir)) {
6381
6709
  collectFlowVersions(flowsDir, d.name, assets);
6382
6710
  }
6383
- const promptsDir = path13__default.join(domainDir, "prompts");
6384
- if (fs11__default.existsSync(promptsDir)) {
6711
+ const promptsDir = path14__default.join(domainDir, "prompts");
6712
+ if (fs12__default.existsSync(promptsDir)) {
6385
6713
  collectPromptVersions(promptsDir, d.name, assets);
6386
6714
  }
6387
6715
  }
6388
6716
  return assets;
6389
6717
  }
6390
6718
  function collectFlowVersions(dir, domain, out) {
6391
- for (const f of fs11__default.readdirSync(dir)) {
6719
+ for (const f of fs12__default.readdirSync(dir)) {
6392
6720
  if (!f.endsWith(".flow.yaml")) continue;
6393
- const fp = path13__default.join(dir, f);
6394
- const content = fs11__default.readFileSync(fp, "utf-8");
6721
+ const fp = path14__default.join(dir, f);
6722
+ const content = fs12__default.readFileSync(fp, "utf-8");
6395
6723
  const parsed = parse(content);
6396
6724
  out.push({
6397
6725
  kind: "flow",
@@ -6403,10 +6731,10 @@ function collectFlowVersions(dir, domain, out) {
6403
6731
  }
6404
6732
  }
6405
6733
  function collectPromptVersions(dir, domain, out) {
6406
- for (const f of fs11__default.readdirSync(dir)) {
6734
+ for (const f of fs12__default.readdirSync(dir)) {
6407
6735
  if (!f.endsWith(".prompt.md")) continue;
6408
- const fp = path13__default.join(dir, f);
6409
- const content = fs11__default.readFileSync(fp, "utf-8");
6736
+ const fp = path14__default.join(dir, f);
6737
+ const content = fs12__default.readFileSync(fp, "utf-8");
6410
6738
  const fm = parseSkillFrontmatter(content);
6411
6739
  out.push({
6412
6740
  kind: "prompt",
@@ -6418,12 +6746,12 @@ function collectPromptVersions(dir, domain, out) {
6418
6746
  }
6419
6747
  }
6420
6748
  function collectSkillVersions(dir, domain, out) {
6421
- for (const entry of fs11__default.readdirSync(dir, { withFileTypes: true })) {
6749
+ for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
6422
6750
  if (!entry.isDirectory()) continue;
6423
- const full = path13__default.join(dir, entry.name);
6424
- const skillMd = path13__default.join(full, "SKILL.md");
6425
- if (fs11__default.existsSync(skillMd)) {
6426
- const content = fs11__default.readFileSync(skillMd, "utf-8");
6751
+ const full = path14__default.join(dir, entry.name);
6752
+ const skillMd = path14__default.join(full, "SKILL.md");
6753
+ if (fs12__default.existsSync(skillMd)) {
6754
+ const content = fs12__default.readFileSync(skillMd, "utf-8");
6427
6755
  const fm = parseSkillFrontmatter(content);
6428
6756
  out.push({
6429
6757
  kind: "skill",
@@ -6438,11 +6766,11 @@ function collectSkillVersions(dir, domain, out) {
6438
6766
  }
6439
6767
  }
6440
6768
  function collectAgentVersions(dir, domain, out) {
6441
- for (const entry of fs11__default.readdirSync(dir, { withFileTypes: true })) {
6769
+ for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
6442
6770
  if (!entry.isDirectory()) continue;
6443
- const agentYaml = path13__default.join(dir, entry.name, "agent.yaml");
6444
- if (!fs11__default.existsSync(agentYaml)) continue;
6445
- const content = fs11__default.readFileSync(agentYaml, "utf-8");
6771
+ const agentYaml = path14__default.join(dir, entry.name, "agent.yaml");
6772
+ if (!fs12__default.existsSync(agentYaml)) continue;
6773
+ const content = fs12__default.readFileSync(agentYaml, "utf-8");
6446
6774
  const parsed = parse(content);
6447
6775
  out.push({
6448
6776
  kind: "agent",
@@ -6473,7 +6801,7 @@ function filterToChangedAssets(assets) {
6473
6801
  encoding: "utf-8"
6474
6802
  });
6475
6803
  const changedFiles = new Set(
6476
- diffOutput.trim().split("\n").filter(Boolean).map((f) => path13__default.resolve(AI_RESOURCES, f))
6804
+ diffOutput.trim().split("\n").filter(Boolean).map((f) => path14__default.resolve(AI_RESOURCES, f))
6477
6805
  );
6478
6806
  return assets.filter((a) => changedFiles.has(a.filePath));
6479
6807
  } catch {
@@ -6499,7 +6827,7 @@ function checkVersionBumps(assets) {
6499
6827
  let warnings = 0;
6500
6828
  for (const a of assets) {
6501
6829
  if (!a.version) continue;
6502
- const relPath = path13__default.relative(AI_RESOURCES, a.filePath);
6830
+ const relPath = path14__default.relative(AI_RESOURCES, a.filePath);
6503
6831
  try {
6504
6832
  const headContent = execSync(`git show HEAD:${relPath}`, {
6505
6833
  cwd: AI_RESOURCES,
@@ -6525,7 +6853,7 @@ function checkFlowVersionPins(assets) {
6525
6853
  }
6526
6854
  let errors = 0;
6527
6855
  for (const f of flows) {
6528
- const content = fs11__default.readFileSync(f.filePath, "utf-8");
6856
+ const content = fs12__default.readFileSync(f.filePath, "utf-8");
6529
6857
  const parsed = parse(content);
6530
6858
  const nodes = (parsed?.nodes ?? []).filter((n) => n.type === "skill" && n.data?.version).map((n) => ({
6531
6859
  nodeId: n.id,
@@ -6571,14 +6899,21 @@ function makeValidateCommand() {
6571
6899
  const cmd = new Command("validate").description(
6572
6900
  "Validate asset manifests, versions, and changelogs"
6573
6901
  );
6574
- cmd.argument("[path]", "Path to asset repo or directory to validate", ".").action((targetPath) => {
6575
- const absPath = path13__default.resolve(targetPath);
6902
+ cmd.argument("[path]", "Path to asset repo or directory to validate", ".").option(
6903
+ "--strict-conformance",
6904
+ "Treat Agent Skills (agentskills.io) standard findings as errors"
6905
+ ).action((targetPath, opts) => {
6906
+ const absPath = path14__default.resolve(targetPath);
6576
6907
  logInfo(`Validating manifests in ${absPath}`);
6577
- const { total, errors } = validateManifests(absPath);
6908
+ const { total, errors, warnings } = validateManifests(
6909
+ absPath,
6910
+ opts.strictConformance ?? false
6911
+ );
6578
6912
  const ws = validateWorkspaceManifests(absPath);
6579
6913
  const totalErrors = errors + ws.errors;
6580
6914
  console.log();
6581
6915
  logInfo(`Scanned ${total} asset manifest(s) and ${ws.total} skaile.yaml file(s)`);
6916
+ if (warnings > 0) logWarn(`${warnings} conformance warning(s)`);
6582
6917
  if (totalErrors === 0) {
6583
6918
  logOk("All manifests valid");
6584
6919
  } else {
@@ -6618,7 +6953,7 @@ function makeValidateCommand() {
6618
6953
  let errors = 0;
6619
6954
  for (const domain of modifiedDomains) {
6620
6955
  const changelogModified = modifiedFiles.some(
6621
- (f) => f === `${domain}/CHANGELOG.md` || f === path13__default.join(domain, "CHANGELOG.md")
6956
+ (f) => f === `${domain}/CHANGELOG.md` || f === path14__default.join(domain, "CHANGELOG.md")
6622
6957
  );
6623
6958
  if (changelogModified) {
6624
6959
  logOk(`${domain}/CHANGELOG.md updated`);
@@ -6700,7 +7035,7 @@ function makeVerifyCommand() {
6700
7035
  }
6701
7036
  function makeWhyCommand() {
6702
7037
  return new Command("why").description("Show why an asset is installed (dependency chain)").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
6703
- const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
7038
+ const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
6704
7039
  const chain = am2.why(ref);
6705
7040
  if (chain.length === 0) {
6706
7041
  logErr(`${ref} not found in lock file. Run \`skaile install\` first.`);
@@ -6721,7 +7056,7 @@ function makeWhyCommand() {
6721
7056
  var _defaultFormatHelp = Help.prototype.formatHelp;
6722
7057
  var pkg = JSON.parse(
6723
7058
  readFileSync(
6724
- path13__default.resolve(path13__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
7059
+ path14__default.resolve(path14__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
6725
7060
  "utf-8"
6726
7061
  )
6727
7062
  );
@@ -6842,7 +7177,7 @@ program.command("init [project-dir]").description("Initialize a project director
6842
7177
  (projectDir, opts) => runInit(projectDir, opts)
6843
7178
  );
6844
7179
  async function runInit(projectDir, opts) {
6845
- const { mkdirSync: mkdirSync3, writeFileSync: writeFileSync2 } = await import('fs');
7180
+ const { mkdirSync: mkdirSync6, writeFileSync: writeFileSync4 } = await import('fs');
6846
7181
  const { stringify } = await import('yaml');
6847
7182
  const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
6848
7183
  const backend = opts.backend;
@@ -6851,33 +7186,33 @@ async function runInit(projectDir, opts) {
6851
7186
  process.exitCode = 1;
6852
7187
  return;
6853
7188
  }
6854
- const resolved = path13__default.resolve(projectDir ?? ".");
6855
- const projectName = path13__default.basename(resolved);
7189
+ const resolved = path14__default.resolve(projectDir ?? ".");
7190
+ const projectName = path14__default.basename(resolved);
6856
7191
  const created = [];
6857
- const { existsSync: existsSync13 } = await import('fs');
6858
- if (!existsSync13(resolved)) {
6859
- mkdirSync3(resolved, { recursive: true });
7192
+ const { existsSync: existsSync14 } = await import('fs');
7193
+ if (!existsSync14(resolved)) {
7194
+ mkdirSync6(resolved, { recursive: true });
6860
7195
  created.push(".");
6861
7196
  }
6862
- const skaileDir = path13__default.join(resolved, ".skaile");
6863
- if (!existsSync13(skaileDir)) {
6864
- mkdirSync3(path13__default.join(skaileDir, "sessions"), { recursive: true });
7197
+ const skaileDir = path14__default.join(resolved, ".skaile");
7198
+ if (!existsSync14(skaileDir)) {
7199
+ mkdirSync6(path14__default.join(skaileDir, "sessions"), { recursive: true });
6865
7200
  created.push(".skaile/");
6866
7201
  }
6867
- const settingsPath = path13__default.join(skaileDir, "settings.json");
6868
- if (!existsSync13(settingsPath)) {
6869
- writeFileSync2(settingsPath, "{}\n");
7202
+ const settingsPath = path14__default.join(skaileDir, "settings.json");
7203
+ if (!existsSync14(settingsPath)) {
7204
+ writeFileSync4(settingsPath, "{}\n");
6870
7205
  created.push(".skaile/settings.json");
6871
7206
  }
6872
- const wsConfigPath = path13__default.join(resolved, "skaile.yaml");
6873
- if (!existsSync13(wsConfigPath)) {
6874
- writeFileSync2(wsConfigPath, stringify(buildInitWorkspaceConfig(projectName, backend)));
7207
+ const wsConfigPath = path14__default.join(resolved, "skaile.yaml");
7208
+ if (!existsSync14(wsConfigPath)) {
7209
+ writeFileSync4(wsConfigPath, stringify(buildInitWorkspaceConfig(projectName, backend)));
6875
7210
  created.push("skaile.yaml");
6876
7211
  }
6877
7212
  for (const dir of new Set(Object.values(DRIVER_TARGETS[backend].local))) {
6878
- const full = path13__default.join(resolved, dir);
6879
- if (!existsSync13(full)) {
6880
- mkdirSync3(full, { recursive: true });
7213
+ const full = path14__default.join(resolved, dir);
7214
+ if (!existsSync14(full)) {
7215
+ mkdirSync6(full, { recursive: true });
6881
7216
  created.push(`${dir}/`);
6882
7217
  }
6883
7218
  }
@@ -6907,8 +7242,8 @@ function buildInitWorkspaceConfig(projectName, backend) {
6907
7242
  }
6908
7243
  async function initGitScaffold(resolved, created) {
6909
7244
  const { execSync: execSync3 } = await import('child_process');
6910
- const { existsSync: existsSync13, readFileSync: readFileSync6, writeFileSync: writeFileSync2 } = await import('fs');
6911
- const gitignorePath = path13__default.join(resolved, ".gitignore");
7245
+ const { existsSync: existsSync14, readFileSync: readFileSync8, writeFileSync: writeFileSync4 } = await import('fs');
7246
+ const gitignorePath = path14__default.join(resolved, ".gitignore");
6912
7247
  const entries = [
6913
7248
  "node_modules/",
6914
7249
  ".skaile/sessions/",
@@ -6917,16 +7252,16 @@ async function initGitScaffold(resolved, created) {
6917
7252
  ".env",
6918
7253
  ".env.local"
6919
7254
  ];
6920
- const existing = existsSync13(gitignorePath) ? readFileSync6(gitignorePath, "utf-8") : "";
7255
+ const existing = existsSync14(gitignorePath) ? readFileSync8(gitignorePath, "utf-8") : "";
6921
7256
  const have = new Set(existing.split("\n").map((l) => l.trim()));
6922
7257
  const append = entries.filter((e) => !have.has(e));
6923
7258
  if (append.length > 0) {
6924
7259
  const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
6925
- writeFileSync2(gitignorePath, `${existing + prefix}${append.join("\n")}
7260
+ writeFileSync4(gitignorePath, `${existing + prefix}${append.join("\n")}
6926
7261
  `);
6927
7262
  if (!existing) created.push(".gitignore");
6928
7263
  }
6929
- if (!existsSync13(path13__default.join(resolved, ".git"))) {
7264
+ if (!existsSync14(path14__default.join(resolved, ".git"))) {
6930
7265
  try {
6931
7266
  execSync3("git init", { cwd: resolved, stdio: "pipe" });
6932
7267
  created.push(".git/");
@@ -6938,10 +7273,10 @@ async function initGitScaffold(resolved, created) {
6938
7273
  }
6939
7274
  async function bootstrapUserConfig() {
6940
7275
  try {
6941
- const fs12 = await import('fs');
7276
+ const fs13 = await import('fs');
6942
7277
  const { userConfigPath, saveConfig, getConfigDefaults } = await import('../library/index.js');
6943
7278
  const userCfgPath = userConfigPath();
6944
- if (!fs12.existsSync(userCfgPath)) {
7279
+ if (!fs13.existsSync(userCfgPath)) {
6945
7280
  const defaults = getConfigDefaults();
6946
7281
  saveConfig(userCfgPath, {
6947
7282
  catalog: { url: defaults.catalog.url, cache_ttl: defaults.catalog.cache_ttl }
@@ -6956,7 +7291,7 @@ async function bootstrapUserConfig() {
6956
7291
  }
6957
7292
  async function hydrateInitSources(resolved, created) {
6958
7293
  try {
6959
- const { ensureSourcesCloned } = await import('../ensure-sources-NSDMTAWN.js');
7294
+ const { ensureSourcesCloned } = await import('../ensure-sources-KLCGXVE6.js');
6960
7295
  const hydrate = ensureSourcesCloned(resolved, { quiet: true });
6961
7296
  for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
6962
7297
  if (hydrate.failed.length > 0) {
@@ -6972,7 +7307,7 @@ function printInitSummary(resolved, projectDir, created) {
6972
7307
  logOk(`Initialized project at ${S.heading(resolved)}`);
6973
7308
  console.log();
6974
7309
  console.log(S.heading(" Next steps:"));
6975
- const isCurrentDir = resolved === path13__default.resolve(".");
7310
+ const isCurrentDir = resolved === path14__default.resolve(".");
6976
7311
  let step = 1;
6977
7312
  if (!isCurrentDir) {
6978
7313
  console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
@@ -6984,7 +7319,7 @@ function printInitSummary(resolved, projectDir, created) {
6984
7319
  console.log();
6985
7320
  }
6986
7321
  program.command("setup").description("Interactive provider setup wizard").action(async () => {
6987
- const { cmdSetup } = await import('../setup-VGZTFQ32.js');
7322
+ const { cmdSetup } = await import('../setup-AYH6SR4U.js');
6988
7323
  await cmdSetup([], { projectDir: process.cwd() });
6989
7324
  });
6990
7325
  program.addCommand(makeInstallCommand());