holycodex 0.13.4 → 0.13.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.
- package/README.md +12 -8
- package/dist/cli.js +172 -33
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
# holycodex
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`holycodex` is the public installer, doctor, and cleanup CLI for HolyCodex. It installs the exact matching `@holycodex/plugin` payload and makes durable Codex workflows, retained Luna specialists, plan-aware routing, Context7, LSP, and native-Windows Git Bash available to Codex. Product and ownership details live in the repository [README](../../README.md) and [architecture](../../docs/ARCHITECTURE.md).
|
|
4
|
+
|
|
5
|
+
Stable installation:
|
|
4
6
|
|
|
5
7
|
```sh
|
|
6
|
-
bunx holycodex
|
|
7
|
-
bunx holycodex
|
|
8
|
+
bunx holycodex install
|
|
9
|
+
bunx holycodex doctor
|
|
8
10
|
```
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
Development installation uses the development dist-tag:
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
```sh
|
|
15
|
+
bunx holycodex@dev install
|
|
16
|
+
```
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
Use `holycodex --help` for commands and options. `--plan` selects the catalog plan, `--fast`, `--fast-all`, and `--no-fast` select the service tier, and `--computer-use` or `--no-computer-use` controls the optional official plugin. Standard is the default tier. See [routing policy](../../docs/ROUTING.md) for plan values, quotas, and route ownership.
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
`doctor` and `cleanup` accept `--json`; install also supports JSON output and concise human progress. Cleanup removes only HolyCodex-managed assets and preserves unrelated Codex configuration and plugins. The CLI does not install MCP servers.
|
|
17
21
|
|
|
18
|
-
Repository, documentation, license, and security notices: https://github.com/davidbasilefilho/holycodex
|
|
22
|
+
Repository, documentation, license, and security notices: [HolyCodex](https://github.com/davidbasilefilho/holycodex), [security advisories](https://github.com/davidbasilefilho/holycodex/security/advisories/new).
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import process$1 from "node:process";
|
|
2
|
-
import { access, copyFile, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { access, copyFile, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
3
3
|
import { homedir, tmpdir } from "node:os";
|
|
4
4
|
import { delimiter, dirname, join, resolve } from "node:path";
|
|
5
5
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
@@ -4391,7 +4391,7 @@ function superRefine(fn, params) {
|
|
|
4391
4391
|
}
|
|
4392
4392
|
//#endregion
|
|
4393
4393
|
//#region packages/cli/src/catalog.ts
|
|
4394
|
-
var VERSION = "0.13.
|
|
4394
|
+
var VERSION = "0.13.5";
|
|
4395
4395
|
var SKILLS = [
|
|
4396
4396
|
"ast-grep",
|
|
4397
4397
|
"babysit-ci",
|
|
@@ -6758,7 +6758,9 @@ function formatInstalledRuntimeGuidance(pluginRoot) {
|
|
|
6758
6758
|
var CORE_INSTRUCTIONS = "HolyCodex: Root is user-facing. Before updates, classify intent and load required skills. Start with \"I detect [intent] intent — [action].\" Choose the accurate intent naturally; no fixed intent taxonomy applies. `plan` and `plan-review` instead own their exact heading and intent as the first visible block; no other mode prints a heading. Do not conceal orchestration. Give concise updates naming each specialist type and what it will do, such as \"Explorer maps X\", \"Librarian verifies Y\", or \"Worker implements Z\". Do not disclose Root orchestration mechanics or explain why delegation is running unless asked. Skills govern method only. Root owns interaction, intent, scope, architecture, product choices, ambiguity, integration, external state, and final judgment and verification. Root is not another implementation branch: evaluate specialist output against scope, fixed architecture, user decisions, repository conventions, and proof; reject or repair weak output and integrate only accepted work. On every plan other than Go, use a CLI workflow for substantive discovery, implementation, verification, multi-file work, risky changes, or architecture-sensitive work. Root may work directly for genuinely small bounded operations such as repository synchronization, one quick mechanical edit, or an equivalent one-off change. State when the direct-work exception applies, and never use it to bypass delegation for broader work. Never invoke regular Codex collaboration subagents. If a required workflow is unavailable or cannot perform the operation, report the blocker instead of bypassing delegation. Missing task-child visibility is not a reason to avoid workflows. Go does not support workflows, so Root works directly without specialist subagents. A task may contain multiple sequential workflows. Prefer the smallest useful fan-out, stop discovery when evidence is sufficient, and avoid duplicate investigation. The selected plan is authoritative: enforce its permitted model routes for each agent and stage, low verbosity, Fast as the only service-tier variation, concurrency, soft target calls, hard maximum calls, workflow depth, retries, loop iterations, fan-out, projected usage, and soft-size guidance. Root should remain near target calls and exceed them only when intermediate evidence justifies more work; the hard maximum is only a safety and quota ceiling. Larger plans do not automatically consume larger allowances. Keep explorer, librarian, and worker selectable only where the plan permits. Root owns workflow integration and final proof. After any code or manifest implementation, Root loads `code-review` exactly once before final response; it also loads `code-review` for a user-requested snippet, file, directory, diff, patch, or PR review. That skill owns the final audit, repair, proportional checks and reruns, reinspection, diff, and status. Classify unknowns: delegate facts, ask material decisions, and state and use safe reversible defaults. Whenever Root needs user input or would ask any question, it must use `request_user_input` when that tool is available, in every scenario and mode. Root must never stop or reply with a plain-text question when the tool is available. If the tool is unavailable, use a safe reversible default where possible or report a non-question blocker. Never repeat questions or ask discoverable facts. Root must use `request_user_input` immediately before committing, pushing, creating or moving tags, building or compiling, publishing, deploying, destructive or irreversible actions, permission changes, financial actions, sending, or any other externally visible action. Earlier general authorization does not replace this immediate approval unless the user explicitly authorized that exact action in the current turn. Root controls browser and native desktop UI itself. Explorer is repository-read-only, Librarian research-only, and Worker cannot alter dashboards, accounts, permissions, or external state. Specialists never delegate, broaden, review, or make final judgments.";
|
|
6759
6759
|
var NATIVE_IO_INSTRUCTIONS = "For `plan` and `plan-review` headings, never print provisionally. Never delegate browser or computer control. For frontend creation, redesign, or visual verification, use installed Build Web Apps `frontend-app-builder` for concept, approval, implementation, and visual verification. For authorized security reviews, audits, scans, threat models, vulnerabilities, or attack paths, use matching installed Codex Security plugin skills. Use these capabilities instead of manual-click instructions, shell-as-GUI, or public research as a substitute for authenticated control. Use Codex native `apply_patch` for workspace file creation, updates, moves, and deletion. Use available native read or shell tools for file inspection and repository search. Do not re-read files only to verify a successful `apply_patch` call.";
|
|
6760
6760
|
var COMPUTER_USE_INSTRUCTIONS = "For native desktop tasks, use the available Computer Use capability.";
|
|
6761
|
-
var ROOT_LUNA_POLICY = "Root is the judgment and control plane: own interaction, scope, architecture, product and risk decisions, workflow integration, material ambiguity, external state, and the final decision. Luna specialists are bounded execution context: Explorer maps sufficient repository facts, Librarian verifies assigned current facts, and Worker implements, integrates, inspects diffs, runs checks, performs mechanical repair and retest, routine review, evidence compression, and optional synthesis. Root accepts successful structured Luna evidence without rereading or re-verifying it; material architecture, product, scope, risk, or contradictory-evidence decisions return to Root.
|
|
6761
|
+
var ROOT_LUNA_POLICY = "Root is the judgment and control plane: own interaction, scope, architecture, product and risk decisions, workflow integration, material ambiguity, external state, and the final decision. Luna specialists are bounded execution context: Explorer maps sufficient repository facts, Librarian verifies assigned current facts, and Worker implements, integrates, inspects diffs, runs checks, performs mechanical repair and retest, routine review, evidence compression, and optional synthesis. Root accepts successful structured Luna evidence without rereading or re-verifying it; material architecture, product, scope, risk, or contradictory-evidence decisions return to Root. When retained context is valid, prefer it with compact outcomes, Luna-local loops and synthesis, sufficient discovery, and genuine concurrency without changing plan quotas. Structured substantive outcomes are the branching contract, not prose parsing. Escalate Luna high to xhigh to max only when the evidence justifies it and the active plan permits the route; max insufficiency returns compact evidence to Root and never creates a Sol specialist.";
|
|
6762
|
+
var ROOT_DESIGN_GATE_POLICY = "Use a lightweight Root design gate only for architecture-sensitive, substantive, or meaningfully multi-file work; trivial, one-off mechanical, and genuinely small single-file work is excluded. Record the owner and seam, data and control flow, stable interfaces, state and policy location, exclusions, duplication seam, errors and recovery, tests, compatibility, and why the chosen shape is preferred when real alternatives exist. This is a compact constraint gate, not a mandatory extra call or a second plan. Repository-native evidence from source, tests, configuration, commands, diff, and status is authoritative for implementation facts. If repository evidence conflicts with the approved constraint, architecture, scope, or another material decision, escalate to Root rather than resolving it silently.";
|
|
6763
|
+
var WORKER_BRIEF_POLICY = "Root gives Worker a compact constraint/outcome brief containing the objective and outcome, literal scope and exclusions, owner and seam, existing mechanism to extend, data and control flow, stable interfaces, state and policy location, error and recovery obligations, compatibility, tests and exact repository-native proof, plus stop and escalation conditions. Worker follows that brief, does not rediscover architecture or make material choices, and returns the standard structured outcome. Worker may perform one warranted bounded diff-level taste/simplification pass for clarity, naming, duplication, or avoidable complexity in changed files only; it must preserve behavior, interfaces, ownership, and scope and then stop. Worker routine review and repair stay within that seam; Root retains final judgment for material architecture, product, scope, risk, and contradictory evidence.";
|
|
6762
6764
|
var CODE_REVIEW_ACTIVATION_POLICY = "After loading `code-review`, its first visible line is **CODE REVIEW MODE ACTIVATED**.";
|
|
6763
6765
|
/** Gets core instructions with platform and active agent-capacity context. */
|
|
6764
6766
|
function coreInstructions(platform, capacity, computerUseEnabled = false, pluginRoot) {
|
|
@@ -6766,7 +6768,7 @@ function coreInstructions(platform, capacity, computerUseEnabled = false, plugin
|
|
|
6766
6768
|
const depth = capacity?.maxDepth;
|
|
6767
6769
|
const capacityInstructions = threads === void 0 || depth === void 0 ? "Before delegation, use active collaboration tool instructions as the authoritative agent-capacity limit." : `Host agent capacity: agents.max_concurrent_threads_per_session=${threads} includes Root. The host nesting limit is ${depth}; the active plan's maxCalls is the hard workflow call ceiling and targetCalls is soft planning guidance. Its lower concurrency, depth, and fan-out limits remain authoritative. Substantive, multi-file, risky, and architecture-sensitive work uses a CLI workflow; genuinely small bounded operations may remain direct. Report a blocker when a required workflow runtime is unavailable. Go does not support workflows, so Root works directly without specialist subagents.`;
|
|
6768
6770
|
const platformInstructions = platform === "win32" ? ` ${WINDOWS_SHELL_POLICY}` : "";
|
|
6769
|
-
return `${CORE_INSTRUCTIONS} ${ROOT_LUNA_POLICY} ${LITE_WRITING_POLICY} ${CONTEXT7_POLICY} ${NATIVE_IO_INSTRUCTIONS}${computerUseEnabled ? ` ${COMPUTER_USE_INSTRUCTIONS}` : ""} ${CODE_REVIEW_ACTIVATION_POLICY} ${capacityInstructions}${platformInstructions}${pluginRoot === void 0 ? "" : ` ${formatInstalledRuntimeGuidance(pluginRoot)}`}`;
|
|
6771
|
+
return `${CORE_INSTRUCTIONS} ${ROOT_LUNA_POLICY} ${ROOT_DESIGN_GATE_POLICY} ${WORKER_BRIEF_POLICY} ${LITE_WRITING_POLICY} ${CONTEXT7_POLICY} ${NATIVE_IO_INSTRUCTIONS}${computerUseEnabled ? ` ${COMPUTER_USE_INSTRUCTIONS}` : ""} ${CODE_REVIEW_ACTIVATION_POLICY} ${capacityInstructions}${platformInstructions}${pluginRoot === void 0 ? "" : ` ${formatInstalledRuntimeGuidance(pluginRoot)}`}`;
|
|
6770
6772
|
}
|
|
6771
6773
|
//#endregion
|
|
6772
6774
|
//#region packages/cli/src/doctor.ts
|
|
@@ -6935,16 +6937,26 @@ async function exists(path) {
|
|
|
6935
6937
|
}
|
|
6936
6938
|
/** Provides backup. */
|
|
6937
6939
|
async function backup(path, root) {
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
+
try {
|
|
6941
|
+
await lstat(path);
|
|
6942
|
+
} catch (error) {
|
|
6943
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
|
|
6944
|
+
throw error;
|
|
6945
|
+
}
|
|
6946
|
+
const target = join(root, backupPath(path));
|
|
6940
6947
|
await mkdir(dirname(target), { recursive: true });
|
|
6941
6948
|
await copyBackup(path, target);
|
|
6942
6949
|
return target;
|
|
6943
6950
|
}
|
|
6951
|
+
function backupPath(path) {
|
|
6952
|
+
const segments = path.replaceAll("\\", "/").replace(/^(?:[A-Za-z]:)?\/+/, "").split("/").filter((segment) => segment !== "" && segment !== ".");
|
|
6953
|
+
if (segments.some((segment) => segment === "..")) throw new Error(`Cannot create a backup for unsafe path: ${path}`);
|
|
6954
|
+
return join(...segments);
|
|
6955
|
+
}
|
|
6944
6956
|
async function copyBackup(source, target) {
|
|
6945
6957
|
const metadata = await lstat(source);
|
|
6946
6958
|
if (metadata.isSymbolicLink()) {
|
|
6947
|
-
await
|
|
6959
|
+
await symlink(await readlink(source), target);
|
|
6948
6960
|
return;
|
|
6949
6961
|
}
|
|
6950
6962
|
if (!metadata.isDirectory()) {
|
|
@@ -6954,6 +6966,60 @@ async function copyBackup(source, target) {
|
|
|
6954
6966
|
await mkdir(target, { recursive: true });
|
|
6955
6967
|
for (const entry of await readdir(source)) await copyBackup(join(source, entry), join(target, entry));
|
|
6956
6968
|
}
|
|
6969
|
+
/** Restores a backup while preserving the original file and symlink types. */
|
|
6970
|
+
async function restoreBackup(path, source) {
|
|
6971
|
+
if (source === void 0) {
|
|
6972
|
+
await rm(path, {
|
|
6973
|
+
recursive: true,
|
|
6974
|
+
force: true
|
|
6975
|
+
});
|
|
6976
|
+
return;
|
|
6977
|
+
}
|
|
6978
|
+
if ((await lstat(source)).isSymbolicLink()) {
|
|
6979
|
+
await rm(path, {
|
|
6980
|
+
recursive: true,
|
|
6981
|
+
force: true
|
|
6982
|
+
});
|
|
6983
|
+
await mkdir(dirname(path), { recursive: true });
|
|
6984
|
+
await symlink(await readlink(source), path);
|
|
6985
|
+
return;
|
|
6986
|
+
}
|
|
6987
|
+
await rm(path, {
|
|
6988
|
+
recursive: true,
|
|
6989
|
+
force: true
|
|
6990
|
+
});
|
|
6991
|
+
await restoreBackupTree(source, path);
|
|
6992
|
+
}
|
|
6993
|
+
async function restoreBackupTree(source, target) {
|
|
6994
|
+
if (!(await lstat(source)).isDirectory()) {
|
|
6995
|
+
await mkdir(dirname(target), { recursive: true });
|
|
6996
|
+
await copyFile(source, target);
|
|
6997
|
+
return;
|
|
6998
|
+
}
|
|
6999
|
+
await mkdir(target, { recursive: true });
|
|
7000
|
+
for (const entry of await readdir(source)) {
|
|
7001
|
+
const entrySource = join(source, entry);
|
|
7002
|
+
const entryTarget = join(target, entry);
|
|
7003
|
+
if ((await lstat(entrySource)).isSymbolicLink()) {
|
|
7004
|
+
await rm(entryTarget, {
|
|
7005
|
+
recursive: true,
|
|
7006
|
+
force: true
|
|
7007
|
+
});
|
|
7008
|
+
await symlink(await readlink(entrySource), entryTarget);
|
|
7009
|
+
continue;
|
|
7010
|
+
}
|
|
7011
|
+
if (entry.endsWith(".symlink")) {
|
|
7012
|
+
const symlinkTarget = entryTarget.slice(0, -8);
|
|
7013
|
+
await rm(symlinkTarget, {
|
|
7014
|
+
recursive: true,
|
|
7015
|
+
force: true
|
|
7016
|
+
});
|
|
7017
|
+
await symlink(await readFile(entrySource, "utf8"), symlinkTarget);
|
|
7018
|
+
continue;
|
|
7019
|
+
}
|
|
7020
|
+
await restoreBackupTree(entrySource, entryTarget);
|
|
7021
|
+
}
|
|
7022
|
+
}
|
|
6957
7023
|
/** Provides atomic write. */
|
|
6958
7024
|
async function atomicWrite(path, content) {
|
|
6959
7025
|
await mkdir(dirname(path), { recursive: true });
|
|
@@ -7000,23 +7066,31 @@ function assertGitBashReady(platform, resolution) {
|
|
|
7000
7066
|
}
|
|
7001
7067
|
/** Provides install. */
|
|
7002
7068
|
async function install(options, runtime = defaultRuntime) {
|
|
7069
|
+
try {
|
|
7070
|
+
return await installOnce(options, runtime);
|
|
7071
|
+
} finally {
|
|
7072
|
+
await pruneBackupHistory();
|
|
7073
|
+
}
|
|
7074
|
+
}
|
|
7075
|
+
async function installOnce(options, runtime) {
|
|
7003
7076
|
notify(options, "prerequisites", "Checking prerequisites", "running");
|
|
7004
7077
|
assertGitBashReady(runtime.platform, runtime.gitBash());
|
|
7005
7078
|
notify(options, "prerequisites", "Checking prerequisites", "complete");
|
|
7006
7079
|
const target = paths();
|
|
7007
7080
|
const existingConfig = await readText(target.config);
|
|
7008
7081
|
const plan = options.plan ?? readManagedPlan(existingConfig) ?? "plus";
|
|
7009
|
-
const computerUseChoice = resolveComputerUseChoice(options);
|
|
7082
|
+
const computerUseChoice = resolveComputerUseChoice(options, existingConfig);
|
|
7010
7083
|
const root = backupRoot();
|
|
7011
7084
|
notify(options, "backup", "Backing up existing installation", "running");
|
|
7012
7085
|
const configBackup = await backup(target.config, root);
|
|
7013
7086
|
const cacheBackup = await backup(target.marketplaceCache, root);
|
|
7014
7087
|
const agentsBackup = await backup(target.agents, root);
|
|
7088
|
+
const legacyBackups = await Promise.all(target.legacy.map((path) => backup(path, root)));
|
|
7015
7089
|
const backups = [
|
|
7016
7090
|
configBackup,
|
|
7017
7091
|
cacheBackup,
|
|
7018
7092
|
agentsBackup,
|
|
7019
|
-
...
|
|
7093
|
+
...legacyBackups
|
|
7020
7094
|
].filter((path) => path !== void 0);
|
|
7021
7095
|
notify(options, "backup", "Backing up existing installation", "complete", `${backups.length} saved`);
|
|
7022
7096
|
notify(options, "configuration", "Preparing configuration", "running");
|
|
@@ -7083,9 +7157,13 @@ async function install(options, runtime = defaultRuntime) {
|
|
|
7083
7157
|
await removeObsoleteVersionCaches(target.cacheRoot);
|
|
7084
7158
|
notify(options, "cleanup", "Removing obsolete caches", "complete");
|
|
7085
7159
|
} catch (error) {
|
|
7086
|
-
await
|
|
7087
|
-
await
|
|
7088
|
-
await
|
|
7160
|
+
await restoreBackup(target.config, configBackup);
|
|
7161
|
+
await restoreBackup(target.marketplaceCache, cacheBackup);
|
|
7162
|
+
await restoreBackup(target.agents, agentsBackup);
|
|
7163
|
+
await Promise.all(target.legacy.map(async (path, index) => {
|
|
7164
|
+
const source = legacyBackups[index];
|
|
7165
|
+
if (source !== void 0) await restoreBackup(path, source);
|
|
7166
|
+
}));
|
|
7089
7167
|
throw error;
|
|
7090
7168
|
} finally {
|
|
7091
7169
|
await rm(staging, {
|
|
@@ -7093,7 +7171,6 @@ async function install(options, runtime = defaultRuntime) {
|
|
|
7093
7171
|
force: true
|
|
7094
7172
|
});
|
|
7095
7173
|
}
|
|
7096
|
-
await pruneBackupHistory();
|
|
7097
7174
|
return {
|
|
7098
7175
|
action: "install",
|
|
7099
7176
|
changed: [
|
|
@@ -7109,8 +7186,8 @@ async function install(options, runtime = defaultRuntime) {
|
|
|
7109
7186
|
buildWebApps
|
|
7110
7187
|
};
|
|
7111
7188
|
}
|
|
7112
|
-
function resolveComputerUseChoice(options) {
|
|
7113
|
-
return options.computerUse ?? "disabled";
|
|
7189
|
+
function resolveComputerUseChoice(options, existingConfig) {
|
|
7190
|
+
return options.computerUse ?? readManagedComputerUse(existingConfig) ?? "disabled";
|
|
7114
7191
|
}
|
|
7115
7192
|
function computerUseFailure(result) {
|
|
7116
7193
|
const reason = result.reason.replaceAll("-", " ");
|
|
@@ -7139,16 +7216,9 @@ async function validateStaging(cache, agents) {
|
|
|
7139
7216
|
for (const path of required) if (!await exists(path)) missing.push(path);
|
|
7140
7217
|
if (missing.length > 0) throw new Error(`Staged HolyCodex installation is incomplete: ${missing.join(", ")}`);
|
|
7141
7218
|
}
|
|
7142
|
-
async function restoreTarget(target, source) {
|
|
7143
|
-
await rm(target, {
|
|
7144
|
-
recursive: true,
|
|
7145
|
-
force: true
|
|
7146
|
-
});
|
|
7147
|
-
if (source !== void 0) await cp(source, target, { recursive: true });
|
|
7148
|
-
}
|
|
7149
7219
|
async function removeObsoleteVersionCaches(cacheRoot) {
|
|
7150
7220
|
if (!await exists(cacheRoot)) return;
|
|
7151
|
-
for (const entry of await readdir(cacheRoot)) if (entry !== "0.13.
|
|
7221
|
+
for (const entry of await readdir(cacheRoot)) if (entry !== "0.13.5") await rm(join(cacheRoot, entry), {
|
|
7152
7222
|
recursive: true,
|
|
7153
7223
|
force: true
|
|
7154
7224
|
});
|
|
@@ -7157,7 +7227,7 @@ async function pruneBackupHistory() {
|
|
|
7157
7227
|
const root = join(tmpdir(), "holycodex-backups");
|
|
7158
7228
|
if (!await exists(root)) return;
|
|
7159
7229
|
const entries = (await readdir(root)).sort().reverse();
|
|
7160
|
-
await Promise.allSettled(entries.slice(BACKUP_RETENTION
|
|
7230
|
+
await Promise.allSettled(entries.slice(BACKUP_RETENTION).map((entry) => rm(join(root, entry), {
|
|
7161
7231
|
recursive: true,
|
|
7162
7232
|
force: true
|
|
7163
7233
|
})));
|
|
@@ -7256,6 +7326,13 @@ function composeAgentPolicies(input, platform) {
|
|
|
7256
7326
|
}
|
|
7257
7327
|
/** Provides cleanup. */
|
|
7258
7328
|
async function cleanup(_options) {
|
|
7329
|
+
try {
|
|
7330
|
+
return await cleanupOnce();
|
|
7331
|
+
} finally {
|
|
7332
|
+
await pruneBackupHistory();
|
|
7333
|
+
}
|
|
7334
|
+
}
|
|
7335
|
+
async function cleanupOnce() {
|
|
7259
7336
|
const target = paths();
|
|
7260
7337
|
const root = backupRoot();
|
|
7261
7338
|
const backups = [
|
|
@@ -7308,6 +7385,10 @@ function formatCliError(error) {
|
|
|
7308
7385
|
if (!(error instanceof ZodError)) return error instanceof Error ? error.message : String(error);
|
|
7309
7386
|
return error.issues.map((issue) => `${issue.path.length === 0 ? "input" : issue.path.join(".")}: ${issue.message}`).join("; ");
|
|
7310
7387
|
}
|
|
7388
|
+
/** Renders a stable machine-readable CLI failure envelope. */
|
|
7389
|
+
function renderJsonError(message) {
|
|
7390
|
+
return `${JSON.stringify({ error: { message } })}\n`;
|
|
7391
|
+
}
|
|
7311
7392
|
/** Checks whether terminal color output is supported. */
|
|
7312
7393
|
function supportsColor(isTTY, noColor) {
|
|
7313
7394
|
return isTTY === true && noColor === void 0;
|
|
@@ -7317,15 +7398,70 @@ function renderHelp(version, color) {
|
|
|
7317
7398
|
const title = paint(color, `${BOLD}${CYAN}`, `HolyCodex ${version}`);
|
|
7318
7399
|
const section = (text) => paint(color, BOLD, text);
|
|
7319
7400
|
const muted = (text) => paint(color, DIM, text);
|
|
7320
|
-
return `${title}
|
|
7321
|
-
|
|
7401
|
+
return `${title}
|
|
7402
|
+
${muted("Durable Codex workflow installer, doctor, and cleanup")}
|
|
7403
|
+
|
|
7404
|
+
${section("USAGE")}
|
|
7405
|
+
holycodex <command> [options]
|
|
7406
|
+
|
|
7407
|
+
${section("COMMANDS")}
|
|
7408
|
+
install Install or update HolyCodex
|
|
7409
|
+
cleanup Remove HolyCodex-owned state
|
|
7410
|
+
doctor Diagnose installation and runtime
|
|
7411
|
+
|
|
7412
|
+
${section("OPTIONS")}
|
|
7413
|
+
--plan <plan> Model routing plan for install: ${PLAN_HELP}
|
|
7414
|
+
Default: ${DEFAULT_PLAN}
|
|
7415
|
+
--max-subagents <count> Override concurrent direct subagents for install
|
|
7416
|
+
--fast Use Fast for generated subagents only
|
|
7417
|
+
--fast-all Use Fast for Root and generated subagents
|
|
7418
|
+
--no-fast Use Standard for Root and generated subagents
|
|
7419
|
+
-h, --help Show help
|
|
7420
|
+
-v, --version Show version
|
|
7421
|
+
--no-tui Accepted; commands remain noninteractive
|
|
7422
|
+
--codex-autonomous Never ask; keep workspace sandbox
|
|
7423
|
+
--no-codex-autonomous Safe interactive defaults
|
|
7424
|
+
--dangerous-codex-autonomous Never ask; disable filesystem sandbox
|
|
7425
|
+
install --verbose Show detailed install steps
|
|
7426
|
+
--json Print machine-readable output
|
|
7427
|
+
--computer-use Enable and verify the official Computer Use plugin
|
|
7428
|
+
--no-computer-use Keep Computer Use disabled
|
|
7429
|
+
`;
|
|
7322
7430
|
}
|
|
7323
7431
|
/** Renders install-specific model plan and option help. */
|
|
7324
7432
|
function renderInstallHelp(version, color) {
|
|
7325
7433
|
const title = paint(color, `${BOLD}${CYAN}`, `HolyCodex ${version}`);
|
|
7326
7434
|
const section = (text) => `${paint(color, BOLD, text)}${text === "Options:" ? "\n --computer-use Enable and verify the official Computer Use plugin\n --no-computer-use Keep Computer Use disabled" : ""}`;
|
|
7327
|
-
return `${title}
|
|
7328
|
-
|
|
7435
|
+
return `${title}
|
|
7436
|
+
|
|
7437
|
+
${section("Usage:")}
|
|
7438
|
+
holycodex install [options]
|
|
7439
|
+
|
|
7440
|
+
${section("Options:")}
|
|
7441
|
+
--plan <plan> Model routing plan: ${PLAN_HELP}
|
|
7442
|
+
Default: ${DEFAULT_PLAN}
|
|
7443
|
+
--max-subagents <count> Override concurrent direct subagents
|
|
7444
|
+
--fast Use Fast for generated subagents only
|
|
7445
|
+
--fast-all Use Fast for Root and generated subagents
|
|
7446
|
+
--no-fast Use Standard for Root and generated subagents
|
|
7447
|
+
-v, --verbose Show detailed install steps
|
|
7448
|
+
--json Print machine-readable output
|
|
7449
|
+
--no-tui Accepted; install remains noninteractive
|
|
7450
|
+
--codex-autonomous Never ask; keep workspace sandbox
|
|
7451
|
+
--no-codex-autonomous Safe interactive defaults
|
|
7452
|
+
--dangerous-codex-autonomous Never ask; disable filesystem sandbox
|
|
7453
|
+
-h, --help Show help
|
|
7454
|
+
|
|
7455
|
+
Plans provide increasing expected model usage and capability. Fast flags are mutually exclusive.
|
|
7456
|
+
|
|
7457
|
+
${section("Examples:")}
|
|
7458
|
+
bunx holycodex install
|
|
7459
|
+
bunx holycodex install --plan go
|
|
7460
|
+
bunx holycodex install --plan plus-low --fast
|
|
7461
|
+
bunx holycodex install --plan plus-high
|
|
7462
|
+
bunx holycodex install --plan pro-5x --fast-all
|
|
7463
|
+
bunx holycodex install --plan pro-20x --no-fast
|
|
7464
|
+
`;
|
|
7329
7465
|
}
|
|
7330
7466
|
/** Renders error. */
|
|
7331
7467
|
function renderError(message, color) {
|
|
@@ -7394,8 +7530,8 @@ function renderNotice(kind, message, color) {
|
|
|
7394
7530
|
}
|
|
7395
7531
|
//#endregion
|
|
7396
7532
|
//#region packages/cli/src/cli.ts
|
|
7397
|
-
async function main() {
|
|
7398
|
-
const parsed = parseCliArguments(
|
|
7533
|
+
async function main(args = process$1.argv.slice(2)) {
|
|
7534
|
+
const parsed = parseCliArguments(args);
|
|
7399
7535
|
const stdoutColor = supportsColor(process$1.stdout.isTTY, process$1.env.NO_COLOR);
|
|
7400
7536
|
const stderrColor = supportsColor(process$1.stderr.isTTY, process$1.env.NO_COLOR);
|
|
7401
7537
|
if (parsed.action === "help") {
|
|
@@ -7422,15 +7558,18 @@ async function main() {
|
|
|
7422
7558
|
if (!result.healthy) process$1.exitCode = 1;
|
|
7423
7559
|
return;
|
|
7424
7560
|
}
|
|
7425
|
-
if (parsed.autonomy.requested && parsed.autonomy.mode === "dangerous") process$1.stderr.write(renderNotice("warning", "Dangerous autonomy disables approvals and filesystem sandboxing.", stderrColor));
|
|
7561
|
+
if (!parsed.json && parsed.autonomy.requested && parsed.autonomy.mode === "dangerous") process$1.stderr.write(renderNotice("warning", "Dangerous autonomy disables approvals and filesystem sandboxing.", stderrColor));
|
|
7426
7562
|
const result = parsed.command === "install" ? await install(options) : await cleanup(options);
|
|
7427
7563
|
process$1.stdout.write(parsed.json ? `${JSON.stringify(result)}\n` : renderRunResult(result, stdoutColor));
|
|
7428
7564
|
}
|
|
7429
7565
|
try {
|
|
7430
7566
|
await main();
|
|
7431
7567
|
} catch (error) {
|
|
7432
|
-
|
|
7433
|
-
|
|
7568
|
+
if (process$1.argv.slice(2).includes("--json")) process$1.stderr.write(renderJsonError(formatCliError(error)));
|
|
7569
|
+
else {
|
|
7570
|
+
const color = supportsColor(process$1.stderr.isTTY, process$1.env.NO_COLOR);
|
|
7571
|
+
process$1.stderr.write(renderError(formatCliError(error), color));
|
|
7572
|
+
}
|
|
7434
7573
|
process$1.exitCode = 1;
|
|
7435
7574
|
}
|
|
7436
7575
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holycodex",
|
|
3
|
-
"version": "0.13.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.13.5",
|
|
4
|
+
"description": "HolyCodex installer, doctor, and cleanup CLI for durable Codex workflows",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
7
7
|
"chatgpt",
|
|
8
8
|
"codex",
|
|
9
|
-
"developer-tools"
|
|
9
|
+
"developer-tools",
|
|
10
|
+
"lsp",
|
|
11
|
+
"orchestration",
|
|
12
|
+
"workflows"
|
|
10
13
|
],
|
|
11
14
|
"homepage": "https://github.com/davidbasilefilho/holycodex#readme",
|
|
12
15
|
"bugs": {
|
|
@@ -39,7 +42,7 @@
|
|
|
39
42
|
"prepack": "vp run --workspace-root build"
|
|
40
43
|
},
|
|
41
44
|
"dependencies": {
|
|
42
|
-
"@holycodex/plugin": "0.13.
|
|
45
|
+
"@holycodex/plugin": "0.13.5",
|
|
43
46
|
"zod": "^4.4.3"
|
|
44
47
|
},
|
|
45
48
|
"devDependencies": {
|