docks-kit 0.16.9 → 0.16.10

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.
@@ -11,9 +11,19 @@ import { compareCodepoints, deepMerge, isObject, jqStringify, parseJson, readJso
11
11
  import { field } from "./toolchain"
12
12
  import { payloadText } from "../payload"
13
13
 
14
- async function cli(args: Array<string>): Promise<{ ok: boolean; out: string }> {
14
+ async function cli(args: Array<string>): Promise<{ ok: boolean; out: string; detail: string }> {
15
15
  const res = await spawnProcess("claude", args, { stdio: ["ignore", "pipe", "pipe"] })
16
- return { ok: res.error === undefined && res.exitCode === 0, out: `${res.stdout}${res.stderr}` }
16
+ // A spawn error carries its cause in `error`, not in either stream, and that
17
+ // is the case a failure message cannot afford to drop: it names an
18
+ // unresolvable launcher instead of a rejected command.
19
+ const out = res.error !== undefined ? res.error.message : `${res.stdout}${res.stderr}`
20
+ const detail = out.split("\n").map((line) => line.trim()).find((line) => line !== "") ?? "unknown error"
21
+ return { ok: res.error === undefined && res.exitCode === 0, out, detail }
22
+ }
23
+
24
+ /** Failure message tail: the cause, then the command to re-run by hand. */
25
+ function manually(detail: string, args: Array<string>): string {
26
+ return `${detail}; run manually: claude ${args.join(" ")}`
17
27
  }
18
28
 
19
29
  function sortedKeys(obj: Json | undefined): Array<string> {
@@ -96,7 +106,10 @@ export async function syncPlugins(ctx: Ctx, claudeDir: string): Promise<void> {
96
106
  if (marketplaceResult.ok) {
97
107
  addedMp++
98
108
  } else {
99
- recordFailure(ctx, `Failed to add marketplace: ${mpName} (${repo})`)
109
+ recordFailure(
110
+ ctx,
111
+ `Failed to add marketplace: ${mpName} (${repo}): ${manually(marketplaceResult.detail, ["plugin", "marketplace", "add", repo])}`
112
+ )
100
113
  f1++
101
114
  }
102
115
  }
@@ -117,7 +130,10 @@ export async function syncPlugins(ctx: Ctx, claudeDir: string): Promise<void> {
117
130
  const refreshResult = await cli(["plugin", "marketplace", "update", mpName])
118
131
  clearProgress()
119
132
  if (!refreshResult.ok) {
120
- recordFailure(ctx, `Failed to refresh marketplace: ${mpName}`)
133
+ recordFailure(
134
+ ctx,
135
+ `Failed to refresh marketplace: ${mpName}: ${manually(refreshResult.detail, ["plugin", "marketplace", "update", mpName])}`
136
+ )
121
137
  f3++
122
138
  }
123
139
  refreshedMarketplaces.add(mpName)
@@ -128,7 +144,10 @@ export async function syncPlugins(ctx: Ctx, claudeDir: string): Promise<void> {
128
144
  if (installResult.ok) {
129
145
  addedPl++
130
146
  } else {
131
- recordFailure(ctx, `Failed to install plugin: ${pluginId}`)
147
+ recordFailure(
148
+ ctx,
149
+ `Failed to install plugin: ${pluginId}: ${manually(installResult.detail, ["plugin", "install", pluginId])}`
150
+ )
132
151
  f2++
133
152
  }
134
153
  }
@@ -162,7 +181,10 @@ export async function syncPlugins(ctx: Ctx, claudeDir: string): Promise<void> {
162
181
  clearProgress()
163
182
  refreshedMarketplaces.add(mpName)
164
183
  if (!refreshResult.ok) {
165
- recordFailure(ctx, `Failed to refresh marketplace: ${mpName}`)
184
+ recordFailure(
185
+ ctx,
186
+ `Failed to refresh marketplace: ${mpName}: ${manually(refreshResult.detail, ["plugin", "marketplace", "update", mpName])}`
187
+ )
166
188
  f3++
167
189
  }
168
190
  }
@@ -173,7 +195,10 @@ export async function syncPlugins(ctx: Ctx, claudeDir: string): Promise<void> {
173
195
  const updateResult = await cli(["plugin", "update", pluginId, "--scope", "user"])
174
196
  clearProgress()
175
197
  if (!updateResult.ok) {
176
- recordFailure(ctx, `Failed to update plugin: ${pluginId}`)
198
+ recordFailure(
199
+ ctx,
200
+ `Failed to update plugin: ${pluginId}: ${manually(updateResult.detail, ["plugin", "update", pluginId, "--scope", "user"])}`
201
+ )
177
202
  f4++
178
203
  } else if (updateResult.out.includes("Successfully updated")) {
179
204
  updatedPl++
@@ -196,7 +221,10 @@ export async function syncPlugins(ctx: Ctx, claudeDir: string): Promise<void> {
196
221
  if (uninstallResult.ok) {
197
222
  removedPl++
198
223
  } else {
199
- recordFailure(ctx, `Failed to uninstall plugin: ${pluginId}`)
224
+ recordFailure(
225
+ ctx,
226
+ `Failed to uninstall plugin: ${pluginId}: ${manually(uninstallResult.detail, ["plugin", "uninstall", "-y", "--scope", "user", pluginId])}`
227
+ )
200
228
  f5++
201
229
  }
202
230
  }
@@ -212,7 +240,10 @@ export async function syncPlugins(ctx: Ctx, claudeDir: string): Promise<void> {
212
240
  if (removeResult.ok) {
213
241
  removedMp++
214
242
  } else {
215
- recordFailure(ctx, `Failed to remove marketplace: ${mpName}`)
243
+ recordFailure(
244
+ ctx,
245
+ `Failed to remove marketplace: ${mpName}: ${manually(removeResult.detail, ["plugin", "marketplace", "remove", mpName])}`
246
+ )
216
247
  f6++
217
248
  }
218
249
  }
@@ -247,10 +278,14 @@ async function reassertEnabledState(ctx: Ctx, repoObj: { [k: string]: Json }, us
247
278
  const user = readJsonFile(userSettingsFile)
248
279
  const enabled = user !== undefined && isObject(user) && isObject(user["enabledPlugins"]) ? (user["enabledPlugins"] as { [k: string]: Json })[pluginId] : undefined
249
280
  if (enabled !== true) continue
250
- if ((await cli(["plugin", "disable", pluginId])).ok) {
281
+ const disableResult = await cli(["plugin", "disable", pluginId])
282
+ if (disableResult.ok) {
251
283
  cliDisabled = true
252
284
  } else {
253
- recordFailure(ctx, `Failed to disable SoT-false plugin: ${pluginId} (will retry next sync)`)
285
+ recordFailure(
286
+ ctx,
287
+ `Failed to disable SoT-false plugin: ${pluginId} (will retry next sync): ${manually(disableResult.detail, ["plugin", "disable", pluginId])}`
288
+ )
254
289
  }
255
290
  }
256
291
 
@@ -1,7 +1,7 @@
1
1
  // Generated by cli/scripts/generate-sot-payload.ts. DO NOT EDIT.
2
2
  // Edit SoT/, notification.mp3, or package.json, then run: bun cli/scripts/generate-sot-payload.ts
3
3
 
4
- export const GENERATED_PACKAGE_VERSION = "0.16.9"
4
+ export const GENERATED_PACKAGE_VERSION = "0.16.10"
5
5
 
6
6
  export const GENERATED_PAYLOAD_TEXT = {
7
7
  "SoT/.agents/skills.txt": "# Universal AI-agent skill manifest intentionally empty.\n# Global skill discovery is opt-in: add one <owner>/<repo> slug per line.\n# EngineNative ignores comments and blank lines.\n",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docks-kit",
3
- "version": "0.16.9",
3
+ "version": "0.16.10",
4
4
  "description": "Portable AI coding agent config kit — SoT sync engine + typed CLI for Claude Code, Codex, and universal agent skills",
5
5
  "type": "module",
6
6
  "license": "MIT",