claudekit-cli 3.42.2-dev.4 → 3.42.2-dev.6

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.
package/cli-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "3.42.2-dev.4",
3
- "generatedAt": "2026-04-29T21:26:47.128Z",
2
+ "version": "3.42.2-dev.6",
3
+ "generatedAt": "2026-05-04T15:17:33.645Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
package/dist/index.js CHANGED
@@ -7054,7 +7054,7 @@ function convertFmToCodexToml(item) {
7054
7054
  if (modelResult.resolved) {
7055
7055
  lines.push(`model = ${JSON.stringify(modelResult.resolved.model)}`);
7056
7056
  if (modelResult.resolved.effort) {
7057
- lines.push(`# effort = ${JSON.stringify(modelResult.resolved.effort)}`);
7057
+ lines.push(`model_reasoning_effort = ${JSON.stringify(modelResult.resolved.effort)}`);
7058
7058
  }
7059
7059
  } else if (typeof item.frontmatter.model === "string" && item.frontmatter.model.trim().length > 0 && item.frontmatter.model.trim() !== "inherit") {
7060
7060
  lines.push(`# model = ${JSON.stringify(item.frontmatter.model.trim())}`);
@@ -12460,6 +12460,9 @@ function getReasonCopy(code, _ctx) {
12460
12460
  return "Target state unavailable while CK changed — manual review required";
12461
12461
  }
12462
12462
  }
12463
+ function providerConfigAppliesToType(config, type) {
12464
+ return config.types === undefined || config.types.includes(type);
12465
+ }
12463
12466
  var UNKNOWN_CHECKSUM = "unknown";
12464
12467
 
12465
12468
  // src/commands/portable/portable-registry.ts
@@ -43801,6 +43804,26 @@ function repairClaudeNodeCommandPath(cmd, root) {
43801
43804
  const command = formatCanonicalClaudeCommand(nodePrefix, root, relativePath, suffix);
43802
43805
  return { command, changed: command !== cmd, issue: "invalid-format" };
43803
43806
  }
43807
+ const absoluteMatch = cmd.match(/^(node\s+)"((?:[A-Za-z]:[/\\]|\/)[^"]*?[/\\]\.claude[/\\][^"]+)"(.*)$/) ?? cmd.match(/^(node\s+)((?:[A-Za-z]:[\\/]|\/)[^\s"]*?[\\/]\.claude[\\/][^\s"]+)(.*)$/);
43808
+ if (absoluteMatch) {
43809
+ const [, nodePrefix, absolutePath, suffix] = absoluteMatch;
43810
+ const normalizedAbsPath = absolutePath.replace(/\\/g, "/");
43811
+ const dotClaudeIdx = normalizedAbsPath.indexOf("/.claude/");
43812
+ if (dotClaudeIdx === -1) {
43813
+ return { command: cmd, changed: false, issue: null };
43814
+ }
43815
+ const isWin2 = process.platform === "win32";
43816
+ const cmp = (s) => isWin2 ? s.toLowerCase() : s;
43817
+ const globalRoots = [
43818
+ `${homedir11().replace(/\\/g, "/").replace(/\/+$/, "")}/.claude/`,
43819
+ `${PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "")}/`
43820
+ ];
43821
+ const isUnderGlobal = globalRoots.some((g2) => cmp(normalizedAbsPath).startsWith(cmp(g2)));
43822
+ const resolvedRoot = isUnderGlobal ? "$HOME" : root;
43823
+ const relativePath = normalizedAbsPath.slice(dotClaudeIdx + 1);
43824
+ const command = formatCanonicalClaudeCommand(nodePrefix, resolvedRoot, relativePath, suffix);
43825
+ return { command, changed: command !== cmd, issue: "invalid-format" };
43826
+ }
43804
43827
  return { command: cmd, changed: false, issue: null };
43805
43828
  }
43806
43829
  function normalizeCommand(cmd) {
@@ -51084,6 +51107,74 @@ var init_commands_discovery = __esm(() => {
51084
51107
  SKIP_DIRS2 = ["node_modules", ".git", "dist", "build"];
51085
51108
  });
51086
51109
 
51110
+ // src/commands/migrate/migrate-provider-scopes.ts
51111
+ function portableTypeToGroup(type) {
51112
+ return TYPE_TO_GROUP[type];
51113
+ }
51114
+ function portableGroupToType(group) {
51115
+ return GROUP_TO_TYPE[group];
51116
+ }
51117
+ function getEnabledPortableTypes(include) {
51118
+ return RECONCILE_PORTABLE_TYPES.filter((type) => include[portableTypeToGroup(type)]);
51119
+ }
51120
+ function resolvePortableTypeGlobal(provider, type, requestedGlobal) {
51121
+ if (requestedGlobal)
51122
+ return true;
51123
+ const providerConfig = providers[provider];
51124
+ const group = portableTypeToGroup(type);
51125
+ const pathConfig = providerConfig?.[group];
51126
+ if (pathConfig?.projectPath === null && pathConfig.globalPath !== null) {
51127
+ return true;
51128
+ }
51129
+ return false;
51130
+ }
51131
+ function resolvePortableGroupGlobal(provider, group, requestedGlobal) {
51132
+ return resolvePortableTypeGlobal(provider, portableGroupToType(group), requestedGlobal);
51133
+ }
51134
+ function buildScopedProviderConfigs(selectedProviders, include, requestedGlobal) {
51135
+ const enabledTypes = getEnabledPortableTypes(include);
51136
+ const configs = [];
51137
+ for (const provider of selectedProviders) {
51138
+ const typesByScope = new Map;
51139
+ for (const type of enabledTypes) {
51140
+ const isGlobal = resolvePortableTypeGlobal(provider, type, requestedGlobal);
51141
+ typesByScope.set(isGlobal, [...typesByScope.get(isGlobal) ?? [], type]);
51142
+ }
51143
+ for (const [global3, types4] of typesByScope) {
51144
+ configs.push({ provider, global: global3, types: types4 });
51145
+ }
51146
+ }
51147
+ return configs;
51148
+ }
51149
+ var RECONCILE_PORTABLE_TYPES, TYPE_TO_GROUP, GROUP_TO_TYPE;
51150
+ var init_migrate_provider_scopes = __esm(() => {
51151
+ init_provider_registry();
51152
+ RECONCILE_PORTABLE_TYPES = [
51153
+ "agent",
51154
+ "command",
51155
+ "skill",
51156
+ "config",
51157
+ "rules",
51158
+ "hooks"
51159
+ ];
51160
+ TYPE_TO_GROUP = {
51161
+ agent: "agents",
51162
+ command: "commands",
51163
+ skill: "skills",
51164
+ config: "config",
51165
+ rules: "rules",
51166
+ hooks: "hooks"
51167
+ };
51168
+ GROUP_TO_TYPE = {
51169
+ agents: "agent",
51170
+ commands: "command",
51171
+ skills: "skill",
51172
+ config: "config",
51173
+ rules: "rules",
51174
+ hooks: "hooks"
51175
+ };
51176
+ });
51177
+
51087
51178
  // src/commands/migrate/skill-directory-installer.ts
51088
51179
  import { existsSync as existsSync21 } from "node:fs";
51089
51180
  import { cp, mkdir as mkdir8, rename as rename5, rm as rm4 } from "node:fs/promises";
@@ -54668,11 +54759,13 @@ function buildSourceItemState(item, type, selectedProviders, options2) {
54668
54759
  }
54669
54760
  function buildTypeDirectoryStates(providerConfigs, types4) {
54670
54761
  const results = [];
54671
- for (const { provider, global: isGlobal } of providerConfigs) {
54762
+ for (const { provider, global: isGlobal, types: configTypes } of providerConfigs) {
54672
54763
  const providerConfig = providers[provider];
54673
54764
  if (!providerConfig)
54674
54765
  continue;
54675
54766
  for (const type of types4) {
54767
+ if (configTypes !== undefined && !configTypes.includes(type))
54768
+ continue;
54676
54769
  const pathKey = portableTypeToProviderPathKey(type);
54677
54770
  const pathConfig = providerConfig[pathKey];
54678
54771
  if (!pathConfig)
@@ -54846,16 +54939,26 @@ function makeDirStateKey(provider, type, global3) {
54846
54939
  return JSON.stringify([provider, type, global3]);
54847
54940
  }
54848
54941
  function dedupeProviderConfigs(providerConfigs) {
54849
- const seen = new Set;
54850
- const unique = [];
54942
+ const unique = new Map;
54851
54943
  for (const config of providerConfigs) {
54852
54944
  const key = makeProviderConfigKey(config.provider, config.global);
54853
- if (seen.has(key))
54945
+ const existing = unique.get(key);
54946
+ if (!existing) {
54947
+ unique.set(key, config.types ? { ...config, types: [...config.types] } : { ...config });
54854
54948
  continue;
54855
- seen.add(key);
54856
- unique.push(config);
54949
+ }
54950
+ if (existing.types === undefined || config.types === undefined) {
54951
+ existing.types = undefined;
54952
+ continue;
54953
+ }
54954
+ existing.types = Array.from(new Set([...existing.types, ...config.types]));
54857
54955
  }
54858
- return unique;
54956
+ return Array.from(unique.values());
54957
+ }
54958
+ function providerConfigIsActiveForEntry(providerConfigs, entry, options2 = {}) {
54959
+ if (options2.emptyMeansAll && providerConfigs.length === 0)
54960
+ return true;
54961
+ return providerConfigs.some((config) => config.provider === entry.provider && config.global === entry.global && providerConfigAppliesToType(config, entry.type));
54859
54962
  }
54860
54963
  function buildTargetStateIndex(targetStates) {
54861
54964
  const index = new Map;
@@ -55044,6 +55147,8 @@ function reconcile(input) {
55044
55147
  actions.push(...sectionRenames);
55045
55148
  for (const sourceItem of input.sourceItems) {
55046
55149
  for (const providerConfig of uniqueProviderConfigs) {
55150
+ if (!providerConfigAppliesToType(providerConfig, sourceItem.type))
55151
+ continue;
55047
55152
  const action = determineAction(sourceItem, providerConfig, input, targetStateIndex, deletedIdentityKeys);
55048
55153
  actions.push(action);
55049
55154
  }
@@ -55307,13 +55412,12 @@ function findRegistryEntry(source, providerConfig, registry) {
55307
55412
  function detectOrphans(input, renamedFromKeys) {
55308
55413
  const actions = [];
55309
55414
  const sourceItemKeys = new Set(input.sourceItems.map((s) => makeItemTypeKey(s.item, s.type)));
55310
- const activeProviderKeys = new Set(input.providerConfigs.map((provider) => makeProviderConfigKey(provider.provider, provider.global)));
55415
+ const activeProviderConfigs = dedupeProviderConfigs(input.providerConfigs);
55311
55416
  const hasConfigSource = input.sourceItems.some((source) => source.type === "config");
55312
55417
  for (const entry of input.registry.installations) {
55313
55418
  const key = makeRegistryIdentityKey(entry);
55314
55419
  const sourceItemKey = makeItemTypeKey(entry.item, entry.type);
55315
- const providerKey = makeProviderConfigKey(entry.provider, entry.global);
55316
- if (!activeProviderKeys.has(providerKey))
55420
+ if (!providerConfigIsActiveForEntry(activeProviderConfigs, entry))
55317
55421
  continue;
55318
55422
  if (renamedFromKeys.has(key))
55319
55423
  continue;
@@ -55345,13 +55449,14 @@ function detectRenames(input) {
55345
55449
  return [];
55346
55450
  const applicable = getApplicableEntries(input.manifest.renames, input.registry.appliedManifestVersion, input.manifest.cliVersion);
55347
55451
  const actions = [];
55452
+ const activeProviderConfigs = dedupeProviderConfigs(input.providerConfigs);
55348
55453
  for (const rename8 of applicable) {
55349
55454
  if (hasDotDotSegment(rename8.from) || hasDotDotSegment(rename8.to) || isAbsoluteLike(rename8.from) || isAbsoluteLike(rename8.to)) {
55350
55455
  console.warn(`[!] Skipping suspicious manifest rename: ${rename8.from} -> ${rename8.to}`);
55351
55456
  continue;
55352
55457
  }
55353
55458
  const normalizedFrom = normalizePortablePath(rename8.from);
55354
- const oldEntries = input.registry.installations.filter((e2) => normalizePortablePath(e2.sourcePath) === normalizedFrom);
55459
+ const oldEntries = input.registry.installations.filter((e2) => normalizePortablePath(e2.sourcePath) === normalizedFrom && providerConfigIsActiveForEntry(activeProviderConfigs, e2, { emptyMeansAll: true }));
55355
55460
  for (const oldEntry of oldEntries) {
55356
55461
  const code = "renamed-cleanup";
55357
55462
  actions.push({
@@ -55378,8 +55483,9 @@ function detectPathMigrations(input) {
55378
55483
  return [];
55379
55484
  const applicable = getApplicableEntries(input.manifest.providerPathMigrations, input.registry.appliedManifestVersion, input.manifest.cliVersion);
55380
55485
  const actions = [];
55486
+ const activeProviderConfigs = dedupeProviderConfigs(input.providerConfigs);
55381
55487
  for (const migration of applicable) {
55382
- const affectedEntries = input.registry.installations.filter((e2) => e2.provider === migration.provider && e2.type === migration.type && pathContainsSegments(e2.path, migration.from));
55488
+ const affectedEntries = input.registry.installations.filter((e2) => e2.provider === migration.provider && e2.type === migration.type && pathContainsSegments(e2.path, migration.from) && providerConfigIsActiveForEntry(activeProviderConfigs, e2, { emptyMeansAll: true }));
55383
55489
  for (const entry of affectedEntries) {
55384
55490
  const code = "path-migrated-cleanup";
55385
55491
  actions.push({
@@ -55790,6 +55896,17 @@ function annotateResultsWithCollisions(results, collisions) {
55790
55896
  }
55791
55897
  }
55792
55898
  }
55899
+ function dedupeProviderPathCollisions(collisions) {
55900
+ const unique = new Map;
55901
+ for (const collision of collisions) {
55902
+ const providersKey = [...collision.providers].sort().join("\x00");
55903
+ const key = JSON.stringify([collision.path, collision.portableType, providersKey]);
55904
+ if (!unique.has(key)) {
55905
+ unique.set(key, { ...collision, providers: [...collision.providers] });
55906
+ }
55907
+ }
55908
+ return Array.from(unique.values());
55909
+ }
55793
55910
  var init_migration_result_utils = __esm(() => {
55794
55911
  init_provider_registry();
55795
55912
  });
@@ -56164,6 +56281,19 @@ function providerSupportsType(provider, type) {
56164
56281
  return getProvidersSupporting("hooks").includes(provider);
56165
56282
  return false;
56166
56283
  }
56284
+ function groupProvidersByTypeScope(selectedProviders, type, requestedGlobal) {
56285
+ const grouped = new Map;
56286
+ for (const provider of selectedProviders) {
56287
+ if (!providerSupportsType(provider, type))
56288
+ continue;
56289
+ const global3 = resolvePortableTypeGlobal(provider, type, requestedGlobal);
56290
+ grouped.set(global3, [...grouped.get(global3) ?? [], provider]);
56291
+ }
56292
+ return Array.from(grouped, ([global3, providersForScope]) => ({
56293
+ global: global3,
56294
+ providers: providersForScope
56295
+ }));
56296
+ }
56167
56297
  function createSkippedActionResult(action, reason) {
56168
56298
  const provider = action.provider;
56169
56299
  return {
@@ -56538,17 +56668,12 @@ function registerMigrationRoutes(app) {
56538
56668
  onReadFailure: (entryPath, error) => warnReadFailure("registry-target", entryPath, error)
56539
56669
  });
56540
56670
  const manifest = discovered.sourcePaths.agents ? await loadPortableManifest(discovered.sourcePaths.agents) : null;
56541
- const providerConfigs = selectedProviders.map((provider) => ({
56542
- provider,
56543
- global: globalParam
56544
- }));
56545
- const enabledTypes = ["agent", "command", "skill", "config", "rules", "hooks"].filter((type) => {
56546
- const key = type === "agent" ? "agents" : type === "command" ? "commands" : type === "skill" ? "skills" : type === "config" ? "config" : type === "rules" ? "rules" : "hooks";
56547
- return include[key];
56548
- });
56671
+ const providerConfigs = buildScopedProviderConfigs(selectedProviders, include, globalParam);
56672
+ const enabledTypes = getEnabledPortableTypes(include);
56549
56673
  const typeDirectoryStates = reinstallEmptyDirs ? buildTypeDirectoryStates(providerConfigs.map((p) => ({
56550
56674
  provider: p.provider,
56551
- global: p.global
56675
+ global: p.global,
56676
+ types: p.types
56552
56677
  })), enabledTypes) : undefined;
56553
56678
  const input = {
56554
56679
  sourceItems,
@@ -56596,13 +56721,14 @@ function registerMigrationRoutes(app) {
56596
56721
  for (const item of items) {
56597
56722
  const sourcePath = item.sourcePath ?? item.path ?? "";
56598
56723
  for (const provider of selectedProviders) {
56599
- const registryEntry = registry.installations.find((inst) => inst.item === item.name && inst.type === type && inst.provider === provider && inst.global === globalParam);
56724
+ const candidateGlobal = resolvePortableTypeGlobal(provider, type, globalParam);
56725
+ const registryEntry = registry.installations.find((inst) => inst.item === item.name && inst.type === type && inst.provider === provider && inst.global === candidateGlobal);
56600
56726
  const alreadyInstalled = registryEntry !== undefined;
56601
56727
  candidates.push({
56602
56728
  item: item.name,
56603
56729
  type,
56604
56730
  provider,
56605
- global: globalParam,
56731
+ global: candidateGlobal,
56606
56732
  isDirectoryItem,
56607
56733
  description: item.description,
56608
56734
  sourcePath,
@@ -56690,14 +56816,12 @@ function registerMigrationRoutes(app) {
56690
56816
  sourcePath: h2.sourcePath ?? ""
56691
56817
  })), "hooks", false);
56692
56818
  }
56693
- const providerConfigs = selectedProviders.map((provider) => ({
56694
- provider,
56695
- global: globalParam
56819
+ const providerConfigs = buildScopedProviderConfigs(selectedProviders, include, globalParam).map((config) => ({
56820
+ provider: config.provider,
56821
+ global: config.global,
56822
+ types: config.types
56696
56823
  }));
56697
- const enabledTypes = ["agent", "command", "skill", "config", "rules", "hooks"].filter((type) => {
56698
- const key = type === "agent" ? "agents" : type === "command" ? "commands" : type === "skill" ? "skills" : type === "config" ? "config" : type === "rules" ? "rules" : "hooks";
56699
- return include[key];
56700
- });
56824
+ const enabledTypes = getEnabledPortableTypes(include);
56701
56825
  const typeDirectoryStates = buildTypeDirectoryStates(providerConfigs, enabledTypes);
56702
56826
  res.status(200).json({ candidates, typeDirectoryStates });
56703
56827
  } catch (error) {
@@ -56860,13 +56984,15 @@ function registerMigrationRoutes(app) {
56860
56984
  const plannedSkills = allowedSkillNames.length > 0 ? discovered2.skills.filter((skill) => allowedSkillNames.includes(skill.name)) : executionMode === "install" ? [] : discovered2.skills;
56861
56985
  const skillProviders = allPlanProviders.filter((provider) => providerSupportsType(provider, "skill"));
56862
56986
  if (skillProviders.length > 0) {
56863
- const globalFromPlan = plan.actions[0]?.global ?? false;
56864
56987
  for (const skill of plannedSkills) {
56865
- const batch = await installSkillDirectories([skill], skillProviders, {
56866
- global: globalFromPlan
56867
- });
56868
- tagResults(batch, "skills", skill.name);
56869
- allResults.push(...batch);
56988
+ for (const provider of skillProviders) {
56989
+ const globalFromPlan = plan.actions.find((action) => action.provider === provider && action.type === "skill")?.global ?? false;
56990
+ const batch = await installSkillDirectories([skill], [provider], {
56991
+ global: globalFromPlan
56992
+ });
56993
+ tagResults(batch, "skills", skill.name);
56994
+ allResults.push(...batch);
56995
+ }
56870
56996
  }
56871
56997
  }
56872
56998
  }
@@ -56886,12 +57012,12 @@ function registerMigrationRoutes(app) {
56886
57012
  for (const provider of allPlanProviders) {
56887
57013
  if (providers[provider]?.agents?.writeStrategy !== "codex-toml")
56888
57014
  continue;
56889
- const providerScopes = [
57015
+ const providerScopes2 = [
56890
57016
  ...new Set(plan.actions.filter((a3) => a3.provider === provider).map((a3) => a3.global).filter((g2) => g2 !== undefined))
56891
57017
  ];
56892
- if (providerScopes.length === 0)
56893
- providerScopes.push(false);
56894
- for (const scope of providerScopes) {
57018
+ if (providerScopes2.length === 0)
57019
+ providerScopes2.push(false);
57020
+ for (const scope of providerScopes2) {
56895
57021
  const staleSlugs = await cleanupStaleCodexConfigEntries({
56896
57022
  global: scope,
56897
57023
  provider
@@ -56918,7 +57044,7 @@ function registerMigrationRoutes(app) {
56918
57044
  const planScopes = [
56919
57045
  ...new Set(plan.actions.map((a3) => a3.global).filter((s) => s !== undefined))
56920
57046
  ];
56921
- const providerCollisions2 = planScopes.flatMap((scope) => detectProviderPathCollisions(allPlanProviders, { global: scope }));
57047
+ const providerCollisions2 = dedupeProviderPathCollisions(planScopes.flatMap((scope) => detectProviderPathCollisions(allPlanProviders, { global: scope })));
56922
57048
  annotateResultsWithCollisions(sortedResults2, providerCollisions2);
56923
57049
  res.status(200).json({
56924
57050
  results: sortedResults2,
@@ -56954,10 +57080,10 @@ function registerMigrationRoutes(app) {
56954
57080
  }
56955
57081
  const configSource = sourceParsed.value;
56956
57082
  const codexCommandsRequireGlobal = include.commands && selectedProviders.includes("codex") && providers.codex.commands !== null && providers.codex.commands.projectPath === null;
56957
- const effectiveGlobal = requestedGlobal || codexCommandsRequireGlobal;
57083
+ const effectiveGlobal = requestedGlobal;
56958
57084
  const warnings = [];
56959
57085
  if (codexCommandsRequireGlobal && !requestedGlobal) {
56960
- warnings.push("Codex commands are global-only; scope was automatically switched to global.");
57086
+ warnings.push("Codex commands are global-only; they will be installed globally while other content stays project-local.");
56961
57087
  }
56962
57088
  const discovered = await discoverMigrationItems(include, configSource);
56963
57089
  const hasItems = discovered.agents.length > 0 || discovered.commands.length > 0 || discovered.skills.length > 0 || discovered.configItem !== null || discovered.ruleItems.length > 0 || discovered.hookItems.length > 0;
@@ -56980,7 +57106,6 @@ function registerMigrationRoutes(app) {
56980
57106
  });
56981
57107
  return;
56982
57108
  }
56983
- const installOptions = { global: effectiveGlobal };
56984
57109
  const results = [];
56985
57110
  const hookRegistrationResults = [];
56986
57111
  const successfulHookFiles = new Map;
@@ -56994,10 +57119,11 @@ function registerMigrationRoutes(app) {
56994
57119
  hooks: include.hooks ? selectedProviders.filter((provider) => !getProvidersSupporting("hooks").includes(provider)) : []
56995
57120
  };
56996
57121
  if (include.agents && discovered.agents.length > 0) {
56997
- const providersForType = selectedProviders.filter((provider) => getProvidersSupporting("agents").includes(provider));
56998
- if (providersForType.length > 0) {
57122
+ for (const group of groupProvidersByTypeScope(selectedProviders, "agent", requestedGlobal)) {
56999
57123
  const batches = await Promise.all(discovered.agents.map(async (agent) => {
57000
- const batch = await installPortableItems([agent], providersForType, "agent", installOptions);
57124
+ const batch = await installPortableItems([agent], group.providers, "agent", {
57125
+ global: group.global
57126
+ });
57001
57127
  tagResults(batch, "agents", agent.name);
57002
57128
  return batch;
57003
57129
  }));
@@ -57007,10 +57133,11 @@ function registerMigrationRoutes(app) {
57007
57133
  }
57008
57134
  }
57009
57135
  if (include.commands && discovered.commands.length > 0) {
57010
- const providersForType = selectedProviders.filter((provider) => getProvidersSupporting("commands").includes(provider));
57011
- if (providersForType.length > 0) {
57136
+ for (const group of groupProvidersByTypeScope(selectedProviders, "command", requestedGlobal)) {
57012
57137
  const batches = await Promise.all(discovered.commands.map(async (command) => {
57013
- const batch = await installPortableItems([command], providersForType, "command", installOptions);
57138
+ const batch = await installPortableItems([command], group.providers, "command", {
57139
+ global: group.global
57140
+ });
57014
57141
  tagResults(batch, "commands", command.name);
57015
57142
  return batch;
57016
57143
  }));
@@ -57020,10 +57147,11 @@ function registerMigrationRoutes(app) {
57020
57147
  }
57021
57148
  }
57022
57149
  if (include.skills && discovered.skills.length > 0) {
57023
- const providersForType = selectedProviders.filter((provider) => getProvidersSupporting("skills").includes(provider));
57024
- if (providersForType.length > 0) {
57150
+ for (const group of groupProvidersByTypeScope(selectedProviders, "skill", requestedGlobal)) {
57025
57151
  const batches = await Promise.all(discovered.skills.map(async (skill) => {
57026
- const batch = await installSkillDirectories([skill], providersForType, installOptions);
57152
+ const batch = await installSkillDirectories([skill], group.providers, {
57153
+ global: group.global
57154
+ });
57027
57155
  tagResults(batch, "skills", skill.name);
57028
57156
  return batch;
57029
57157
  }));
@@ -57033,18 +57161,18 @@ function registerMigrationRoutes(app) {
57033
57161
  }
57034
57162
  }
57035
57163
  if (include.config && discovered.configItem) {
57036
- const providersForType = selectedProviders.filter((provider) => getProvidersSupporting("config").includes(provider));
57037
- if (providersForType.length > 0) {
57038
- const batch = await installPortableItems([discovered.configItem], providersForType, "config", installOptions);
57164
+ for (const group of groupProvidersByTypeScope(selectedProviders, "config", requestedGlobal)) {
57165
+ const batch = await installPortableItems([discovered.configItem], group.providers, "config", { global: group.global });
57039
57166
  tagResults(batch, "config");
57040
57167
  results.push(...batch);
57041
57168
  }
57042
57169
  }
57043
57170
  if (include.rules && discovered.ruleItems.length > 0) {
57044
- const providersForType = selectedProviders.filter((provider) => getProvidersSupporting("rules").includes(provider));
57045
- if (providersForType.length > 0) {
57171
+ for (const group of groupProvidersByTypeScope(selectedProviders, "rules", requestedGlobal)) {
57046
57172
  const batches = await Promise.all(discovered.ruleItems.map(async (rule) => {
57047
- const batch = await installPortableItems([rule], providersForType, "rules", installOptions);
57173
+ const batch = await installPortableItems([rule], group.providers, "rules", {
57174
+ global: group.global
57175
+ });
57048
57176
  tagResults(batch, "rules", rule.name);
57049
57177
  return batch;
57050
57178
  }));
@@ -57054,14 +57182,18 @@ function registerMigrationRoutes(app) {
57054
57182
  }
57055
57183
  }
57056
57184
  if (include.hooks && discovered.hookItems.length > 0) {
57057
- const providersForType = selectedProviders.filter((provider) => getProvidersSupporting("hooks").includes(provider));
57058
- if (providersForType.length > 0) {
57185
+ for (const group of groupProvidersByTypeScope(selectedProviders, "hooks", requestedGlobal)) {
57059
57186
  const batches = await Promise.all(discovered.hookItems.map(async (hook) => {
57060
- const batch = await installPortableItems([hook], providersForType, "hooks", installOptions);
57187
+ const batch = await installPortableItems([hook], group.providers, "hooks", {
57188
+ global: group.global
57189
+ });
57061
57190
  tagResults(batch, "hooks", hook.name);
57062
57191
  for (const result of batch.filter((entry) => entry.success && !entry.skipped)) {
57063
- const existing = successfulHookFiles.get(result.provider) ?? [];
57064
- existing.push(basename12(result.path));
57192
+ const existing = successfulHookFiles.get(result.provider) ?? {
57193
+ files: [],
57194
+ global: group.global
57195
+ };
57196
+ existing.files.push(basename12(result.path));
57065
57197
  successfulHookFiles.set(result.provider, existing);
57066
57198
  if (result.path.length > 0) {
57067
57199
  const absExisting = successfulHookAbsPaths.get(result.provider) ?? [];
@@ -57076,22 +57208,25 @@ function registerMigrationRoutes(app) {
57076
57208
  }
57077
57209
  }
57078
57210
  }
57079
- for (const [provider, files] of successfulHookFiles) {
57080
- if (files.length === 0)
57211
+ for (const [provider, entry] of successfulHookFiles) {
57212
+ if (entry.files.length === 0)
57081
57213
  continue;
57082
57214
  const mergeResult = await migrateHooksSettings({
57083
57215
  sourceProvider: "claude-code",
57084
57216
  targetProvider: provider,
57085
- installedHookFiles: files,
57217
+ installedHookFiles: entry.files,
57086
57218
  installedHookAbsolutePaths: successfulHookAbsPaths.get(provider),
57087
- global: effectiveGlobal
57219
+ global: entry.global
57088
57220
  });
57089
57221
  recordHookRegistrationOutcome(provider, mergeResult, warnings, hookRegistrationResults);
57090
57222
  }
57091
57223
  const responseResults = [...results, ...hookRegistrationResults];
57092
57224
  const sortedResults = sortPortableInstallResults(responseResults);
57093
57225
  const counts = toExecutionCounts(sortedResults);
57094
- const providerCollisions = detectProviderPathCollisions(selectedProviders, installOptions);
57226
+ const providerScopes = [
57227
+ ...new Set(buildScopedProviderConfigs(selectedProviders, include, requestedGlobal).map((p) => p.global))
57228
+ ];
57229
+ const providerCollisions = dedupeProviderPathCollisions(providerScopes.flatMap((scope) => detectProviderPathCollisions(selectedProviders, { global: scope })));
57095
57230
  annotateResultsWithCollisions(sortedResults, providerCollisions);
57096
57231
  res.status(200).json({
57097
57232
  results: sortedResults,
@@ -57114,6 +57249,7 @@ var MIGRATION_TYPES, MAX_PROVIDER_COUNT = 20, MAX_PLAN_ACTIONS = 5000, ALLOWED_C
57114
57249
  var init_migration_routes = __esm(() => {
57115
57250
  init_agents_discovery();
57116
57251
  init_commands_discovery();
57252
+ init_migrate_provider_scopes();
57117
57253
  init_skill_directory_installer();
57118
57254
  init_codex_toml_installer();
57119
57255
  init_config_discovery();
@@ -62253,7 +62389,7 @@ var package_default;
62253
62389
  var init_package = __esm(() => {
62254
62390
  package_default = {
62255
62391
  name: "claudekit-cli",
62256
- version: "3.42.2-dev.4",
62392
+ version: "3.42.2-dev.6",
62257
62393
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
62258
62394
  type: "module",
62259
62395
  repository: {
@@ -104752,24 +104888,63 @@ import { mkdir as mkdir34 } from "node:fs/promises";
104752
104888
  import { join as join135, resolve as resolve38 } from "node:path";
104753
104889
 
104754
104890
  // src/domains/github/kit-access-checker.ts
104891
+ init_error2();
104755
104892
  init_logger();
104756
104893
  init_safe_spinner();
104757
104894
  init_types3();
104895
+ init_types3();
104758
104896
  init_github_client();
104897
+ function toGitHubError(error) {
104898
+ if (error instanceof GitHubError) {
104899
+ return error;
104900
+ }
104901
+ const classified = classifyGitHubError(error, "check repository access");
104902
+ const actions = suggestActions(classified.category);
104903
+ const formattedActions = formatActions(actions);
104904
+ const messageParts = [classified.message];
104905
+ if (classified.details) {
104906
+ messageParts.push(`
104907
+ ${classified.details}`);
104908
+ }
104909
+ if (formattedActions) {
104910
+ messageParts.push(`
104911
+ Solutions:${formattedActions}`);
104912
+ }
104913
+ messageParts.push(`
104914
+ Need help? Run with: ck new --verbose`);
104915
+ return new GitHubError(messageParts.join(`
104916
+ `), classified.httpStatus);
104917
+ }
104759
104918
  async function detectAccessibleKits() {
104760
104919
  const spinner = createSpinner("Checking kit access...").start();
104761
104920
  const github = new GitHubClient;
104762
- const results = await Promise.all(Object.entries(AVAILABLE_KITS).map(async ([type, config]) => {
104763
- try {
104764
- await github.checkAccess(config);
104765
- logger.debug(`Access confirmed: ${type}`);
104766
- return type;
104767
- } catch {
104768
- logger.debug(`No access to ${type}`);
104769
- return null;
104770
- }
104921
+ const settled = await Promise.allSettled(Object.entries(AVAILABLE_KITS).map(async ([type, config]) => {
104922
+ await github.checkAccess(config);
104923
+ logger.debug(`Access confirmed: ${type}`);
104924
+ return type;
104771
104925
  }));
104772
- const accessible = results.filter((kit) => kit !== null);
104926
+ const accessible = [];
104927
+ const fatalErrors = [];
104928
+ for (const result of settled) {
104929
+ if (result.status === "fulfilled") {
104930
+ accessible.push(result.value);
104931
+ } else {
104932
+ const err = result.reason;
104933
+ const status = err?.statusCode ?? err?.status;
104934
+ if (status === 404) {
104935
+ logger.debug("No access to kit (404)");
104936
+ } else {
104937
+ fatalErrors.push(toGitHubError(err));
104938
+ }
104939
+ }
104940
+ }
104941
+ if (fatalErrors.length > 0) {
104942
+ spinner.fail("Kit access check failed");
104943
+ for (const extra of fatalErrors.slice(1)) {
104944
+ logger.debug(`Additional kit access error (suppressed): ${extra.message}`);
104945
+ }
104946
+ throw fatalErrors[0];
104947
+ }
104773
104948
  if (accessible.length === 0) {
104774
104949
  spinner.fail("No kit access found");
104775
104950
  } else {
@@ -107521,6 +107696,9 @@ function createTtyProgressSink(total, context) {
107521
107696
  };
107522
107697
  }
107523
107698
 
107699
+ // src/commands/migrate/migrate-command.ts
107700
+ init_migrate_provider_scopes();
107701
+
107524
107702
  // src/commands/migrate/migrate-scope-resolver.ts
107525
107703
  function resolveMigrationScope(argv, options2) {
107526
107704
  const argSet = new Set(argv);
@@ -107566,6 +107744,7 @@ function resolveMigrationScope(argv, options2) {
107566
107744
 
107567
107745
  // src/commands/migrate/migrate-ui-summary.ts
107568
107746
  init_provider_registry();
107747
+ init_migrate_provider_scopes();
107569
107748
  var PORTABLE_TYPES = [
107570
107749
  { key: "agents", label: "Agents" },
107571
107750
  { key: "commands", label: "Commands" },
@@ -107588,9 +107767,10 @@ function buildPreflightRows(counts, selectedProviders, options2) {
107588
107767
  notes.add(`${providers[provider].displayName}: unsupported`);
107589
107768
  continue;
107590
107769
  }
107591
- const destination = getPortableBasePath(provider, key, { global: options2.actualGlobal });
107770
+ const actualGlobal = resolvePortableGroupGlobal(provider, key, options2.requestedGlobal);
107771
+ const destination = getPortableBasePath(provider, key, { global: actualGlobal });
107592
107772
  if (!destination) {
107593
- const note2 = options2.actualGlobal ? "project-only" : "global-only";
107773
+ const note2 = actualGlobal ? "project-only" : "global-only";
107594
107774
  notes.add(`${providers[provider].displayName}: ${note2}`);
107595
107775
  continue;
107596
107776
  }
@@ -107634,8 +107814,17 @@ function buildTargetSummaryLines(rows) {
107634
107814
  }
107635
107815
  return [...allDestinations.slice(0, 3), `+${allDestinations.length - 3} more destination(s)`];
107636
107816
  }
107637
- function buildProviderScopeSubtitle(selectedProviders, global3) {
107638
- const scope = global3 ? "global" : "project";
107817
+ function buildProviderScopeSubtitle(selectedProviders, requestedGlobal, counts) {
107818
+ const activeTypes = PORTABLE_TYPES.filter(({ key }) => !counts || counts[key] > 0);
107819
+ const resolvedScopes = new Set;
107820
+ for (const provider of selectedProviders) {
107821
+ for (const { key } of activeTypes) {
107822
+ if (!providers[provider][key])
107823
+ continue;
107824
+ resolvedScopes.add(resolvePortableGroupGlobal(provider, key, requestedGlobal));
107825
+ }
107826
+ }
107827
+ const scope = resolvedScopes.size > 1 ? "mixed" : resolvedScopes.values().next().value ?? requestedGlobal ? "global" : "project";
107639
107828
  if (selectedProviders.length === 1) {
107640
107829
  return `${providers[selectedProviders[0]].displayName} -> ${scope}`;
107641
107830
  }
@@ -108055,8 +108244,7 @@ async function migrateCommand(options2) {
108055
108244
  }
108056
108245
  const codexCommandsRequireGlobal = scope.commands && selectedProviders.includes("codex") && providers.codex.commands !== null && providers.codex.commands.projectPath === null;
108057
108246
  if (codexCommandsRequireGlobal && !installGlobally) {
108058
- installGlobally = true;
108059
- f2.info(import_picocolors30.default.dim("Codex commands are global-only; scope adjusted to global."));
108247
+ f2.info(import_picocolors30.default.dim("Codex commands are global-only; they will be installed globally while other content stays project-local."));
108060
108248
  }
108061
108249
  const sourceCounts = {
108062
108250
  agents: agents2.length,
@@ -108075,7 +108263,6 @@ async function migrateCommand(options2) {
108075
108263
  hooksSource
108076
108264
  ].filter((origin) => origin !== null);
108077
108265
  const preflightRows = buildPreflightRows(sourceCounts, selectedProviders, {
108078
- actualGlobal: installGlobally,
108079
108266
  requestedGlobal
108080
108267
  });
108081
108268
  const discoveryParts = [];
@@ -108105,7 +108292,7 @@ async function migrateCommand(options2) {
108105
108292
  console.log();
108106
108293
  console.log(renderSourceTargetHeader({
108107
108294
  sourceLines: buildSourceSummaryLines(sourceCounts, sourceOrigins),
108108
- subtitle: buildProviderScopeSubtitle(selectedProviders, installGlobally),
108295
+ subtitle: buildProviderScopeSubtitle(selectedProviders, requestedGlobal, sourceCounts),
108109
108296
  targetLines: buildTargetSummaryLines(preflightRows),
108110
108297
  title: "ck migrate"
108111
108298
  }).join(`
@@ -108163,13 +108350,14 @@ async function migrateCommand(options2) {
108163
108350
  rules: effectiveRuleItems,
108164
108351
  hooks: effectiveHookItems
108165
108352
  }, selectedProviders);
108166
- const targetStates = await computeTargetStates(selectedProviders, installGlobally);
108167
- const providerConfigs = selectedProviders.map((provider) => ({
108168
- provider,
108169
- global: installGlobally
108170
- }));
108171
- const portableTypes = ["agent", "command", "config", "rules", "hooks"];
108172
- const typeDirectoryStates = buildTypeDirectoryStates(selectedProviders.map((provider) => ({ provider, global: installGlobally })), [...portableTypes]);
108353
+ const providerConfigs = buildScopedProviderConfigs(selectedProviders, scope, installGlobally);
108354
+ const targetStates = await computeTargetStates(providerConfigs);
108355
+ const portableTypes = getEnabledPortableTypes(scope).filter((type) => type !== "skill");
108356
+ const typeDirectoryStates = buildTypeDirectoryStates(providerConfigs.map((config) => ({
108357
+ provider: config.provider,
108358
+ global: config.global,
108359
+ types: config.types?.filter((type) => type !== "skill")
108360
+ })), portableTypes);
108173
108361
  const reinstallEmptyDirs = options2.respectDeletions ? false : options2.reinstallEmptyDirs ?? true;
108174
108362
  const plan = reconcile({
108175
108363
  sourceItems: sourceStates,
@@ -108232,7 +108420,6 @@ async function migrateCommand(options2) {
108232
108420
  }
108233
108421
  }
108234
108422
  let allResults = [];
108235
- const installOpts = { global: installGlobally };
108236
108423
  const agentByName = new Map(effectiveAgents.map((item) => [item.name, item]));
108237
108424
  const commandByName = new Map(effectiveCommands.map((item) => [item.name, item]));
108238
108425
  const skillByName = new Map(effectiveSkills.map((item) => [item.name, item]));
@@ -108251,42 +108438,42 @@ async function migrateCommand(options2) {
108251
108438
  const item = agentByName.get(action.item);
108252
108439
  if (!item || !getProvidersSupporting("agents").includes(provider))
108253
108440
  continue;
108254
- writeTasks.push({ item, provider, type: "agent" });
108441
+ writeTasks.push({ item, provider, type: "agent", global: action.global });
108255
108442
  continue;
108256
108443
  }
108257
108444
  if (action.type === "command") {
108258
108445
  const item = commandByName.get(action.item);
108259
108446
  if (!item || !getProvidersSupporting("commands").includes(provider))
108260
108447
  continue;
108261
- writeTasks.push({ item, provider, type: "command" });
108448
+ writeTasks.push({ item, provider, type: "command", global: action.global });
108262
108449
  continue;
108263
108450
  }
108264
108451
  if (action.type === "skill") {
108265
108452
  const item = skillByName.get(action.item);
108266
108453
  if (!item || !getProvidersSupporting("skills").includes(provider))
108267
108454
  continue;
108268
- writeTasks.push({ item, provider, type: "skill" });
108455
+ writeTasks.push({ item, provider, type: "skill", global: action.global });
108269
108456
  continue;
108270
108457
  }
108271
108458
  if (action.type === "config") {
108272
108459
  const item = configByName.get(action.item);
108273
108460
  if (!item || !getProvidersSupporting("config").includes(provider))
108274
108461
  continue;
108275
- writeTasks.push({ item, provider, type: "config" });
108462
+ writeTasks.push({ item, provider, type: "config", global: action.global });
108276
108463
  continue;
108277
108464
  }
108278
108465
  if (action.type === "rules") {
108279
108466
  const item = ruleByName.get(action.item);
108280
108467
  if (!item || !getProvidersSupporting("rules").includes(provider))
108281
108468
  continue;
108282
- writeTasks.push({ item, provider, type: "rules" });
108469
+ writeTasks.push({ item, provider, type: "rules", global: action.global });
108283
108470
  continue;
108284
108471
  }
108285
108472
  if (action.type === "hooks") {
108286
108473
  const item = hookByName.get(action.item);
108287
108474
  if (!item || !getProvidersSupporting("hooks").includes(provider))
108288
108475
  continue;
108289
- writeTasks.push({ item, provider, type: "hooks" });
108476
+ writeTasks.push({ item, provider, type: "hooks", global: action.global });
108290
108477
  }
108291
108478
  }
108292
108479
  const plannedSkillActions = plannedExecActions.filter((action) => action.type === "skill").length;
@@ -108294,22 +108481,31 @@ async function migrateCommand(options2) {
108294
108481
  const skillProviders = selectedProviders.filter((pv) => getProvidersSupporting("skills").includes(pv));
108295
108482
  for (const provider of skillProviders) {
108296
108483
  for (const skill of effectiveSkills) {
108297
- writeTasks.push({ item: skill, provider, type: "skill" });
108484
+ writeTasks.push({
108485
+ item: skill,
108486
+ provider,
108487
+ type: "skill",
108488
+ global: resolvePortableTypeGlobal(provider, "skill", installGlobally)
108489
+ });
108298
108490
  }
108299
108491
  }
108300
108492
  }
108301
108493
  const progressSink = createMigrateProgressSink(writeTasks.length + plannedDeleteActions.length);
108302
108494
  const writtenPaths = new Set;
108303
108495
  for (const task of writeTasks) {
108304
- const taskResults = task.type === "skill" ? annotateInstallResults(await installSkillDirectories([task.item], [task.provider], installOpts), "skill", task.item.name) : annotateInstallResults(await installPortableItems([task.item], [task.provider], task.type, installOpts), task.type, task.item.name);
108496
+ const taskInstallOpts = { global: task.global };
108497
+ const taskResults = task.type === "skill" ? annotateInstallResults(await installSkillDirectories([task.item], [task.provider], taskInstallOpts), "skill", task.item.name) : annotateInstallResults(await installPortableItems([task.item], [task.provider], task.type, taskInstallOpts), task.type, task.item.name);
108305
108498
  allResults.push(...taskResults);
108306
108499
  for (const result of taskResults.filter((entry) => entry.success && !entry.skipped)) {
108307
108500
  if (result.path.length > 0) {
108308
108501
  writtenPaths.add(resolve41(result.path));
108309
108502
  }
108310
108503
  if (task.type === "hooks") {
108311
- const existing = successfulHookFiles.get(task.provider) ?? [];
108312
- existing.push(basename27(result.path));
108504
+ const existing = successfulHookFiles.get(task.provider) ?? {
108505
+ files: [],
108506
+ global: task.global
108507
+ };
108508
+ existing.files.push(basename27(result.path));
108313
108509
  successfulHookFiles.set(task.provider, existing);
108314
108510
  if (result.path.length > 0) {
108315
108511
  const absExisting = successfulHookAbsPaths.get(task.provider) ?? [];
@@ -108337,9 +108533,9 @@ async function migrateCommand(options2) {
108337
108533
  }
108338
108534
  }
108339
108535
  if (hooksSource && successfulHookFiles.size > 0) {
108340
- for (const hooksProvider of successfulHookFiles.keys()) {
108536
+ for (const [hooksProvider, entry] of successfulHookFiles) {
108341
108537
  const providerCfg = providers[hooksProvider];
108342
- const targetHooksDir = installGlobally ? providerCfg.hooks?.globalPath : providerCfg.hooks?.projectPath;
108538
+ const targetHooksDir = entry.global ? providerCfg.hooks?.globalPath : providerCfg.hooks?.projectPath;
108343
108539
  if (!targetHooksDir)
108344
108540
  continue;
108345
108541
  const companionResult = await copyHooksCompanionDirs(hooksSource, targetHooksDir);
@@ -108361,15 +108557,15 @@ async function migrateCommand(options2) {
108361
108557
  }
108362
108558
  }
108363
108559
  }
108364
- for (const [hooksProvider, files] of successfulHookFiles) {
108365
- if (files.length === 0)
108560
+ for (const [hooksProvider, entry] of successfulHookFiles) {
108561
+ if (entry.files.length === 0)
108366
108562
  continue;
108367
108563
  const mergeResult = await migrateHooksSettings({
108368
108564
  sourceProvider: "claude-code",
108369
108565
  targetProvider: hooksProvider,
108370
- installedHookFiles: files,
108566
+ installedHookFiles: entry.files,
108371
108567
  installedHookAbsolutePaths: successfulHookAbsPaths.get(hooksProvider),
108372
- global: installGlobally
108568
+ global: entry.global
108373
108569
  });
108374
108570
  if (mergeResult.success && mergeResult.hooksRegistered > 0) {
108375
108571
  logger.verbose(`Registered ${mergeResult.hooksRegistered} hook(s) in ${hooksProvider} settings.json`);
@@ -108400,15 +108596,22 @@ async function migrateCommand(options2) {
108400
108596
  const providerConfig = providers[provider];
108401
108597
  if (providerConfig.agents?.writeStrategy !== "codex-toml")
108402
108598
  continue;
108403
- const staleSlugs = await cleanupStaleCodexConfigEntries({
108404
- global: installGlobally,
108405
- provider
108406
- });
108407
- if (staleSlugs.length > 0) {
108408
- const staleSlugSet = new Set(staleSlugs.map((s) => `${s}.toml`));
108409
- const removed = await removeInstallationsByFilter((i) => i.type === "agent" && i.provider === provider && i.global === installGlobally && staleSlugSet.has(basename27(i.path)));
108410
- for (const entry of removed) {
108411
- logger.verbose(`[migrate] Cleaned stale registry entry: ${entry.item} (${provider})`);
108599
+ const providerScopes = [
108600
+ ...new Set(plan.actions.filter((action) => action.provider === provider).map((action) => action.global))
108601
+ ];
108602
+ if (providerScopes.length === 0)
108603
+ providerScopes.push(installGlobally);
108604
+ for (const scope2 of providerScopes) {
108605
+ const staleSlugs = await cleanupStaleCodexConfigEntries({
108606
+ global: scope2,
108607
+ provider
108608
+ });
108609
+ if (staleSlugs.length > 0) {
108610
+ const staleSlugSet = new Set(staleSlugs.map((s) => `${s}.toml`));
108611
+ const removed = await removeInstallationsByFilter((i) => i.type === "agent" && i.provider === provider && i.global === scope2 && staleSlugSet.has(basename27(i.path)));
108612
+ for (const entry of removed) {
108613
+ logger.verbose(`[migrate] Cleaned stale registry entry: ${entry.item} (${provider})`);
108614
+ }
108412
108615
  }
108413
108616
  }
108414
108617
  }
@@ -108498,12 +108701,11 @@ async function computeSourceStates(items, selectedProviders) {
108498
108701
  processItems(items.hooks, "hooks");
108499
108702
  return states;
108500
108703
  }
108501
- async function computeTargetStates(selectedProviders, global3) {
108704
+ async function computeTargetStates(providerConfigs) {
108502
108705
  const registry = await readPortableRegistry();
108503
108706
  const relevantEntries = registry.installations.filter((entry) => {
108504
- if (!selectedProviders.includes(entry.provider))
108505
- return false;
108506
- if (entry.global !== global3)
108707
+ const matchingConfig = providerConfigs.some((config) => config.provider === entry.provider && config.global === entry.global && providerConfigAppliesToType(config, entry.type));
108708
+ if (!matchingConfig)
108507
108709
  return false;
108508
108710
  return entry.type !== "skill";
108509
108711
  });
@@ -108583,7 +108785,9 @@ function buildDryRunFallbackResults(skills, selectedProviders, installGlobally,
108583
108785
  }
108584
108786
  const results = [];
108585
108787
  for (const provider of selectedProviders.filter((entry) => getProvidersSupporting("skills").includes(entry))) {
108586
- const basePath = getPortableBasePath(provider, "skills", { global: installGlobally });
108788
+ const basePath = getPortableBasePath(provider, "skills", {
108789
+ global: resolvePortableTypeGlobal(provider, "skill", installGlobally)
108790
+ });
108587
108791
  if (!basePath)
108588
108792
  continue;
108589
108793
  for (const skill of skills) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.42.2-dev.4",
3
+ "version": "3.42.2-dev.6",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {