holycodex 0.9.4 → 0.9.5

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +69 -36
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -7,6 +7,6 @@ bunx holycodex@dev install
7
7
  bunx holycodex@dev doctor
8
8
  ```
9
9
 
10
- Use `holycodex --help` for commands and autonomy options. Stable releases use `bunx holycodex`; development releases use npm's `dev` dist-tag.
10
+ Use `holycodex --help` for commands, autonomy options, and service tiers. `--fast` selects the fast tier; `--no-fast` or omitting both tier flags selects the default. Stable releases use `bunx holycodex`; development releases use npm's `dev` dist-tag.
11
11
 
12
12
  Repository, documentation, license, and security notices: https://github.com/davidbasilefilho/holycodex
package/dist/cli.js CHANGED
@@ -4252,7 +4252,7 @@ function superRefine(fn, params) {
4252
4252
  }
4253
4253
  //#endregion
4254
4254
  //#region packages/cli/src/catalog.ts
4255
- var VERSION = "0.9.4";
4255
+ var VERSION = "0.9.5";
4256
4256
  var SKILLS = [
4257
4257
  "ast-grep",
4258
4258
  "caveman",
@@ -4991,8 +4991,8 @@ function removeManaged(input) {
4991
4991
  return input.replace(new RegExp(`${escapedStart}([\\s\\S]*?)${escapedEnd}(?:\\r?\\n){0,2}`, "g"), (_match, body) => {
4992
4992
  const encoded = body.match(/^# holycodex original root: ([A-Za-z0-9+/=]+)$/m)?.[1];
4993
4993
  if (encoded !== void 0) return `${Buffer.from(encoded, "base64").toString("utf8")}\n`;
4994
- const tableKey = body.match(/^# holycodex original table key: ([A-Za-z0-9+/=]+)$/m)?.[1];
4995
- return tableKey === void 0 ? "" : `${Buffer.from(tableKey, "base64").toString("utf8")}\n`;
4994
+ const tableKeys = [...body.matchAll(/^# holycodex original table key: ([A-Za-z0-9+/=]+)$/gm)].flatMap((match) => match[1] === void 0 ? [] : [match[1]]);
4995
+ return tableKeys.length === 0 ? "" : `${tableKeys.map((key) => Buffer.from(key, "base64").toString("utf8")).join("\n")}\n`;
4996
4996
  }).trim();
4997
4997
  }
4998
4998
  /** Removes legacy omo. */
@@ -5008,18 +5008,17 @@ function removeLegacyOmo(input) {
5008
5008
  ].some((name) => header === name || header.startsWith(`${name}.`)) || !/(?:sisyphuslabs|omo@|oh-my|code-yeongyu)/i.test(section);
5009
5009
  }).join("").trimEnd();
5010
5010
  }
5011
- function injectTableKey(input, table, key, value) {
5011
+ function injectTableKeys(input, table, entries) {
5012
5012
  const match = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*(?:#.*)?$`, "m").exec(input);
5013
5013
  const tail = match === null ? "" : input.slice(match.index + match[0].length);
5014
5014
  const tableEnd = nextTableBoundary(tail);
5015
5015
  const tableBody = tableEnd < 0 ? tail : tail.slice(0, tableEnd);
5016
- const originalKey = new RegExp(`^[ \\t]*${key}[ \\t]*=.*$`, "m").exec(tableBody)?.[0];
5017
- const managed = `${START}\n${originalKey === void 0 ? "" : `${ORIGINAL_TABLE_KEY}${Buffer.from(originalKey).toString("base64")}\n`}${key} = ${value}\n${END}`;
5018
- if (match === null) return `${input.trimEnd()}\n\n${START}\n[${table}]\n${key} = ${value}\n${END}`.trim();
5016
+ const managed = `${START}\n${entries.map(([key]) => new RegExp(`^[ \\t]*${key}[ \\t]*=.*$`, "m").exec(tableBody)?.[0]).filter((value) => value !== void 0).map((value) => `${ORIGINAL_TABLE_KEY}${Buffer.from(value).toString("base64")}\n`).join("")}${entries.map(([key, value]) => `${key} = ${value}`).join("\n")}\n${END}`;
5017
+ if (match === null) return `${input.trimEnd()}\n\n${START}\n[${table}]\n${entries.map(([key, value]) => `${key} = ${value}`).join("\n")}\n${END}`.trim();
5019
5018
  const bodyStart = match.index + match[0].length;
5020
5019
  const next = nextTableBoundary(input.slice(bodyStart));
5021
5020
  const bodyEnd = next < 0 ? input.length : bodyStart + next;
5022
- const cleanedBody = input.slice(bodyStart, bodyEnd).replace(new RegExp(`^\\s*${key}\\s*=.*\\r?\\n?`, "gm"), "").trim();
5021
+ const cleanedBody = entries.reduce((body, [key]) => body.replace(new RegExp(`^\\s*${key}\\s*=.*\\r?\\n?`, "gm"), ""), input.slice(bodyStart, bodyEnd)).trim();
5023
5022
  const suffix = input.slice(bodyEnd).trimStart();
5024
5023
  return `${input.slice(0, bodyStart)}\n${cleanedBody ? `${cleanedBody}\n` : ""}${managed}${suffix ? `\n${suffix}` : ""}`.trim();
5025
5024
  }
@@ -5037,6 +5036,14 @@ function rootValue(input, key) {
5037
5036
  function removeRootValue(input, value) {
5038
5037
  return value === void 0 ? input : input.replace(value, "");
5039
5038
  }
5039
+ function removeRootKey(input, key) {
5040
+ let updated = input;
5041
+ for (;;) {
5042
+ const value = rootValue(updated, key);
5043
+ if (value === void 0) return updated;
5044
+ updated = removeRootValue(updated, value);
5045
+ }
5046
+ }
5040
5047
  /** Reads the explicitly recorded model routing plan from managed configuration. */
5041
5048
  function readManagedPlan(input) {
5042
5049
  const value = new RegExp(`^${PLAN_PREFIX}(.+)$`, "m").exec(input)?.[1]?.trim();
@@ -5060,8 +5067,8 @@ function readPreservedRootOverrides(input) {
5060
5067
  reasoningEffort: false
5061
5068
  };
5062
5069
  const plan = readManagedPlan(managedRoot);
5063
- const model = rootTomlString(managedRoot, "model");
5064
- const reasoningEffort = rootTomlString(managedRoot, "model_reasoning_effort");
5070
+ const model = rootTomlString(input, "model");
5071
+ const reasoningEffort = rootTomlString(input, "model_reasoning_effort");
5065
5072
  if (plan === void 0 || model === void 0 || reasoningEffort === void 0) return {
5066
5073
  model: false,
5067
5074
  reasoningEffort: false
@@ -5091,11 +5098,6 @@ function preserveManagedRootPreferences(input, base) {
5091
5098
  updatedRoot = removeRootValue(updatedRoot, rootValue(updatedRoot, key)).trim();
5092
5099
  updatedRoot = `${updatedRoot}${updatedRoot ? "\n" : ""}${live}`;
5093
5100
  }
5094
- const verbosity = rootValue(managedRoot, "model_verbosity")?.trim();
5095
- if (verbosity !== void 0 && verbosity !== (rootValue(root, "model_verbosity")?.trim() ?? "model_verbosity = \"low\"")) {
5096
- updatedRoot = removeRootValue(updatedRoot, rootValue(updatedRoot, "model_verbosity")).trim();
5097
- updatedRoot = `${updatedRoot}${updatedRoot ? "\n" : ""}${verbosity}`;
5098
- }
5099
5101
  if (updatedRoot === root.trim()) return base;
5100
5102
  return `${updatedRoot}${tables ? `\n${tables.trimStart()}` : ""}`;
5101
5103
  }
@@ -5106,7 +5108,7 @@ function mergedStatusLine(original) {
5106
5108
  return `[${items.map((item) => JSON.stringify(item)).join(", ")}]`;
5107
5109
  }
5108
5110
  /** Installs config. */
5109
- function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents) {
5111
+ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents, fast = false) {
5110
5112
  const base = preserveManagedRootPreferences(input, removeLegacyOmo(removeManaged(input)));
5111
5113
  const firstTable = base.search(/^\s*\[/m);
5112
5114
  const root = firstTable < 0 ? base : base.slice(0, firstTable);
@@ -5115,31 +5117,41 @@ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents
5115
5117
  "approval_policy",
5116
5118
  "sandbox_mode",
5117
5119
  "max_concurrent_threads_per_session",
5118
- "status_line"
5120
+ "status_line",
5121
+ "model_verbosity",
5122
+ "service_tier"
5119
5123
  ].map((key) => rootValue(root, key));
5120
- const originalRoot = root.trim();
5121
- const preservedRoot = controlled.reduce(removeRootValue, root).trim();
5124
+ const preservedRoot = [
5125
+ "approval_policy",
5126
+ "sandbox_mode",
5127
+ "max_concurrent_threads_per_session",
5128
+ "status_line",
5129
+ "model_verbosity",
5130
+ "service_tier"
5131
+ ].reduce(removeRootKey, root).trim();
5132
+ const originalControlled = controlled.filter((value) => value !== void 0).sort((left, right) => root.indexOf(left) - root.indexOf(right)).join("\n");
5122
5133
  const hasModel = /^\s*model\s*=/m.test(preservedRoot);
5123
5134
  const hasEffort = /^\s*model_reasoning_effort\s*=/m.test(preservedRoot);
5124
- const hasVerbosity = /^\s*model_verbosity\s*=/m.test(preservedRoot);
5125
5135
  const rootRoute = MODEL_ROUTING_PLANS[plan].root;
5126
5136
  const effectiveMaxSubagents = maxSubagents ?? MODEL_ROUTING_PLANS[plan].usage.maxSubagents;
5127
5137
  const model = hasModel ? "" : `model = "${rootRoute.model}"\n`;
5128
5138
  const effort = hasEffort ? "" : `model_reasoning_effort = "${rootRoute.reasoningEffort}"\n`;
5129
- const verbosity = hasVerbosity ? "" : "model_verbosity = \"low\"\n";
5130
5139
  const approval = mode === "default" ? "on-request" : "never";
5131
5140
  const sandbox = mode === "dangerous" ? "danger-full-access" : "workspace-write";
5132
- const original = originalRoot ? `${ORIGINAL_ROOT}${Buffer.from(originalRoot).toString("base64")}\n` : "";
5133
- const preserved = preservedRoot ? `${preservedRoot}\n` : "";
5134
- let configured = `${`${START}\n${PLAN_PREFIX}${plan}\n${maxSubagents === void 0 ? "" : `${MAX_SUBAGENTS_PREFIX}${maxSubagents}\n`}${original}${model}${effort}${verbosity}${preserved}approval_policy = "${approval}"\nsandbox_mode = "${sandbox}"\nstatus_line = ${mergedStatusLine(controlled[3])}\n${END}`}${tables ? `\n\n${tables}` : ""}`;
5135
- configured = injectTableKey(configured, "features", "default_mode_request_user_input", "true");
5136
- configured = injectTableKey(configured, "features", "multi_agent", "true");
5137
- configured = injectTableKey(configured, "features", "multi_agent_v2", "true");
5141
+ const original = originalControlled ? `${ORIGINAL_ROOT}${Buffer.from(originalControlled).toString("base64")}\n` : "";
5142
+ const rootBlock = `${START}\n${PLAN_PREFIX}${plan}\n${maxSubagents === void 0 ? "" : `${MAX_SUBAGENTS_PREFIX}${maxSubagents}\n`}${original}${model}${effort}model_verbosity = "low"\nservice_tier = "${fast ? "fast" : "default"}"\napproval_policy = "${approval}"\nsandbox_mode = "${sandbox}"\nstatus_line = ${mergedStatusLine(controlled[3])}\n${END}`;
5143
+ let configured = `${preservedRoot ? `${preservedRoot}\n` : ""}${rootBlock}${tables ? `\n\n${tables}` : ""}`;
5144
+ configured = injectTableKeys(configured, "features", [
5145
+ ["default_mode_request_user_input", "true"],
5146
+ ["multi_agent", "true"],
5147
+ ["multi_agent_v2", "true"]
5148
+ ]);
5138
5149
  const usage = MODEL_ROUTING_PLANS[plan].usage;
5139
- configured = injectTableKey(configured, "agents", "max_threads", String(effectiveMaxSubagents + 1));
5140
- configured = injectTableKey(configured, "agents", "max_depth", String(usage.maxDepth));
5141
- if (mode !== "dangerous") configured = injectTableKey(configured, "sandbox_workspace_write", "network_access", "true");
5142
- for (const agent of AGENTS) configured = injectTableKey(configured, `agents.${agent}`, "config_file", `"holycodex/agents/${agent}.toml"`);
5150
+ configured = injectTableKeys(configured, "agents", [["max_threads", String(effectiveMaxSubagents + 1)], ["max_depth", String(usage.maxDepth)]]);
5151
+ if (mode !== "dangerous") configured = injectTableKeys(configured, "sandbox_workspace_write", [["network_access", "true"]]);
5152
+ configured = injectTableKeys(configured, "desktop", [["enabled-reasoning-efforts", "[\"low\", \"medium\", \"high\"]"], ["show-context-window-usage", "true"]]);
5153
+ if (_platform === "win32") configured = injectTableKeys(configured, "windows", [["sandbox", "\"unelevated\""]]);
5154
+ for (const agent of AGENTS) configured = injectTableKeys(configured, `agents.${agent}`, [["config_file", `"holycodex/agents/${agent}.toml"`]]);
5143
5155
  const plugin = `${START}\n[plugins."holycodex@holycodex"]\nenabled = true\n${END}`;
5144
5156
  return `${configured.trim()}\n\n${plugin}\n`;
5145
5157
  }
@@ -5226,6 +5238,14 @@ function tableBoolean(config, table, key) {
5226
5238
  const value = body === void 0 ? void 0 : new RegExp(`^\\s*${key}\\s*=\\s*(true|false)`, "m").exec(body)?.[1];
5227
5239
  return value === void 0 ? void 0 : value === "true";
5228
5240
  }
5241
+ function tableString(config, table, key) {
5242
+ const body = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5243
+ return body === void 0 ? void 0 : rootTomlString(body, key);
5244
+ }
5245
+ function tableStringArray(config, table, key) {
5246
+ const body = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5247
+ return body === void 0 ? void 0 : rootTomlStringArray(body, key);
5248
+ }
5229
5249
  function tableInteger(config, table, key) {
5230
5250
  const body = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5231
5251
  const value = body === void 0 ? void 0 : new RegExp(`^\\s*${key}\\s*=\\s*(\\d+)`, "m").exec(body)?.[1];
@@ -5316,12 +5336,17 @@ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")
5316
5336
  const expectedMaxSubagents = managedMaxSubagents.configured ? managedMaxSubagents.value : preset?.usage.maxSubagents;
5317
5337
  const rootOverrides = readPreservedRootOverrides(config);
5318
5338
  checks.push(preset !== void 0 && rootTomlString(config, "model") === preset.root.model && rootTomlString(config, "model_reasoning_effort") === preset.root.reasoningEffort ? check("root-model", "ok", "root-model-ready", "Root model matches the selected routing plan.") : rootOverrides.model || rootOverrides.reasoningEffort ? check("root-model", "ok", "root-model-override", "Root model uses an intentionally preserved explicit override.") : check("root-model", "error", "root-model-stale", "Root model configuration does not match the selected routing plan.", "Reinstall HolyCodex."));
5339
+ checks.push(["default", "fast"].includes(rootTomlString(config, "service_tier") ?? "") ? check("service-tier", "ok", "service-tier-ready", "Codex service tier is explicitly managed.") : check("service-tier", "error", "service-tier-stale", "service_tier must be either default or fast.", "Reinstall HolyCodex with --fast or --no-fast."));
5340
+ checks.push(rootTomlString(config, "model_verbosity") === "low" ? check("root-verbosity", "ok", "root-verbosity-ready", "Root model verbosity is forced to low.") : check("root-verbosity", "error", "root-verbosity-stale", "Root model verbosity must be low.", "Reinstall HolyCodex."));
5319
5341
  checks.push(preset === void 0 || expectedMaxSubagents === void 0 || tableInteger(config, "agents", "max_threads") !== expectedMaxSubagents + 1 || tableInteger(config, "agents", "max_depth") !== preset.usage.maxDepth ? check("agent-usage", "error", "agent-usage-stale", "Agent concurrency configuration does not match the selected routing plan or explicit override.", "Reinstall HolyCodex.") : check("agent-usage", "ok", "agent-usage-ready", `Agent concurrency allows ${expectedMaxSubagents} direct subagent${expectedMaxSubagents === 1 ? "" : "s"}.`));
5320
5342
  checks.push(mode === "unknown" ? check("autonomy", "error", "invalid-autonomy-config", "Approval, sandbox, and network settings do not match a supported mode.", "Rerun install with the intended autonomy flag.") : mode === "dangerous" ? check("autonomy", "warning", "dangerous-autonomy", "Explicit dangerous autonomy is active; workspace containment is removed.") : check("autonomy", "ok", `${mode}-ready`, mode === "safe-workspace" ? "Safe workspace autonomy is active." : "Approval-free workspace autonomy is active."));
5321
5343
  checks.push(tableBoolean(config, "features", "default_mode_request_user_input") === true ? check("user-input", "ok", "user-input-ready", "default_mode_request_user_input is enabled.") : check("user-input", "error", "user-input-disabled", "default_mode_request_user_input is not enabled.", "Rerun holycodex install."));
5344
+ checks.push(tableStringArray(config, "desktop", "enabled-reasoning-efforts")?.join(",") === "low,medium,high" ? check("desktop-reasoning", "ok", "desktop-reasoning-ready", "Desktop exposes low, medium, and high reasoning efforts.") : check("desktop-reasoning", "error", "desktop-reasoning-stale", "Desktop reasoning choices must be low, medium, and high.", "Reinstall HolyCodex."));
5345
+ checks.push(tableBoolean(config, "desktop", "show-context-window-usage") === true ? check("desktop-context-usage", "ok", "desktop-context-usage-ready", "Desktop context-window usage is visible.") : check("desktop-context-usage", "error", "desktop-context-usage-hidden", "Desktop context-window usage is not enabled.", "Reinstall HolyCodex."));
5322
5346
  checks.push(rootTomlStringArray(config, "status_line")?.includes("context-remaining") === true ? check("context-visibility", "warning", "context-visible-support-unverified", "status_line includes context-remaining. Current official Codex config documents this item, but publishes no minimum compatible Codex version.") : check("context-visibility", "error", "context-hidden", "status_line does not include context-remaining.", "Rerun holycodex install."));
5323
5347
  const codex = await runtime.command("codex", ["--version"]);
5324
5348
  checks.push(codex.ok ? check("codex", "ok", "codex-version", codex.output || "Codex is available.") : check("codex", "warning", "codex-version-unavailable", "Codex version could not be read; status-line compatibility cannot be independently confirmed."));
5349
+ if (runtime.platform === "win32") checks.push(tableString(config, "windows", "sandbox") === "unelevated" ? check("windows-sandbox", "ok", "windows-sandbox-ready", "Windows sandbox runs unelevated.") : check("windows-sandbox", "error", "windows-sandbox-stale", "Windows sandbox must run unelevated.", "Reinstall HolyCodex on Windows."));
5325
5350
  const agentModelFailures = [];
5326
5351
  for (const agent of AGENTS) try {
5327
5352
  const text = await readFile(join(agentRoot, `${agent}.toml`), "utf8");
@@ -5426,7 +5451,7 @@ async function install(options, runtime = defaultRuntime) {
5426
5451
  ].filter((path) => path !== void 0);
5427
5452
  const existingConfig = await readText(target.config);
5428
5453
  const previousPlan = readManagedPlan(existingConfig);
5429
- const config = installConfig(existingConfig, options.autonomy, runtime.platform, plan, options.maxSubagents);
5454
+ const config = installConfig(existingConfig, options.autonomy, runtime.platform, plan, options.maxSubagents, options.fast ?? false);
5430
5455
  await atomicWrite(target.config, config);
5431
5456
  await rm(target.cache, {
5432
5457
  recursive: true,
@@ -5501,6 +5526,7 @@ async function writeInstalledAgents(root, platform, plan) {
5501
5526
  let source = await readText(path);
5502
5527
  source = replaceTomlString(source, "model", route.model);
5503
5528
  source = replaceTomlString(source, "model_reasoning_effort", route.reasoningEffort);
5529
+ source = replaceTomlString(source, "model_verbosity", "low");
5504
5530
  if (platform === "win32") {
5505
5531
  await atomicWrite(path, source);
5506
5532
  return;
@@ -5568,16 +5594,16 @@ function supportsColor(isTTY, noColor) {
5568
5594
  }
5569
5595
  /** Renders help. */
5570
5596
  function renderHelp(version, color) {
5571
- const title = paint(color, `${BOLD}${CYAN}`, `HOLYCODEX ${version}`);
5597
+ const title = paint(color, `${BOLD}${CYAN}`, `HolyCodex ${version}`);
5572
5598
  const section = (text) => paint(color, BOLD, text);
5573
5599
  const muted = (text) => paint(color, DIM, text);
5574
- return `${title}\n${muted("Lean Codex toolkit installer and doctor")}\n\n${section("USAGE")}\n holycodex <command> [options]\n\n${section("COMMANDS")}\n install Install or update HolyCodex\n cleanup Remove HolyCodex-owned state\n doctor Diagnose installation and runtime\n\n${section("OPTIONS")}\n --plan <plan> Model routing plan for install: ${PLAN_HELP}\n Default: ${DEFAULT_PLAN}\n --max-subagents <count> Override concurrent direct subagents for install\n -h, --help Show help\n -v, --version Show version\n --no-tui Accepted; commands remain noninteractive\n --codex-autonomous Never ask; keep workspace sandbox\n --no-codex-autonomous Safe interactive defaults\n --dangerous-codex-autonomous Never ask; disable filesystem sandbox\n --json Print machine-readable output\n`;
5600
+ return `${title}\n${muted("Lean Codex toolkit installer and doctor")}\n\n${section("USAGE")}\n holycodex <command> [options]\n\n${section("COMMANDS")}\n install Install or update HolyCodex\n cleanup Remove HolyCodex-owned state\n doctor Diagnose installation and runtime\n\n${section("OPTIONS")}\n --plan <plan> Model routing plan for install: ${PLAN_HELP}\n Default: ${DEFAULT_PLAN}\n --max-subagents <count> Override concurrent direct subagents for install\n --fast Use Codex fast service tier\n --no-fast Use Codex default service tier\n -h, --help Show help\n -v, --version Show version\n --no-tui Accepted; commands remain noninteractive\n --codex-autonomous Never ask; keep workspace sandbox\n --no-codex-autonomous Safe interactive defaults\n --dangerous-codex-autonomous Never ask; disable filesystem sandbox\n --json Print machine-readable output\n`;
5575
5601
  }
5576
5602
  /** Renders install-specific model plan and option help. */
5577
5603
  function renderInstallHelp(version, color) {
5578
- const title = paint(color, `${BOLD}${CYAN}`, `HOLYCODEX ${version}`);
5604
+ const title = paint(color, `${BOLD}${CYAN}`, `HolyCodex ${version}`);
5579
5605
  const section = (text) => paint(color, BOLD, text);
5580
- return `${title}\n\n${section("Usage:")}\n holycodex install [options]\n\n${section("Options:")}\n --plan <plan> Model routing plan: ${PLAN_HELP}\n Default: ${DEFAULT_PLAN}\n --max-subagents <count> Override concurrent direct subagents\n --json Print machine-readable output\n --no-tui Accepted; install remains noninteractive\n --codex-autonomous Never ask; keep workspace sandbox\n --no-codex-autonomous Safe interactive defaults\n --dangerous-codex-autonomous Never ask; disable filesystem sandbox\n -h, --help Show help\n\nPlans provide increasing expected model usage and capability.\n\n${section("Examples:")}\n bunx holycodex install\n bunx holycodex install --plan go\n bunx holycodex install --plan plus-low\n bunx holycodex install --plan plus-high\n bunx holycodex install --plan pro-5x\n bunx holycodex install --plan pro-20x\n`;
5606
+ return `${title}\n\n${section("Usage:")}\n holycodex install [options]\n\n${section("Options:")}\n --plan <plan> Model routing plan: ${PLAN_HELP}\n Default: ${DEFAULT_PLAN}\n --max-subagents <count> Override concurrent direct subagents\n --fast Use Codex fast service tier\n --no-fast Use Codex default service tier\n --json Print machine-readable output\n --no-tui Accepted; install remains noninteractive\n --codex-autonomous Never ask; keep workspace sandbox\n --no-codex-autonomous Safe interactive defaults\n --dangerous-codex-autonomous Never ask; disable filesystem sandbox\n -h, --help Show help\n\nPlans provide increasing expected model usage and capability.\n\n${section("Examples:")}\n bunx holycodex install\n bunx holycodex install --plan go\n bunx holycodex install --plan plus-low\n bunx holycodex install --plan plus-high\n bunx holycodex install --plan pro-5x\n bunx holycodex install --plan pro-20x\n`;
5581
5607
  }
5582
5608
  /** Renders error. */
5583
5609
  function renderError(message, color) {
@@ -5641,9 +5667,16 @@ async function main() {
5641
5667
  process$1.exitCode = 1;
5642
5668
  return;
5643
5669
  }
5670
+ const fastFlags = args.filter((arg) => ["--fast", "--no-fast"].includes(arg));
5671
+ if (fastFlags.length > 1) {
5672
+ process$1.stderr.write(renderError(`Conflicting fast flags: ${fastFlags.join(", ")}`, stderrColor));
5673
+ process$1.exitCode = 1;
5674
+ return;
5675
+ }
5644
5676
  const options = {
5645
5677
  autonomy: args.includes("--dangerous-codex-autonomous") ? "dangerous" : args.includes("--codex-autonomous") ? "autonomous" : "default",
5646
5678
  json: args.includes("--json"),
5679
+ fast: args.includes("--fast"),
5647
5680
  plan,
5648
5681
  ...maxSubagents === void 0 ? {} : { maxSubagents }
5649
5682
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "holycodex",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Lean Codex-only agent toolkit installer and doctor",
5
5
  "keywords": [
6
6
  "agents",
@@ -39,7 +39,7 @@
39
39
  "prepack": "vp run --workspace-root build"
40
40
  },
41
41
  "dependencies": {
42
- "@holycodex/plugin": "0.9.4",
42
+ "@holycodex/plugin": "0.9.5",
43
43
  "zod": "^4.4.3"
44
44
  },
45
45
  "engines": {