claudekit-cli 3.41.4-dev.47 → 3.41.4-dev.48

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.41.4-dev.47",
3
- "generatedAt": "2026-04-24T01:07:18.882Z",
2
+ "version": "3.41.4-dev.48",
3
+ "generatedAt": "2026-04-24T02:15:04.014Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
package/dist/index.js CHANGED
@@ -53250,24 +53250,37 @@ async function _ensureFeatureFlagLocked(configTomlPath) {
53250
53250
  };
53251
53251
  }
53252
53252
  }
53253
- const hasManagedBlock = existing.includes(SENTINEL_START2) && existing.includes(SENTINEL_END2);
53254
- if (hasManagedBlock) {
53255
- const replaced = replaceManagedBlock(existing);
53256
- await atomicWrite(configTomlPath, replaced);
53253
+ const { content: stripped, removed: hadManagedBlock } = stripAllManagedBlocks(existing);
53254
+ let content = stripped;
53255
+ let mutated = hadManagedBlock;
53256
+ const featuresHeaderIdx = findFeaturesSectionStart(content);
53257
+ if (featuresHeaderIdx !== -1) {
53258
+ const { updated, changed } = ensureFlagInFeaturesSection(content, featuresHeaderIdx);
53259
+ content = updated;
53260
+ mutated = mutated || changed;
53261
+ if (!mutated) {
53262
+ return { status: "already-set", configPath: configTomlPath };
53263
+ }
53264
+ try {
53265
+ await atomicWrite(configTomlPath, content);
53266
+ } catch (err) {
53267
+ return {
53268
+ status: "failed",
53269
+ configPath: configTomlPath,
53270
+ error: `Failed to write ${configTomlPath}: ${err instanceof Error ? err.message : String(err)}`
53271
+ };
53272
+ }
53257
53273
  return { status: "updated", configPath: configTomlPath };
53258
53274
  }
53259
- if (hasRawFeatureFlag(existing)) {
53260
- return { status: "already-set", configPath: configTomlPath };
53261
- }
53262
- const separator = existing.length > 0 && !existing.endsWith(`
53275
+ const separator = content.length === 0 ? "" : content.endsWith(`
53263
53276
  `) ? `
53264
-
53265
53277
  ` : `
53278
+
53266
53279
  `;
53267
- const updated = `${existing}${separator}${MANAGED_BLOCK}
53280
+ const withBlock = `${content}${separator}${MANAGED_BLOCK}
53268
53281
  `;
53269
53282
  try {
53270
- await atomicWrite(configTomlPath, updated);
53283
+ await atomicWrite(configTomlPath, withBlock);
53271
53284
  } catch (err) {
53272
53285
  return {
53273
53286
  status: "failed",
@@ -53275,34 +53288,80 @@ async function _ensureFeatureFlagLocked(configTomlPath) {
53275
53288
  error: `Failed to write ${configTomlPath}: ${err instanceof Error ? err.message : String(err)}`
53276
53289
  };
53277
53290
  }
53278
- return { status: "written", configPath: configTomlPath };
53291
+ return { status: hadManagedBlock ? "updated" : "written", configPath: configTomlPath };
53279
53292
  }
53280
- function hasRawFeatureFlag(content) {
53281
- const withoutManaged = removeManagedBlock(content);
53282
- return /^\s*codex_hooks\s*=\s*true(\s*#[^\r\n]*)?\s*$/m.test(withoutManaged);
53293
+ function findFeaturesSectionStart(content) {
53294
+ const match = /^[ \t]*\[features\][ \t]*(?:#[^\r\n]*)?$/m.exec(content);
53295
+ return match ? match.index : -1;
53283
53296
  }
53284
- function replaceManagedBlock(content) {
53285
- const startIdx = content.indexOf(SENTINEL_START2);
53286
- const endIdx = content.lastIndexOf(SENTINEL_END2);
53287
- if (startIdx === -1 || endIdx === -1 || endIdx < startIdx) {
53288
- return content;
53297
+ function ensureFlagInFeaturesSection(content, headerStartIdx) {
53298
+ const headerLineEnd = content.indexOf(`
53299
+ `, headerStartIdx);
53300
+ const bodyStart = headerLineEnd === -1 ? content.length : headerLineEnd + 1;
53301
+ const rest = content.slice(bodyStart);
53302
+ const nextHeaderMatch = /\n\[[^\]]+\]/.exec(rest);
53303
+ const bodyEnd = nextHeaderMatch ? bodyStart + nextHeaderMatch.index + 1 : content.length;
53304
+ const body = content.slice(bodyStart, bodyEnd);
53305
+ const flagRegex = /^([ \t]*codex_hooks[ \t]*=[ \t]*)(true|false)([ \t]*#[^\r\n]*)?[ \t]*$/m;
53306
+ const flagMatch = flagRegex.exec(body);
53307
+ if (flagMatch) {
53308
+ if (flagMatch[2] === "true") {
53309
+ return { updated: content, changed: false };
53310
+ }
53311
+ const newBody = body.replace(flagRegex, (_m, prefix, _v, trailing) => `${prefix}true${trailing ?? ""}`);
53312
+ return {
53313
+ updated: content.slice(0, bodyStart) + newBody + content.slice(bodyEnd),
53314
+ changed: true
53315
+ };
53289
53316
  }
53290
- const endOfBlock = endIdx + SENTINEL_END2.length;
53291
- const afterBlock = content[endOfBlock] === `
53292
- ` ? content.slice(endOfBlock + 1) : content.slice(endOfBlock);
53293
- const before = content.slice(0, startIdx);
53294
- return `${before}${MANAGED_BLOCK}
53295
- ${afterBlock}`;
53296
- }
53297
- function removeManagedBlock(content) {
53298
- const startIdx = content.indexOf(SENTINEL_START2);
53299
- const endIdx = content.indexOf(SENTINEL_END2);
53300
- if (startIdx === -1 || endIdx === -1 || endIdx < startIdx)
53301
- return content;
53302
- const endOfBlock = endIdx + SENTINEL_END2.length;
53303
- const afterBlock = content[endOfBlock] === `
53304
- ` ? content.slice(endOfBlock + 1) : content.slice(endOfBlock);
53305
- return content.slice(0, startIdx) + afterBlock;
53317
+ if (headerLineEnd === -1) {
53318
+ return { updated: `${content}
53319
+ codex_hooks = true
53320
+ `, changed: true };
53321
+ }
53322
+ let insertAt = bodyEnd;
53323
+ while (insertAt > bodyStart && content[insertAt - 1] === `
53324
+ ` && content[insertAt - 2] === `
53325
+ `) {
53326
+ insertAt -= 1;
53327
+ }
53328
+ const needsLeadingNewline = insertAt > bodyStart && content[insertAt - 1] !== `
53329
+ `;
53330
+ const insertion = `${needsLeadingNewline ? `
53331
+ ` : ""}codex_hooks = true
53332
+ `;
53333
+ return {
53334
+ updated: content.slice(0, insertAt) + insertion + content.slice(insertAt),
53335
+ changed: true
53336
+ };
53337
+ }
53338
+ function stripAllManagedBlocks(content) {
53339
+ let result = content;
53340
+ let removed = false;
53341
+ while (true) {
53342
+ const startIdx = result.indexOf(SENTINEL_START2);
53343
+ if (startIdx === -1)
53344
+ break;
53345
+ const endIdx = result.indexOf(SENTINEL_END2, startIdx);
53346
+ if (endIdx === -1)
53347
+ break;
53348
+ const endOfBlock = endIdx + SENTINEL_END2.length;
53349
+ const afterBlockStart = result[endOfBlock] === `
53350
+ ` ? endOfBlock + 1 : endOfBlock;
53351
+ let beforeBlockEnd = startIdx;
53352
+ if (beforeBlockEnd >= 1 && result[beforeBlockEnd - 1] === `
53353
+ `) {
53354
+ beforeBlockEnd -= 1;
53355
+ if (beforeBlockEnd >= 1 && result[beforeBlockEnd - 1] === `
53356
+ `) {
53357
+ beforeBlockEnd -= 1;
53358
+ }
53359
+ beforeBlockEnd += 1;
53360
+ }
53361
+ result = result.slice(0, beforeBlockEnd) + result.slice(afterBlockStart);
53362
+ removed = true;
53363
+ }
53364
+ return { content: result, removed };
53306
53365
  }
53307
53366
  async function atomicWrite(filePath, content) {
53308
53367
  const tempPath = `${filePath}.ck-tmp`;
@@ -61558,7 +61617,7 @@ var package_default;
61558
61617
  var init_package = __esm(() => {
61559
61618
  package_default = {
61560
61619
  name: "claudekit-cli",
61561
- version: "3.41.4-dev.47",
61620
+ version: "3.41.4-dev.48",
61562
61621
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
61563
61622
  type: "module",
61564
61623
  repository: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.41.4-dev.47",
3
+ "version": "3.41.4-dev.48",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {