@zeroxyz/cli 1.7.0 → 1.8.0
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 +24 -2
- package/dist/index.js +623 -165
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,17 +4,26 @@ The `zero` CLI lets AI agents discover, call, and review capabilities indexed by
|
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The npm package is the bootstrap and manual CLI. Agent sessions should run through
|
|
8
|
+
the Zero plugin's managed runner, which auto-updates at `~/.zero/runtime/bin/zero`.
|
|
8
9
|
|
|
9
10
|
```bash
|
|
10
11
|
npm install -g @zeroxyz/cli
|
|
12
|
+
zero init
|
|
13
|
+
zero auth login
|
|
11
14
|
```
|
|
12
15
|
|
|
16
|
+
`zero init` installs the Zero plugin through supported harness CLIs when they are
|
|
17
|
+
callable from the current shell (`codex`, `claude`, `gemini`, `openclaw`). If no
|
|
18
|
+
plugin install succeeds, it falls back to the standalone skill/hook install under
|
|
19
|
+
`~/.claude` and `~/.agents`, with hooks registered in `~/.claude/settings.json`
|
|
20
|
+
and `~/.codex/hooks.json`.
|
|
21
|
+
|
|
13
22
|
## Breaking changes
|
|
14
23
|
|
|
15
24
|
### 1.0.0
|
|
16
25
|
|
|
17
|
-
- **`zero init` no longer
|
|
26
|
+
- **`zero init` no longer creates a local wallet.** It installs the Zero plugin when possible and otherwise writes the standalone skill/hooks. `zero uninstall` removes the standalone files; host plugin installs are managed by their harnesses.
|
|
18
27
|
- **`zero welcome` was removed.** The welcome bonus is claimed by signing in (`zero auth login`).
|
|
19
28
|
- **The legacy `privateKey` field in `~/.zero/config.json` is no longer an identity and never pays.** Wallets created by a pre-1.0 `zero init` stop signing requests and payments. Pick one of:
|
|
20
29
|
- **Recommended:** sign in and sweep the old wallet's funds into your managed Zero wallet:
|
|
@@ -53,6 +62,19 @@ zero review <runId> --success --accuracy 5 --value 4 --reliability 5
|
|
|
53
62
|
|
|
54
63
|
## Commands
|
|
55
64
|
|
|
65
|
+
### `zero init`
|
|
66
|
+
|
|
67
|
+
Bootstrap Zero for agent harnesses.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
zero init # target every supported agent
|
|
71
|
+
zero init --agent codex # only Codex
|
|
72
|
+
zero init --agent claude,codex # comma-separated or repeat --agent
|
|
73
|
+
zero init --agent standalone # only standalone skills + Claude/Codex hooks
|
|
74
|
+
zero init --no-fallback # fail instead of writing standalone fallback
|
|
75
|
+
zero init --dry-run # preview actions
|
|
76
|
+
```
|
|
77
|
+
|
|
56
78
|
### `zero auth`
|
|
57
79
|
|
|
58
80
|
Sign in and out of Zero. Signing in provisions a managed Zero wallet that signs your payments.
|
package/dist/index.js
CHANGED
|
@@ -52631,12 +52631,12 @@ var require_array = __commonJS({
|
|
|
52631
52631
|
if (Array.isArray(values)) {
|
|
52632
52632
|
arrayValues = values;
|
|
52633
52633
|
} else if (values && typeof values === "object") {
|
|
52634
|
-
let
|
|
52634
|
+
let unique2 = {};
|
|
52635
52635
|
arrayValues = coders.map((coder) => {
|
|
52636
52636
|
const name = coder.localName;
|
|
52637
52637
|
(0, index_js_1.assert)(name, "cannot encode object for signature with missing names", "INVALID_ARGUMENT", { argument: "values", info: { coder }, value: values });
|
|
52638
|
-
(0, index_js_1.assert)(!
|
|
52639
|
-
|
|
52638
|
+
(0, index_js_1.assert)(!unique2[name], "cannot encode object for signature with duplicate names", "INVALID_ARGUMENT", { argument: "values", info: { coder }, value: values });
|
|
52639
|
+
unique2[name] = true;
|
|
52640
52640
|
return values[name];
|
|
52641
52641
|
});
|
|
52642
52642
|
} else {
|
|
@@ -55096,10 +55096,10 @@ var require_dist = __commonJS({
|
|
|
55096
55096
|
}
|
|
55097
55097
|
}
|
|
55098
55098
|
check_fenced(norm);
|
|
55099
|
-
let
|
|
55100
|
-
let [g2] = determine_group(
|
|
55099
|
+
let unique2 = Array_from(new Set(chars));
|
|
55100
|
+
let [g2] = determine_group(unique2);
|
|
55101
55101
|
check_group(g2, chars);
|
|
55102
|
-
check_whole(g2,
|
|
55102
|
+
check_whole(g2, unique2);
|
|
55103
55103
|
type2 = g2.N;
|
|
55104
55104
|
}
|
|
55105
55105
|
}
|
|
@@ -55110,10 +55110,10 @@ var require_dist = __commonJS({
|
|
|
55110
55110
|
return info;
|
|
55111
55111
|
});
|
|
55112
55112
|
}
|
|
55113
|
-
function check_whole(group,
|
|
55113
|
+
function check_whole(group, unique2) {
|
|
55114
55114
|
let maker;
|
|
55115
55115
|
let shared = [];
|
|
55116
|
-
for (let cp of
|
|
55116
|
+
for (let cp of unique2) {
|
|
55117
55117
|
let whole = WHOLE_MAP.get(cp);
|
|
55118
55118
|
if (whole === UNIQUE_PH) return;
|
|
55119
55119
|
if (whole) {
|
|
@@ -55132,9 +55132,9 @@ var require_dist = __commonJS({
|
|
|
55132
55132
|
}
|
|
55133
55133
|
}
|
|
55134
55134
|
}
|
|
55135
|
-
function determine_group(
|
|
55135
|
+
function determine_group(unique2) {
|
|
55136
55136
|
let groups = GROUPS;
|
|
55137
|
-
for (let cp of
|
|
55137
|
+
for (let cp of unique2) {
|
|
55138
55138
|
let gs = groups.filter((g2) => group_has_cp(g2, cp));
|
|
55139
55139
|
if (!gs.length) {
|
|
55140
55140
|
if (!GROUPS.some((g2) => group_has_cp(g2, cp))) {
|
|
@@ -76582,7 +76582,7 @@ init_esm_shims();
|
|
|
76582
76582
|
|
|
76583
76583
|
// package.json
|
|
76584
76584
|
var package_default = {
|
|
76585
|
-
version: "1.
|
|
76585
|
+
version: "1.8.0"};
|
|
76586
76586
|
|
|
76587
76587
|
// src/app.ts
|
|
76588
76588
|
init_esm_shims();
|
|
@@ -77590,7 +77590,7 @@ init_esm_shims();
|
|
|
77590
77590
|
// ../sdk/dist/index.js
|
|
77591
77591
|
init_esm_shims();
|
|
77592
77592
|
|
|
77593
|
-
// ../sdk/dist/chunk-
|
|
77593
|
+
// ../sdk/dist/chunk-W7JBWVWW.js
|
|
77594
77594
|
init_esm_shims();
|
|
77595
77595
|
|
|
77596
77596
|
// ../../node_modules/.pnpm/viem@2.52.2_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@4.3.6/node_modules/viem/_esm/index.js
|
|
@@ -145833,6 +145833,9 @@ var searchResultSchema = external_exports3.object({
|
|
|
145833
145833
|
cost: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }),
|
|
145834
145834
|
reviewCount: external_exports3.number().optional(),
|
|
145835
145835
|
rating: ratingSchema,
|
|
145836
|
+
// All-time activation count (non-deleted runs), mirroring capabilities.ts.
|
|
145837
|
+
// Optional so a response from an older API deploy still parses (ZERO-385).
|
|
145838
|
+
activationCount: external_exports3.number().optional(),
|
|
145836
145839
|
availabilityStatus: external_exports3.enum(["healthy", "unknown", "down"]).nullable().optional(),
|
|
145837
145840
|
/**
|
|
145838
145841
|
* @deprecated The API no longer emits `displayStatus`; it has been replaced
|
|
@@ -147591,9 +147594,251 @@ var sectionDivider = () => {
|
|
|
147591
147594
|
console.log("");
|
|
147592
147595
|
};
|
|
147593
147596
|
|
|
147597
|
+
// src/util/json-config-file.ts
|
|
147598
|
+
init_esm_shims();
|
|
147599
|
+
var updateJsonConfigFile = (path3, update2, options = {}) => {
|
|
147600
|
+
let config2 = {};
|
|
147601
|
+
if (existsSync(path3)) {
|
|
147602
|
+
try {
|
|
147603
|
+
config2 = JSON.parse(readFileSync(path3, "utf-8"));
|
|
147604
|
+
} catch {
|
|
147605
|
+
return { status: "unparseable", path: path3 };
|
|
147606
|
+
}
|
|
147607
|
+
} else if (!options.createIfMissing) {
|
|
147608
|
+
return { status: "missing", path: path3 };
|
|
147609
|
+
}
|
|
147610
|
+
const changed = update2(config2);
|
|
147611
|
+
if (!changed) return { status: "unchanged", path: path3 };
|
|
147612
|
+
mkdirSync(dirname(path3), { recursive: true });
|
|
147613
|
+
writeFileSync(path3, `${JSON.stringify(config2, null, 2)}
|
|
147614
|
+
`);
|
|
147615
|
+
return { status: "updated", path: path3 };
|
|
147616
|
+
};
|
|
147617
|
+
|
|
147594
147618
|
// src/commands/init-command.ts
|
|
147595
147619
|
var SKILL_DIRS = [".claude/skills", ".agents/skills"];
|
|
147596
147620
|
var ZERO_SANDBOX_DOMAIN = "*.zero.xyz";
|
|
147621
|
+
var CLAUDE_SETTINGS_PATH = ".claude/settings.json";
|
|
147622
|
+
var CODEX_HOOKS_PATH = ".codex/hooks.json";
|
|
147623
|
+
var PLUGIN_AGENTS = ["codex", "claude", "gemini", "openclaw"];
|
|
147624
|
+
var INIT_AGENTS = [...PLUGIN_AGENTS, "standalone"];
|
|
147625
|
+
var initAgentSchema = zod_default.enum(INIT_AGENTS);
|
|
147626
|
+
var HARNESS_SPECS = {
|
|
147627
|
+
claude: {
|
|
147628
|
+
agent: "claude",
|
|
147629
|
+
displayName: "Claude Code",
|
|
147630
|
+
executable: "claude",
|
|
147631
|
+
installCommands: [
|
|
147632
|
+
{
|
|
147633
|
+
label: "add marketplace",
|
|
147634
|
+
command: "claude",
|
|
147635
|
+
args: ["plugin", "marketplace", "add", "officialzeroxyz/zero-plugins"],
|
|
147636
|
+
required: false
|
|
147637
|
+
},
|
|
147638
|
+
{
|
|
147639
|
+
label: "install plugin",
|
|
147640
|
+
command: "claude",
|
|
147641
|
+
args: ["plugin", "install", "zero@zero-plugins"]
|
|
147642
|
+
}
|
|
147643
|
+
],
|
|
147644
|
+
manualInstructions: [
|
|
147645
|
+
"Claude Code Desktop: open the Code tab, choose Customize, then add a Personal plugin marketplace from officialzeroxyz/zero-plugins.",
|
|
147646
|
+
"After it syncs, click the + icon on the Zero plugin, then start a new session and ask Claude to help set up and test Zero."
|
|
147647
|
+
]
|
|
147648
|
+
},
|
|
147649
|
+
codex: {
|
|
147650
|
+
agent: "codex",
|
|
147651
|
+
displayName: "Codex",
|
|
147652
|
+
executable: "codex",
|
|
147653
|
+
installCommands: [
|
|
147654
|
+
{
|
|
147655
|
+
label: "add marketplace",
|
|
147656
|
+
command: "codex",
|
|
147657
|
+
args: ["plugin", "marketplace", "add", "officialzeroxyz/zero-plugins"],
|
|
147658
|
+
required: false
|
|
147659
|
+
},
|
|
147660
|
+
{
|
|
147661
|
+
label: "install plugin",
|
|
147662
|
+
command: "codex",
|
|
147663
|
+
args: ["plugin", "add", "zero@zero-plugins"]
|
|
147664
|
+
}
|
|
147665
|
+
],
|
|
147666
|
+
manualInstructions: [
|
|
147667
|
+
"Codex app: open Plugins in the sidebar, click +, then add marketplace officialzeroxyz/zero-plugins.",
|
|
147668
|
+
"Select the Zero filter, click Add plugin on Zero, then start a new chat and ask Codex to help set up and test Zero."
|
|
147669
|
+
]
|
|
147670
|
+
},
|
|
147671
|
+
gemini: {
|
|
147672
|
+
agent: "gemini",
|
|
147673
|
+
displayName: "Gemini CLI",
|
|
147674
|
+
executable: "gemini",
|
|
147675
|
+
installCommands: [
|
|
147676
|
+
{
|
|
147677
|
+
label: "install extension",
|
|
147678
|
+
command: "gemini",
|
|
147679
|
+
args: [
|
|
147680
|
+
"extensions",
|
|
147681
|
+
"install",
|
|
147682
|
+
"https://github.com/officialzeroxyz/zero-plugins",
|
|
147683
|
+
"--auto-update"
|
|
147684
|
+
]
|
|
147685
|
+
}
|
|
147686
|
+
],
|
|
147687
|
+
manualInstructions: [
|
|
147688
|
+
"Gemini CLI: run this from a shell where `gemini` is on PATH: gemini extensions install https://github.com/officialzeroxyz/zero-plugins --auto-update"
|
|
147689
|
+
]
|
|
147690
|
+
},
|
|
147691
|
+
openclaw: {
|
|
147692
|
+
agent: "openclaw",
|
|
147693
|
+
displayName: "OpenClaw",
|
|
147694
|
+
executable: "openclaw",
|
|
147695
|
+
installCommands: [
|
|
147696
|
+
{
|
|
147697
|
+
label: "install plugin",
|
|
147698
|
+
command: "openclaw",
|
|
147699
|
+
args: [
|
|
147700
|
+
"plugins",
|
|
147701
|
+
"install",
|
|
147702
|
+
"zero",
|
|
147703
|
+
"--marketplace",
|
|
147704
|
+
"officialzeroxyz/zero-plugins"
|
|
147705
|
+
]
|
|
147706
|
+
}
|
|
147707
|
+
],
|
|
147708
|
+
manualInstructions: [
|
|
147709
|
+
"OpenClaw: run this from a shell where `openclaw` is on PATH: openclaw plugins install zero --marketplace officialzeroxyz/zero-plugins"
|
|
147710
|
+
]
|
|
147711
|
+
}
|
|
147712
|
+
};
|
|
147713
|
+
var unique = (items) => [...new Set(items)];
|
|
147714
|
+
var parseAgentValues = (values) => {
|
|
147715
|
+
if (!values || values.length === 0) {
|
|
147716
|
+
return {
|
|
147717
|
+
kind: "default",
|
|
147718
|
+
requestedAgents: [...PLUGIN_AGENTS],
|
|
147719
|
+
pluginAgents: [...PLUGIN_AGENTS]
|
|
147720
|
+
};
|
|
147721
|
+
}
|
|
147722
|
+
const parsed = unique(
|
|
147723
|
+
values.flatMap(
|
|
147724
|
+
(value) => value.split(",").map((part) => part.trim().toLowerCase()).filter(Boolean)
|
|
147725
|
+
)
|
|
147726
|
+
);
|
|
147727
|
+
if (parsed.length === 0) {
|
|
147728
|
+
throw new Error("Pass at least one agent name to --agent");
|
|
147729
|
+
}
|
|
147730
|
+
const agents = parsed.map((value) => {
|
|
147731
|
+
const result = initAgentSchema.safeParse(value);
|
|
147732
|
+
if (!result.success) {
|
|
147733
|
+
throw new Error(
|
|
147734
|
+
`Unknown agent "${value}". Expected one of: ${INIT_AGENTS.join(", ")}`
|
|
147735
|
+
);
|
|
147736
|
+
}
|
|
147737
|
+
return result.data;
|
|
147738
|
+
});
|
|
147739
|
+
if (agents.includes("standalone") && agents.length > 1) {
|
|
147740
|
+
throw new Error(
|
|
147741
|
+
"`standalone` cannot be combined with other --agent values; run it separately."
|
|
147742
|
+
);
|
|
147743
|
+
}
|
|
147744
|
+
if (agents[0] === "standalone") {
|
|
147745
|
+
return { kind: "standalone", requestedAgents: agents, pluginAgents: [] };
|
|
147746
|
+
}
|
|
147747
|
+
return {
|
|
147748
|
+
kind: "specific",
|
|
147749
|
+
requestedAgents: agents,
|
|
147750
|
+
pluginAgents: agents
|
|
147751
|
+
};
|
|
147752
|
+
};
|
|
147753
|
+
var collectAgentOption = (value, previous = []) => [
|
|
147754
|
+
...previous,
|
|
147755
|
+
value
|
|
147756
|
+
];
|
|
147757
|
+
var commandSummary = (command, args) => [command, ...args].join(" ");
|
|
147758
|
+
var commandOutput = (result) => {
|
|
147759
|
+
const chunks = [result.stderr, result.stdout].map((chunk) => typeof chunk === "string" ? chunk.trim() : "").filter(Boolean);
|
|
147760
|
+
return chunks.join("\n").trim();
|
|
147761
|
+
};
|
|
147762
|
+
var commandErrorDetail = (result, fallback2) => {
|
|
147763
|
+
if (result.error) return result.error.message;
|
|
147764
|
+
const output = commandOutput(result);
|
|
147765
|
+
if (output.length > 0) return truncateError(output);
|
|
147766
|
+
if (result.signal) return `${fallback2} exited via signal ${result.signal}`;
|
|
147767
|
+
return `${fallback2} exited with status ${result.status ?? "unknown"}`;
|
|
147768
|
+
};
|
|
147769
|
+
var isCommandCallable = (command) => {
|
|
147770
|
+
if (process.platform === "win32") {
|
|
147771
|
+
const result2 = spawnSync("where.exe", [command], {
|
|
147772
|
+
encoding: "utf8",
|
|
147773
|
+
stdio: "ignore"
|
|
147774
|
+
});
|
|
147775
|
+
return result2.status === 0;
|
|
147776
|
+
}
|
|
147777
|
+
const result = spawnSync("/bin/sh", ["-c", `command -v ${command}`], {
|
|
147778
|
+
encoding: "utf8",
|
|
147779
|
+
stdio: "ignore"
|
|
147780
|
+
});
|
|
147781
|
+
return result.status === 0;
|
|
147782
|
+
};
|
|
147783
|
+
var installHarnessPlugin = (spec, options) => {
|
|
147784
|
+
if (options.dryRun) {
|
|
147785
|
+
for (const step of spec.installCommands) {
|
|
147786
|
+
stepInfo(`would run: ${commandSummary(step.command, step.args)}`);
|
|
147787
|
+
}
|
|
147788
|
+
return {
|
|
147789
|
+
agent: spec.agent,
|
|
147790
|
+
displayName: spec.displayName,
|
|
147791
|
+
status: "would_install",
|
|
147792
|
+
detail: "dry run"
|
|
147793
|
+
};
|
|
147794
|
+
}
|
|
147795
|
+
let optionalFailure;
|
|
147796
|
+
for (const step of spec.installCommands) {
|
|
147797
|
+
if (options.verbose) {
|
|
147798
|
+
stepInfo(`running: ${commandSummary(step.command, step.args)}`);
|
|
147799
|
+
}
|
|
147800
|
+
const result = spawnSync(step.command, step.args, {
|
|
147801
|
+
encoding: "utf8",
|
|
147802
|
+
stdio: "pipe",
|
|
147803
|
+
env: process.env
|
|
147804
|
+
});
|
|
147805
|
+
if (result.status === 0) continue;
|
|
147806
|
+
const detail = commandErrorDetail(result, step.label);
|
|
147807
|
+
if (step.required === false) {
|
|
147808
|
+
optionalFailure = `${step.label}: ${detail}`;
|
|
147809
|
+
if (options.verbose) stepInfo(`${optionalFailure}; continuing`);
|
|
147810
|
+
continue;
|
|
147811
|
+
}
|
|
147812
|
+
return {
|
|
147813
|
+
agent: spec.agent,
|
|
147814
|
+
displayName: spec.displayName,
|
|
147815
|
+
status: "failed",
|
|
147816
|
+
detail
|
|
147817
|
+
};
|
|
147818
|
+
}
|
|
147819
|
+
return {
|
|
147820
|
+
agent: spec.agent,
|
|
147821
|
+
displayName: spec.displayName,
|
|
147822
|
+
status: "installed",
|
|
147823
|
+
detail: optionalFailure ? `installed; ignored ${optionalFailure}` : void 0
|
|
147824
|
+
};
|
|
147825
|
+
};
|
|
147826
|
+
var printManualInstructions = (spec) => {
|
|
147827
|
+
for (const line of spec.manualInstructions) {
|
|
147828
|
+
console.log(` ${color.gray("\xB7")} ${color.dim(line)}`);
|
|
147829
|
+
}
|
|
147830
|
+
};
|
|
147831
|
+
var fallbackReason = (selection, detectedAgents, results) => {
|
|
147832
|
+
if (selection.kind === "standalone")
|
|
147833
|
+
return "--agent standalone was requested";
|
|
147834
|
+
if (selection.kind === "default" && detectedAgents.length === 0) {
|
|
147835
|
+
return "no supported harness CLIs were callable in this shell";
|
|
147836
|
+
}
|
|
147837
|
+
if (results.every((result) => result.status === "skipped_unavailable")) {
|
|
147838
|
+
return "no requested harness CLIs were callable in this shell";
|
|
147839
|
+
}
|
|
147840
|
+
return "no plugin install succeeded";
|
|
147841
|
+
};
|
|
147597
147842
|
var PLUGIN_HOOKS_ROOT = "${CLAUDE_PLUGIN_ROOT}/hooks";
|
|
147598
147843
|
var SCRIPT_NAME_PATTERN = /\$\{CLAUDE_PLUGIN_ROOT\}\/hooks\/([a-z0-9][a-z0-9-]*\.sh)/;
|
|
147599
147844
|
var fetchText = async (url4) => {
|
|
@@ -147658,59 +147903,7 @@ var installHookScripts = async (home, hooksJson, webBase, verbose) => {
|
|
|
147658
147903
|
})
|
|
147659
147904
|
);
|
|
147660
147905
|
};
|
|
147661
|
-
var
|
|
147662
|
-
const hooksDir = join(home, ".zero", "hooks");
|
|
147663
|
-
const settingsPath = join(home, ".claude", "settings.json");
|
|
147664
|
-
let settings = {};
|
|
147665
|
-
if (existsSync(settingsPath)) {
|
|
147666
|
-
try {
|
|
147667
|
-
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
147668
|
-
} catch {
|
|
147669
|
-
stepWarn(
|
|
147670
|
-
"Hooks not registered",
|
|
147671
|
-
`${settingsPath} is not valid JSON \u2014 fix it and re-run \`zero init\``
|
|
147672
|
-
);
|
|
147673
|
-
return false;
|
|
147674
|
-
}
|
|
147675
|
-
}
|
|
147676
|
-
if (!settings.hooks || typeof settings.hooks !== "object") {
|
|
147677
|
-
settings.hooks = {};
|
|
147678
|
-
}
|
|
147679
|
-
const hooks = settings.hooks;
|
|
147680
|
-
for (const [event, entries] of Object.entries(hooksJson.hooks)) {
|
|
147681
|
-
for (const entry of entries ?? []) {
|
|
147682
|
-
const scripts = entryScriptNames(entry);
|
|
147683
|
-
if (scripts.length === 0) {
|
|
147684
|
-
if (verbose) {
|
|
147685
|
-
stepInfo(`${event}: entry has no plugin hook script \u2014 skipped`);
|
|
147686
|
-
}
|
|
147687
|
-
continue;
|
|
147688
|
-
}
|
|
147689
|
-
const rewritten = {
|
|
147690
|
-
...entry,
|
|
147691
|
-
hooks: (entry.hooks ?? []).map((hook) => ({
|
|
147692
|
-
...hook,
|
|
147693
|
-
command: typeof hook.command === "string" ? hook.command.replaceAll(PLUGIN_HOOKS_ROOT, hooksDir) : hook.command
|
|
147694
|
-
}))
|
|
147695
|
-
};
|
|
147696
|
-
if (!Array.isArray(hooks[event])) hooks[event] = [];
|
|
147697
|
-
const list2 = hooks[event];
|
|
147698
|
-
const existingIdx = list2.findIndex((existing) => {
|
|
147699
|
-
const existingHooks = existing?.hooks;
|
|
147700
|
-
if (!Array.isArray(existingHooks)) return false;
|
|
147701
|
-
return existingHooks.some(
|
|
147702
|
-
(h2) => typeof h2.command === "string" && scripts.some((s) => h2.command.includes(s))
|
|
147703
|
-
);
|
|
147704
|
-
});
|
|
147705
|
-
if (existingIdx >= 0) {
|
|
147706
|
-
list2[existingIdx] = rewritten;
|
|
147707
|
-
if (verbose) stepInfo(`${event}: ${scripts.join(", ")} entry replaced`);
|
|
147708
|
-
} else {
|
|
147709
|
-
list2.push(rewritten);
|
|
147710
|
-
if (verbose) stepInfo(`${event}: ${scripts.join(", ")} entry appended`);
|
|
147711
|
-
}
|
|
147712
|
-
}
|
|
147713
|
-
}
|
|
147906
|
+
var ensureZeroSandboxAllowlist = (settings, verbose) => {
|
|
147714
147907
|
if (!settings.sandbox || typeof settings.sandbox !== "object") {
|
|
147715
147908
|
settings.sandbox = {};
|
|
147716
147909
|
}
|
|
@@ -147729,86 +147922,326 @@ var registerHooksInClaudeSettings = (home, hooksJson, verbose) => {
|
|
|
147729
147922
|
stepInfo(`sandbox.network.allowedDomains += ${ZERO_SANDBOX_DOMAIN}`);
|
|
147730
147923
|
}
|
|
147731
147924
|
}
|
|
147732
|
-
|
|
147733
|
-
|
|
147734
|
-
|
|
147925
|
+
};
|
|
147926
|
+
var registerHooksInJsonFile = (home, hooksJson, target, verbose) => {
|
|
147927
|
+
const hooksDir = join(home, ".zero", "hooks");
|
|
147928
|
+
const configPath = join(home, target.relativePath);
|
|
147929
|
+
const result = updateJsonConfigFile(
|
|
147930
|
+
configPath,
|
|
147931
|
+
(config2) => {
|
|
147932
|
+
if (!config2.hooks || typeof config2.hooks !== "object") {
|
|
147933
|
+
config2.hooks = {};
|
|
147934
|
+
}
|
|
147935
|
+
const hooks = config2.hooks;
|
|
147936
|
+
for (const [event, entries] of Object.entries(hooksJson.hooks)) {
|
|
147937
|
+
for (const entry of entries ?? []) {
|
|
147938
|
+
const scripts = entryScriptNames(entry);
|
|
147939
|
+
if (scripts.length === 0) {
|
|
147940
|
+
if (verbose) {
|
|
147941
|
+
stepInfo(`${event}: entry has no plugin hook script \u2014 skipped`);
|
|
147942
|
+
}
|
|
147943
|
+
continue;
|
|
147944
|
+
}
|
|
147945
|
+
const rewritten = {
|
|
147946
|
+
...entry,
|
|
147947
|
+
hooks: (entry.hooks ?? []).map((hook) => ({
|
|
147948
|
+
...hook,
|
|
147949
|
+
command: typeof hook.command === "string" ? hook.command.replaceAll(PLUGIN_HOOKS_ROOT, hooksDir) : hook.command
|
|
147950
|
+
}))
|
|
147951
|
+
};
|
|
147952
|
+
if (!Array.isArray(hooks[event])) hooks[event] = [];
|
|
147953
|
+
const list2 = hooks[event];
|
|
147954
|
+
const existingIdx = list2.findIndex((existing) => {
|
|
147955
|
+
const existingHooks = existing?.hooks;
|
|
147956
|
+
if (!Array.isArray(existingHooks)) return false;
|
|
147957
|
+
return existingHooks.some(
|
|
147958
|
+
(h2) => typeof h2.command === "string" && scripts.some((s) => h2.command.includes(s))
|
|
147959
|
+
);
|
|
147960
|
+
});
|
|
147961
|
+
if (existingIdx >= 0) {
|
|
147962
|
+
list2[existingIdx] = rewritten;
|
|
147963
|
+
if (verbose) {
|
|
147964
|
+
stepInfo(`${event}: ${scripts.join(", ")} entry replaced`);
|
|
147965
|
+
}
|
|
147966
|
+
} else {
|
|
147967
|
+
list2.push(rewritten);
|
|
147968
|
+
if (verbose) {
|
|
147969
|
+
stepInfo(`${event}: ${scripts.join(", ")} entry appended`);
|
|
147970
|
+
}
|
|
147971
|
+
}
|
|
147972
|
+
}
|
|
147973
|
+
}
|
|
147974
|
+
if (target.includeSandboxAllowlist) {
|
|
147975
|
+
ensureZeroSandboxAllowlist(config2, verbose);
|
|
147976
|
+
}
|
|
147977
|
+
return true;
|
|
147978
|
+
},
|
|
147979
|
+
{ createIfMissing: true }
|
|
147980
|
+
);
|
|
147981
|
+
if (result.status === "unparseable") {
|
|
147982
|
+
stepWarn(
|
|
147983
|
+
"Hooks not registered",
|
|
147984
|
+
`${configPath} is not valid JSON \u2014 fix it and re-run \`zero init\``
|
|
147985
|
+
);
|
|
147986
|
+
return false;
|
|
147987
|
+
}
|
|
147735
147988
|
return true;
|
|
147736
147989
|
};
|
|
147990
|
+
var runStandaloneInit = async (appContext, options = {}) => {
|
|
147991
|
+
const verbose = options.verbose ?? false;
|
|
147992
|
+
options.onStep?.("fetch");
|
|
147993
|
+
console.log("");
|
|
147994
|
+
console.log(` ${color.boldCyan("Installing standalone Zero fallback")}`);
|
|
147995
|
+
console.log("");
|
|
147996
|
+
console.log(color.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
147997
|
+
console.log("");
|
|
147998
|
+
const home = homedir();
|
|
147999
|
+
const webBase = appContext.env.ZERO_WEB_URL;
|
|
148000
|
+
const [skillMd, hooksJsonRaw] = await Promise.all([
|
|
148001
|
+
fetchText(`${webBase}/SKILL.md`),
|
|
148002
|
+
fetchText(`${webBase}/hooks.json`)
|
|
148003
|
+
]);
|
|
148004
|
+
let hooksJson;
|
|
148005
|
+
try {
|
|
148006
|
+
hooksJson = JSON.parse(hooksJsonRaw);
|
|
148007
|
+
} catch {
|
|
148008
|
+
throw new Error(`${webBase}/hooks.json is not valid JSON`);
|
|
148009
|
+
}
|
|
148010
|
+
if (!hooksJson?.hooks || typeof hooksJson.hooks !== "object") {
|
|
148011
|
+
throw new Error(`${webBase}/hooks.json has no "hooks" object`);
|
|
148012
|
+
}
|
|
148013
|
+
if (verbose) {
|
|
148014
|
+
stepInfo(`fetched ${webBase}/SKILL.md and ${webBase}/hooks.json`);
|
|
148015
|
+
}
|
|
148016
|
+
options.onStep?.("skill");
|
|
148017
|
+
const skillsDirs = unique([
|
|
148018
|
+
...SKILL_DIRS.map((dir) => join(home, dir)),
|
|
148019
|
+
...(options.skillsDir ?? []).map((dir) => expandHome(dir, home))
|
|
148020
|
+
]);
|
|
148021
|
+
const skillsInstalled = installSkill(skillsDirs, skillMd, verbose);
|
|
148022
|
+
if (skillsInstalled.length === 0) {
|
|
148023
|
+
throw new Error("could not write the Zero skill to any skills directory");
|
|
148024
|
+
}
|
|
148025
|
+
stepSuccess("Skill installed", `${skillsInstalled.length} locations`);
|
|
148026
|
+
options.onStep?.("hooks");
|
|
148027
|
+
const hookScriptsInstalled = await installHookScripts(
|
|
148028
|
+
home,
|
|
148029
|
+
hooksJson,
|
|
148030
|
+
webBase,
|
|
148031
|
+
verbose
|
|
148032
|
+
);
|
|
148033
|
+
stepSuccess("Hook scripts installed", "~/.zero/hooks");
|
|
148034
|
+
options.onStep?.("settings");
|
|
148035
|
+
const settingsRegistered = registerHooksInJsonFile(
|
|
148036
|
+
home,
|
|
148037
|
+
hooksJson,
|
|
148038
|
+
{
|
|
148039
|
+
relativePath: CLAUDE_SETTINGS_PATH,
|
|
148040
|
+
includeSandboxAllowlist: true
|
|
148041
|
+
},
|
|
148042
|
+
verbose
|
|
148043
|
+
);
|
|
148044
|
+
if (settingsRegistered) {
|
|
148045
|
+
stepSuccess("Hooks registered", "~/.claude/settings.json");
|
|
148046
|
+
}
|
|
148047
|
+
const codexHooksRegistered = registerHooksInJsonFile(
|
|
148048
|
+
home,
|
|
148049
|
+
hooksJson,
|
|
148050
|
+
{
|
|
148051
|
+
relativePath: CODEX_HOOKS_PATH,
|
|
148052
|
+
includeSandboxAllowlist: false
|
|
148053
|
+
},
|
|
148054
|
+
verbose
|
|
148055
|
+
);
|
|
148056
|
+
if (codexHooksRegistered) {
|
|
148057
|
+
stepSuccess("Codex hooks registered", "~/.codex/hooks.json");
|
|
148058
|
+
}
|
|
148059
|
+
return {
|
|
148060
|
+
skillsInstalled,
|
|
148061
|
+
hookScriptsInstalled,
|
|
148062
|
+
settingsRegistered,
|
|
148063
|
+
codexHooksRegistered
|
|
148064
|
+
};
|
|
148065
|
+
};
|
|
148066
|
+
var statusLabel = (result) => {
|
|
148067
|
+
switch (result.status) {
|
|
148068
|
+
case "installed":
|
|
148069
|
+
return "plugin installed";
|
|
148070
|
+
case "skipped_unavailable":
|
|
148071
|
+
return "skipped unavailable";
|
|
148072
|
+
case "failed":
|
|
148073
|
+
return "failed";
|
|
148074
|
+
case "would_install":
|
|
148075
|
+
return "would install";
|
|
148076
|
+
}
|
|
148077
|
+
};
|
|
148078
|
+
var printRunnerModelNote = () => {
|
|
148079
|
+
console.log(
|
|
148080
|
+
` ${color.dim("Agent sessions use the auto-updated managed runner at ~/.zero/runtime/bin/zero.")}`
|
|
148081
|
+
);
|
|
148082
|
+
console.log(
|
|
148083
|
+
` ${color.dim("The global npm `zero` is the bootstrap and manual CLI; it does not replace the managed runner.")}`
|
|
148084
|
+
);
|
|
148085
|
+
};
|
|
147737
148086
|
var runInit = async (appContext, options = {}) => {
|
|
147738
148087
|
const verbose = options.verbose ?? false;
|
|
148088
|
+
const dryRun = options.dryRun ?? false;
|
|
148089
|
+
const fallbackAllowed = options.fallback ?? true;
|
|
148090
|
+
const selection = parseAgentValues(options.agent);
|
|
148091
|
+
const requestedAgents = selection.requestedAgents;
|
|
148092
|
+
let currentStep = "plugins";
|
|
147739
148093
|
appContext.services.analyticsService.capture("init_started", {});
|
|
147740
|
-
let currentStep = "fetch";
|
|
147741
148094
|
try {
|
|
147742
148095
|
console.log("");
|
|
147743
|
-
console.log(` ${color.boldCyan("
|
|
148096
|
+
console.log(` ${color.boldCyan("Initializing Zero")}`);
|
|
147744
148097
|
console.log("");
|
|
147745
148098
|
console.log(color.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
147746
148099
|
console.log("");
|
|
147747
|
-
|
|
147748
|
-
|
|
147749
|
-
const [
|
|
147750
|
-
|
|
147751
|
-
|
|
147752
|
-
|
|
147753
|
-
|
|
147754
|
-
|
|
147755
|
-
|
|
147756
|
-
} catch {
|
|
147757
|
-
throw new Error(`${webBase}/hooks.json is not valid JSON`);
|
|
147758
|
-
}
|
|
147759
|
-
if (!hooksJson?.hooks || typeof hooksJson.hooks !== "object") {
|
|
147760
|
-
throw new Error(`${webBase}/hooks.json has no "hooks" object`);
|
|
147761
|
-
}
|
|
147762
|
-
if (verbose) {
|
|
147763
|
-
stepInfo(`fetched ${webBase}/SKILL.md and ${webBase}/hooks.json`);
|
|
148100
|
+
console.log(` Requested agents: ${requestedAgents.join(", ")}`);
|
|
148101
|
+
if (dryRun) stepInfo("dry run: no plugin commands or file writes will run");
|
|
148102
|
+
const detectedAgents = selection.kind === "standalone" ? [] : selection.pluginAgents.filter(
|
|
148103
|
+
(agent) => isCommandCallable(HARNESS_SPECS[agent].executable)
|
|
148104
|
+
);
|
|
148105
|
+
if (selection.kind === "default") {
|
|
148106
|
+
console.log(
|
|
148107
|
+
` Detected callable harnesses: ${detectedAgents.length > 0 ? detectedAgents.join(", ") : "none"}`
|
|
148108
|
+
);
|
|
147764
148109
|
}
|
|
147765
|
-
|
|
147766
|
-
const
|
|
147767
|
-
|
|
147768
|
-
|
|
147769
|
-
|
|
147770
|
-
|
|
147771
|
-
|
|
147772
|
-
|
|
147773
|
-
|
|
147774
|
-
|
|
148110
|
+
console.log("");
|
|
148111
|
+
const pluginResults = [];
|
|
148112
|
+
if (selection.kind !== "standalone") {
|
|
148113
|
+
for (const agent of selection.pluginAgents) {
|
|
148114
|
+
const spec = HARNESS_SPECS[agent];
|
|
148115
|
+
if (!detectedAgents.includes(agent)) {
|
|
148116
|
+
const result2 = {
|
|
148117
|
+
agent,
|
|
148118
|
+
displayName: spec.displayName,
|
|
148119
|
+
status: "skipped_unavailable",
|
|
148120
|
+
detail: `\`${spec.executable}\` is not callable in this shell`
|
|
148121
|
+
};
|
|
148122
|
+
pluginResults.push(result2);
|
|
148123
|
+
stepSkip(
|
|
148124
|
+
`${spec.displayName}: ${statusLabel(result2)}`,
|
|
148125
|
+
result2.detail
|
|
148126
|
+
);
|
|
148127
|
+
if (selection.kind === "specific") {
|
|
148128
|
+
printManualInstructions(spec);
|
|
148129
|
+
}
|
|
148130
|
+
continue;
|
|
148131
|
+
}
|
|
148132
|
+
const result = installHarnessPlugin(spec, { dryRun, verbose });
|
|
148133
|
+
pluginResults.push(result);
|
|
148134
|
+
if (result.status === "installed") {
|
|
148135
|
+
stepSuccess(
|
|
148136
|
+
`${spec.displayName}: ${statusLabel(result)}`,
|
|
148137
|
+
result.detail
|
|
148138
|
+
);
|
|
148139
|
+
} else if (result.status === "would_install") {
|
|
148140
|
+
stepSkip(
|
|
148141
|
+
`${spec.displayName}: ${statusLabel(result)}`,
|
|
148142
|
+
result.detail
|
|
148143
|
+
);
|
|
148144
|
+
} else {
|
|
148145
|
+
stepWarn(
|
|
148146
|
+
`${spec.displayName}: ${statusLabel(result)}`,
|
|
148147
|
+
result.detail
|
|
148148
|
+
);
|
|
148149
|
+
}
|
|
148150
|
+
}
|
|
147775
148151
|
}
|
|
147776
|
-
|
|
147777
|
-
|
|
147778
|
-
const hookScriptsInstalled = await installHookScripts(
|
|
147779
|
-
home,
|
|
147780
|
-
hooksJson,
|
|
147781
|
-
webBase,
|
|
147782
|
-
verbose
|
|
148152
|
+
const pluginSucceeded = pluginResults.some(
|
|
148153
|
+
(result) => result.status === "installed" || result.status === "would_install"
|
|
147783
148154
|
);
|
|
147784
|
-
|
|
147785
|
-
|
|
147786
|
-
|
|
147787
|
-
|
|
147788
|
-
|
|
147789
|
-
|
|
147790
|
-
|
|
147791
|
-
|
|
147792
|
-
|
|
148155
|
+
let standaloneFallbackReason;
|
|
148156
|
+
let standaloneFallbackUsed = false;
|
|
148157
|
+
let standaloneResult = {
|
|
148158
|
+
skillsInstalled: [],
|
|
148159
|
+
hookScriptsInstalled: [],
|
|
148160
|
+
settingsRegistered: false,
|
|
148161
|
+
codexHooksRegistered: false
|
|
148162
|
+
};
|
|
148163
|
+
if (selection.kind === "standalone" || !pluginSucceeded) {
|
|
148164
|
+
standaloneFallbackReason = fallbackReason(
|
|
148165
|
+
selection,
|
|
148166
|
+
detectedAgents,
|
|
148167
|
+
pluginResults
|
|
148168
|
+
);
|
|
148169
|
+
if (!fallbackAllowed && selection.kind !== "standalone") {
|
|
148170
|
+
throw new Error(
|
|
148171
|
+
`No Zero plugin install succeeded and --no-fallback was set (${standaloneFallbackReason}).`
|
|
148172
|
+
);
|
|
148173
|
+
}
|
|
148174
|
+
standaloneFallbackUsed = !dryRun;
|
|
148175
|
+
sectionDivider();
|
|
148176
|
+
const fallbackVerb = dryRun ? "would be used" : "used";
|
|
148177
|
+
console.log(
|
|
148178
|
+
` Standalone fallback ${fallbackVerb}: ${standaloneFallbackReason}.`
|
|
148179
|
+
);
|
|
148180
|
+
if (dryRun) {
|
|
148181
|
+
stepInfo("would install/update ~/.claude/skills/zero");
|
|
148182
|
+
stepInfo("would install/update ~/.agents/skills/zero");
|
|
148183
|
+
stepInfo(
|
|
148184
|
+
"would register current standalone hooks in ~/.claude/settings.json and ~/.codex/hooks.json"
|
|
148185
|
+
);
|
|
148186
|
+
} else {
|
|
148187
|
+
standaloneResult = await runStandaloneInit(appContext, {
|
|
148188
|
+
verbose,
|
|
148189
|
+
skillsDir: options.skillsDir,
|
|
148190
|
+
onStep: (step) => {
|
|
148191
|
+
currentStep = step;
|
|
148192
|
+
}
|
|
148193
|
+
});
|
|
148194
|
+
}
|
|
148195
|
+
} else {
|
|
148196
|
+
sectionDivider();
|
|
148197
|
+
console.log(
|
|
148198
|
+
" Standalone fallback not used: at least one harness plugin install succeeded."
|
|
148199
|
+
);
|
|
147793
148200
|
}
|
|
147794
148201
|
currentStep = "complete";
|
|
147795
148202
|
appContext.services.analyticsService.capture("init_completed", {
|
|
147796
148203
|
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147797
|
-
|
|
148204
|
+
requested_agents: requestedAgents,
|
|
147798
148205
|
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147799
|
-
|
|
148206
|
+
detected_harnesses: detectedAgents,
|
|
147800
148207
|
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147801
|
-
|
|
148208
|
+
plugin_installs: pluginResults.map((result) => ({
|
|
148209
|
+
agent: result.agent,
|
|
148210
|
+
status: result.status
|
|
148211
|
+
})),
|
|
148212
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148213
|
+
standalone_fallback_used: standaloneFallbackUsed,
|
|
148214
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148215
|
+
standalone_fallback_reason: standaloneFallbackReason,
|
|
148216
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148217
|
+
dry_run: dryRun,
|
|
148218
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148219
|
+
skills_installed: standaloneResult.skillsInstalled,
|
|
148220
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148221
|
+
skills_installed_count: standaloneResult.skillsInstalled.length,
|
|
148222
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148223
|
+
hook_scripts_installed: standaloneResult.hookScriptsInstalled,
|
|
148224
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148225
|
+
settings_registered: standaloneResult.settingsRegistered,
|
|
147802
148226
|
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147803
|
-
|
|
148227
|
+
codex_hooks_registered: standaloneResult.codexHooksRegistered
|
|
147804
148228
|
});
|
|
147805
148229
|
sectionDivider();
|
|
147806
|
-
console.log(` ${color.boldGreen("Zero
|
|
148230
|
+
console.log(` ${color.boldGreen("Zero init complete.")}`);
|
|
147807
148231
|
console.log(
|
|
147808
148232
|
` ${color.dim("Next: sign in with `zero auth login` \u2014 it prints a URL to approve in your browser.")}`
|
|
147809
148233
|
);
|
|
148234
|
+
printRunnerModelNote();
|
|
147810
148235
|
console.log("");
|
|
147811
|
-
return {
|
|
148236
|
+
return {
|
|
148237
|
+
...standaloneResult,
|
|
148238
|
+
requestedAgents,
|
|
148239
|
+
detectedAgents,
|
|
148240
|
+
pluginResults,
|
|
148241
|
+
standaloneFallbackUsed,
|
|
148242
|
+
standaloneFallbackReason,
|
|
148243
|
+
dryRun
|
|
148244
|
+
};
|
|
147812
148245
|
} catch (err) {
|
|
147813
148246
|
appContext.services.analyticsService.capture("init_failed", {
|
|
147814
148247
|
step: currentStep,
|
|
@@ -147818,7 +148251,18 @@ var runInit = async (appContext, options = {}) => {
|
|
|
147818
148251
|
}
|
|
147819
148252
|
};
|
|
147820
148253
|
var initCommand = (appContext) => new Command("init").description(
|
|
147821
|
-
"Install the Zero
|
|
148254
|
+
"Install the Zero plugin for supported agents, with a standalone skill/hook fallback"
|
|
148255
|
+
).option(
|
|
148256
|
+
"--agent <agent>",
|
|
148257
|
+
"Agent target: codex, claude, gemini, openclaw, or standalone. Repeat or comma-separate values. Omit to target every supported agent.",
|
|
148258
|
+
collectAgentOption,
|
|
148259
|
+
[]
|
|
148260
|
+
).option(
|
|
148261
|
+
"--no-fallback",
|
|
148262
|
+
"Do not install standalone skills/hooks if plugin install does not succeed"
|
|
148263
|
+
).option(
|
|
148264
|
+
"--dry-run",
|
|
148265
|
+
"Show what would be installed without running commands or writing files"
|
|
147822
148266
|
).option(
|
|
147823
148267
|
"-v, --verbose",
|
|
147824
148268
|
"Explain why each install step was taken or skipped"
|
|
@@ -148166,11 +148610,12 @@ var formatDetail = (r2) => {
|
|
|
148166
148610
|
}
|
|
148167
148611
|
return lines.join("\n");
|
|
148168
148612
|
};
|
|
148169
|
-
var runsDetailCommand = (appContext) => new Command("detail").description("Show full metadata for a single run").argument("<runId>", "Run ID (run_\u2026)").option("--json", "Output raw JSON to stdout").action(async (runId,
|
|
148613
|
+
var runsDetailCommand = (appContext) => new Command("detail").description("Show full metadata for a single run").argument("<runId>", "Run ID (run_\u2026)").option("--json", "Output raw JSON to stdout").action(async (runId, _opts, cmd) => {
|
|
148614
|
+
const { json: json3 } = cmd.opts();
|
|
148170
148615
|
try {
|
|
148171
148616
|
const { client } = appContext.services;
|
|
148172
148617
|
const run = await client.runs.get(runId);
|
|
148173
|
-
if (
|
|
148618
|
+
if (json3) {
|
|
148174
148619
|
console.log(JSON.stringify(run, null, 2));
|
|
148175
148620
|
return;
|
|
148176
148621
|
}
|
|
@@ -148434,6 +148879,8 @@ var HOOK_FILES = [
|
|
|
148434
148879
|
"ensure-runner.sh"
|
|
148435
148880
|
];
|
|
148436
148881
|
var ZERO_SANDBOX_DOMAIN2 = "*.zero.xyz";
|
|
148882
|
+
var CLAUDE_SETTINGS_PATH2 = ".claude/settings.json";
|
|
148883
|
+
var CODEX_HOOKS_PATH2 = ".codex/hooks.json";
|
|
148437
148884
|
var LEGACY_SKILL_NAMES = ["zero"];
|
|
148438
148885
|
var removeSkills = (home, verbose = false) => {
|
|
148439
148886
|
const skillNames = LEGACY_SKILL_NAMES;
|
|
@@ -148459,30 +148906,17 @@ var removeSkills = (home, verbose = false) => {
|
|
|
148459
148906
|
return removed;
|
|
148460
148907
|
};
|
|
148461
148908
|
var removeHooks = (home, verbose = false) => {
|
|
148462
|
-
|
|
148463
|
-
|
|
148464
|
-
|
|
148465
|
-
|
|
148466
|
-
|
|
148467
|
-
|
|
148468
|
-
|
|
148469
|
-
|
|
148470
|
-
|
|
148471
|
-
|
|
148472
|
-
|
|
148473
|
-
}
|
|
148474
|
-
}
|
|
148475
|
-
if (settings) {
|
|
148476
|
-
settingsChanged = stripZeroFromSettings(settings, verbose);
|
|
148477
|
-
if (settingsChanged) {
|
|
148478
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
148479
|
-
`);
|
|
148480
|
-
if (verbose) stepInfo(`rewrote ${settingsPath} without Zero entries`);
|
|
148481
|
-
} else if (verbose) {
|
|
148482
|
-
stepInfo(`no Zero entries found in ${settingsPath}`);
|
|
148483
|
-
}
|
|
148484
|
-
}
|
|
148485
|
-
}
|
|
148909
|
+
const claudeSettingsChanged = stripZeroFromJsonFile(
|
|
148910
|
+
join(home, CLAUDE_SETTINGS_PATH2),
|
|
148911
|
+
verbose,
|
|
148912
|
+
true
|
|
148913
|
+
);
|
|
148914
|
+
const codexHooksChanged = stripZeroFromJsonFile(
|
|
148915
|
+
join(home, CODEX_HOOKS_PATH2),
|
|
148916
|
+
verbose,
|
|
148917
|
+
false
|
|
148918
|
+
);
|
|
148919
|
+
const settingsChanged = claudeSettingsChanged || codexHooksChanged;
|
|
148486
148920
|
let scriptsRemoved = 0;
|
|
148487
148921
|
const zeroHooksDir = join(home, ".zero", "hooks");
|
|
148488
148922
|
if (existsSync(zeroHooksDir)) {
|
|
@@ -148502,7 +148936,29 @@ var removeHooks = (home, verbose = false) => {
|
|
|
148502
148936
|
}
|
|
148503
148937
|
return { settingsChanged, scriptsRemoved };
|
|
148504
148938
|
};
|
|
148505
|
-
var
|
|
148939
|
+
var stripZeroFromJsonFile = (settingsPath, verbose, removeSandboxAllowlist) => {
|
|
148940
|
+
const result = updateJsonConfigFile(
|
|
148941
|
+
settingsPath,
|
|
148942
|
+
(settings) => stripZeroFromSettings(settings, verbose, removeSandboxAllowlist)
|
|
148943
|
+
);
|
|
148944
|
+
if (result.status === "missing") {
|
|
148945
|
+
if (verbose) stepInfo(`${settingsPath} not found \u2014 no settings to clean`);
|
|
148946
|
+
return false;
|
|
148947
|
+
}
|
|
148948
|
+
if (result.status === "unparseable") {
|
|
148949
|
+
if (verbose) {
|
|
148950
|
+
stepInfo(`${settingsPath} was unparseable JSON \u2014 leaving it untouched`);
|
|
148951
|
+
}
|
|
148952
|
+
return false;
|
|
148953
|
+
}
|
|
148954
|
+
if (result.status === "updated") {
|
|
148955
|
+
if (verbose) stepInfo(`rewrote ${settingsPath} without Zero entries`);
|
|
148956
|
+
return true;
|
|
148957
|
+
}
|
|
148958
|
+
if (verbose) stepInfo(`no Zero entries found in ${settingsPath}`);
|
|
148959
|
+
return false;
|
|
148960
|
+
};
|
|
148961
|
+
var stripZeroFromSettings = (settings, verbose, removeSandboxAllowlist) => {
|
|
148506
148962
|
let changed = false;
|
|
148507
148963
|
const hooks = settings.hooks && typeof settings.hooks === "object" ? settings.hooks : null;
|
|
148508
148964
|
if (hooks) {
|
|
@@ -148515,24 +148971,26 @@ var stripZeroFromSettings = (settings, verbose) => {
|
|
|
148515
148971
|
}
|
|
148516
148972
|
if (Object.keys(hooks).length === 0) delete settings.hooks;
|
|
148517
148973
|
}
|
|
148518
|
-
|
|
148519
|
-
|
|
148520
|
-
|
|
148521
|
-
|
|
148522
|
-
|
|
148523
|
-
|
|
148524
|
-
|
|
148525
|
-
|
|
148526
|
-
|
|
148527
|
-
|
|
148528
|
-
|
|
148529
|
-
|
|
148530
|
-
|
|
148531
|
-
|
|
148532
|
-
|
|
148533
|
-
|
|
148534
|
-
|
|
148535
|
-
|
|
148974
|
+
if (removeSandboxAllowlist) {
|
|
148975
|
+
const sandbox = settings.sandbox && typeof settings.sandbox === "object" ? settings.sandbox : null;
|
|
148976
|
+
const network = sandbox?.network && typeof sandbox.network === "object" ? sandbox.network : null;
|
|
148977
|
+
if (network && Array.isArray(network.allowedDomains)) {
|
|
148978
|
+
const domains = network.allowedDomains;
|
|
148979
|
+
const next = domains.filter((d3) => d3 !== ZERO_SANDBOX_DOMAIN2);
|
|
148980
|
+
if (next.length !== domains.length) {
|
|
148981
|
+
changed = true;
|
|
148982
|
+
if (verbose) {
|
|
148983
|
+
stepInfo(`sandbox.network.allowedDomains -= ${ZERO_SANDBOX_DOMAIN2}`);
|
|
148984
|
+
}
|
|
148985
|
+
if (next.length === 0) {
|
|
148986
|
+
delete network.allowedDomains;
|
|
148987
|
+
if (sandbox && Object.keys(network).length === 0)
|
|
148988
|
+
delete sandbox.network;
|
|
148989
|
+
if (sandbox && Object.keys(sandbox).length === 0)
|
|
148990
|
+
delete settings.sandbox;
|
|
148991
|
+
} else {
|
|
148992
|
+
network.allowedDomains = next;
|
|
148993
|
+
}
|
|
148536
148994
|
}
|
|
148537
148995
|
}
|
|
148538
148996
|
}
|