@vm0/cli 9.89.0 → 9.90.1

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/zero.js CHANGED
@@ -7,11 +7,13 @@ import {
7
7
  allowsCustomModel,
8
8
  configureGlobalProxyFromEnv,
9
9
  connectorTypeSchema,
10
+ createAgentSkill,
10
11
  createZeroAgent,
11
12
  createZeroComputerConnector,
12
13
  createZeroConnectorSession,
13
14
  createZeroRun,
14
15
  decodeZeroTokenPayload,
16
+ deleteAgentSkill,
15
17
  deleteZeroAgent,
16
18
  deleteZeroComputerConnector,
17
19
  deleteZeroConnector,
@@ -25,12 +27,15 @@ import {
25
27
  deployZeroSchedule,
26
28
  disableZeroSchedule,
27
29
  enableZeroSchedule,
30
+ findMatchingPermissions,
28
31
  getActiveOrg,
32
+ getAgentSkill,
29
33
  getApiUrl,
30
34
  getAskUserAnswer,
31
35
  getAuthMethodsForType,
32
36
  getBaseUrl,
33
37
  getConnectorDerivedNames,
38
+ getConnectorFirewall,
34
39
  getConnectorTypeForSecretName,
35
40
  getCustomModelPlaceholder,
36
41
  getDefaultAuthMethod,
@@ -55,9 +60,11 @@ import {
55
60
  hasRequiredScopes,
56
61
  inviteZeroOrgMember,
57
62
  isFeatureEnabled,
63
+ isFirewallConnectorType,
58
64
  isInteractive,
59
65
  isUUID,
60
66
  leaveZeroOrg,
67
+ listAgentSkills,
61
68
  listZeroAgents,
62
69
  listZeroConnectors,
63
70
  listZeroOrgModelProviders,
@@ -86,6 +93,7 @@ import {
86
93
  setZeroSecret,
87
94
  setZeroVariable,
88
95
  switchZeroOrg,
96
+ updateAgentSkill,
89
97
  updateZeroAgent,
90
98
  updateZeroAgentInstructions,
91
99
  updateZeroOrg,
@@ -93,10 +101,10 @@ import {
93
101
  updateZeroUserPreferences,
94
102
  upsertZeroOrgModelProvider,
95
103
  withErrorHandler
96
- } from "./chunk-AM6X5N5J.js";
104
+ } from "./chunk-RJS4OQ2I.js";
97
105
 
98
106
  // src/zero.ts
99
- import { Command as Command61 } from "commander";
107
+ import { Command as Command68 } from "commander";
100
108
 
101
109
  // src/commands/zero/org/index.ts
102
110
  import { Command as Command23 } from "commander";
@@ -1192,6 +1200,9 @@ Examples:
1192
1200
  const connectors = await getZeroAgentUserConnectors(agentId);
1193
1201
  if (connectors.length > 0)
1194
1202
  console.log(`Connectors: ${connectors.join(", ")}`);
1203
+ if (agent.customSkills?.length > 0) {
1204
+ console.log(`Skills: ${agent.customSkills.join(", ")}`);
1205
+ }
1195
1206
  if (agent.description)
1196
1207
  console.log(`Description: ${agent.description}`);
1197
1208
  if (agent.sound) console.log(`Sound: ${agent.sound}`);
@@ -1904,10 +1915,12 @@ var disconnectCommand = new Command33().name("disconnect").description("Disconne
1904
1915
  var zeroConnectorCommand = new Command34().name("connector").description("Check or connect third-party services (GitHub, Slack, etc.)").addCommand(listCommand6).addCommand(statusCommand2).addCommand(connectCommand).addCommand(disconnectCommand);
1905
1916
 
1906
1917
  // src/commands/zero/doctor/index.ts
1907
- import { Command as Command36 } from "commander";
1918
+ import { Command as Command37 } from "commander";
1908
1919
 
1909
1920
  // src/commands/zero/doctor/missing-token.ts
1910
1921
  import { Command as Command35 } from "commander";
1922
+
1923
+ // src/commands/zero/doctor/platform-url.ts
1911
1924
  function toPlatformUrl(apiUrl) {
1912
1925
  const parsed = new URL(apiUrl);
1913
1926
  const parts = parsed.hostname.split(".");
@@ -1921,6 +1934,12 @@ function toPlatformUrl(apiUrl) {
1921
1934
  parsed.hostname = parts.join(".");
1922
1935
  return parsed;
1923
1936
  }
1937
+ async function getPlatformOrigin() {
1938
+ const apiUrl = await getApiUrl();
1939
+ return toPlatformUrl(apiUrl).origin;
1940
+ }
1941
+
1942
+ // src/commands/zero/doctor/missing-token.ts
1924
1943
  var missingTokenCommand = new Command35().name("missing-token").description(
1925
1944
  "Diagnose a missing token and find the connector that provides it"
1926
1945
  ).argument("<token-name>", "The environment variable / token name to look up").addHelpText(
@@ -1956,37 +1975,99 @@ Notes:
1956
1975
  if (!isConnected) {
1957
1976
  const url = `${platformUrl.origin}/connectors`;
1958
1977
  console.log(
1959
- `The ${label} connector is not connected. Ask the user to connect it at: ${url}`
1978
+ `The ${label} connector is not connected. Ask the user to connect it at: [Connect ${label}](${url})`
1960
1979
  );
1961
1980
  } else if (!hasPermission) {
1962
1981
  const path = agentId ? `/team/${agentId}` : "/team";
1963
1982
  const url = `${platformUrl.origin}${path}?tab=authorization`;
1964
1983
  console.log(
1965
- `The ${label} connector is connected but not authorized for this agent. Ask the user to enable it at: ${url}`
1984
+ `The ${label} connector is connected but not authorized for this agent. Ask the user to enable it at: [Authorize ${label}](${url})`
1966
1985
  );
1967
1986
  } else {
1968
1987
  const url = `${platformUrl.origin}/connectors`;
1969
1988
  console.log(
1970
- `The ${label} connector is connected and authorized, but the token is still missing. Ask the user to check the connector status at: ${url}`
1989
+ `The ${label} connector is connected and authorized, but the token is still missing. Ask the user to check the connector status at: [Check ${label} status](${url})`
1971
1990
  );
1972
1991
  }
1973
1992
  })
1974
1993
  );
1975
1994
 
1995
+ // src/commands/zero/doctor/firewall-deny.ts
1996
+ import { Command as Command36, Option } from "commander";
1997
+ var firewallDenyCommand = new Command36().name("firewall-deny").description(
1998
+ "Diagnose a firewall denial and find the permission that covers it"
1999
+ ).argument("<firewall-ref>", "The firewall connector type (e.g. github)").addOption(
2000
+ new Option(
2001
+ "--method <method>",
2002
+ "The denied HTTP method"
2003
+ ).makeOptionMandatory()
2004
+ ).addOption(
2005
+ new Option("--path <path>", "The denied path").makeOptionMandatory()
2006
+ ).addHelpText(
2007
+ "after",
2008
+ `
2009
+ Examples:
2010
+ zero doctor firewall-deny github --method GET --path /repos/owner/repo/pulls
2011
+ zero doctor firewall-deny slack --method POST --path /chat.postMessage
2012
+
2013
+ Notes:
2014
+ - Identifies which named permission covers a denied request
2015
+ - Outputs a platform URL for the user to allow the permission`
2016
+ ).action(
2017
+ withErrorHandler(
2018
+ async (firewallRef, opts) => {
2019
+ if (!isFirewallConnectorType(firewallRef)) {
2020
+ throw new Error(`Unknown firewall connector type: ${firewallRef}`);
2021
+ }
2022
+ const { label } = CONNECTOR_TYPES[firewallRef];
2023
+ const config = getConnectorFirewall(firewallRef);
2024
+ const permissions = findMatchingPermissions(
2025
+ opts.method,
2026
+ opts.path,
2027
+ config
2028
+ );
2029
+ const platformOrigin = await getPlatformOrigin();
2030
+ const agentId = process.env.ZERO_AGENT_ID;
2031
+ const urlParams = new URLSearchParams({
2032
+ ref: firewallRef,
2033
+ method: opts.method,
2034
+ path: opts.path
2035
+ });
2036
+ if (permissions.length > 0) {
2037
+ urlParams.set("permission", permissions[0]);
2038
+ }
2039
+ const pagePath = agentId ? `/firewall-allow/${agentId}` : "/firewall-allow";
2040
+ const url = `${platformOrigin}${pagePath}?${urlParams.toString()}`;
2041
+ console.log(
2042
+ `The ${label} firewall blocked ${opts.method} ${opts.path}.`
2043
+ );
2044
+ if (permissions.length > 0) {
2045
+ console.log(`This is covered by the "${permissions[0]}" permission.`);
2046
+ } else {
2047
+ console.log("No named permission was found covering this request.");
2048
+ }
2049
+ console.log(
2050
+ `Ask the user to allow it at: [Allow ${label} access](${url})`
2051
+ );
2052
+ }
2053
+ )
2054
+ );
2055
+
1976
2056
  // src/commands/zero/doctor/index.ts
1977
- var zeroDoctorCommand = new Command36().name("doctor").description("Diagnose runtime issues (missing tokens, connectors)").addCommand(missingTokenCommand).addHelpText(
2057
+ var zeroDoctorCommand = new Command37().name("doctor").description("Diagnose runtime issues (missing tokens, firewall denials)").addCommand(missingTokenCommand).addCommand(firewallDenyCommand).addHelpText(
1978
2058
  "after",
1979
2059
  `
1980
2060
  Examples:
1981
2061
  Missing an API key? zero doctor missing-token GITHUB_TOKEN
2062
+ Firewall blocked? zero doctor firewall-deny github --method GET --path /repos/owner/repo
1982
2063
 
1983
2064
  Notes:
1984
- - Use this when your task fails due to a missing environment variable
1985
- - The doctor will identify which connector provides the token and give the user a link to connect it`
2065
+ - Use this when your task fails due to a missing environment variable or firewall denial
2066
+ - The doctor will identify the issue and give the user a link to resolve it`
1986
2067
  );
1987
2068
 
1988
2069
  // src/commands/zero/preference/index.ts
1989
- import { Command as Command37 } from "commander";
2070
+ import { Command as Command38 } from "commander";
1990
2071
  import chalk31 from "chalk";
1991
2072
  function detectTimezone2() {
1992
2073
  return Intl.DateTimeFormat().resolvedOptions().timeZone;
@@ -2043,7 +2124,7 @@ System timezone detected: ${detectedTz}`));
2043
2124
  }
2044
2125
  }
2045
2126
  }
2046
- var zeroPreferenceCommand = new Command37().name("preference").description("View or update user preferences (timezone, notifications)").option("--timezone <timezone>", "IANA timezone (e.g., America/New_York)").action(
2127
+ var zeroPreferenceCommand = new Command38().name("preference").description("View or update user preferences (timezone, notifications)").option("--timezone <timezone>", "IANA timezone (e.g., America/New_York)").action(
2047
2128
  withErrorHandler(async (opts) => {
2048
2129
  const updates = buildUpdates(opts);
2049
2130
  if (updates) {
@@ -2068,7 +2149,7 @@ var zeroPreferenceCommand = new Command37().name("preference").description("View
2068
2149
  );
2069
2150
 
2070
2151
  // src/commands/zero/run/run.ts
2071
- import { Command as Command38 } from "commander";
2152
+ import { Command as Command39 } from "commander";
2072
2153
 
2073
2154
  // src/commands/zero/run/shared.ts
2074
2155
  import chalk32 from "chalk";
@@ -2147,7 +2228,7 @@ function showZeroNextSteps(result) {
2147
2228
  }
2148
2229
 
2149
2230
  // src/commands/zero/run/run.ts
2150
- var mainRunCommand = new Command38().name("run").description("Delegate a task to a teammate agent").argument("<agent-id>", "Agent UUID (from `zero agent list`)").argument("<prompt>", "Task prompt for the agent").option(
2231
+ var mainRunCommand = new Command39().name("run").description("Delegate a task to a teammate agent").argument("<agent-id>", "Agent UUID (from `zero agent list`)").argument("<prompt>", "Task prompt for the agent").option(
2151
2232
  "--append-system-prompt <text>",
2152
2233
  "Append text to the agent's system prompt"
2153
2234
  ).option(
@@ -2199,8 +2280,8 @@ Notes:
2199
2280
  );
2200
2281
 
2201
2282
  // src/commands/zero/run/continue.ts
2202
- import { Command as Command39 } from "commander";
2203
- var continueCommand = new Command39().name("continue").description("Continue a previous delegation from a session").argument("<session-id>", "Session ID from a previous run").argument("<prompt>", "Follow-up prompt for the agent").option(
2283
+ import { Command as Command40 } from "commander";
2284
+ var continueCommand = new Command40().name("continue").description("Continue a previous delegation from a session").argument("<session-id>", "Session ID from a previous run").argument("<prompt>", "Follow-up prompt for the agent").option(
2204
2285
  "--append-system-prompt <text>",
2205
2286
  "Append text to the agent's system prompt"
2206
2287
  ).option(
@@ -2261,10 +2342,10 @@ Examples:
2261
2342
  var zeroRunCommand = mainRunCommand;
2262
2343
 
2263
2344
  // src/commands/zero/schedule/index.ts
2264
- import { Command as Command46 } from "commander";
2345
+ import { Command as Command47 } from "commander";
2265
2346
 
2266
2347
  // src/commands/zero/schedule/setup.ts
2267
- import { Command as Command40 } from "commander";
2348
+ import { Command as Command41 } from "commander";
2268
2349
  import chalk33 from "chalk";
2269
2350
  var FREQUENCY_CHOICES = [
2270
2351
  { title: "Daily", value: "daily", description: "Run every day" },
@@ -2710,7 +2791,7 @@ async function handleScheduleEnabling(params) {
2710
2791
  showEnableHint(agentName);
2711
2792
  }
2712
2793
  }
2713
- var setupCommand2 = new Command40().name("setup").description("Create or edit a schedule for a zero agent").argument("<agent-id>", "Agent ID").option("-n, --name <schedule-name>", 'Schedule name (default: "default")').option("-f, --frequency <type>", "Frequency: daily|weekly|monthly|once|loop").option("-t, --time <HH:MM>", "Time to run (24-hour format)").option("-d, --day <day>", "Day of week (mon-sun) or day of month (1-31)").option("-i, --interval <seconds>", "Interval in seconds for loop mode").option("-z, --timezone <tz>", "IANA timezone").option("-p, --prompt <text>", "Prompt to run").option("-e, --enable", "Enable schedule immediately after creation").option("--notify-email", "Enable email notifications (default: false)").option("--no-notify-email", "Disable email notifications").option("--notify-slack", "Enable Slack notifications (default: false)").option("--no-notify-slack", "Disable Slack notifications").option(
2794
+ var setupCommand2 = new Command41().name("setup").description("Create or edit a schedule for a zero agent").argument("<agent-id>", "Agent ID").option("-n, --name <schedule-name>", 'Schedule name (default: "default")').option("-f, --frequency <type>", "Frequency: daily|weekly|monthly|once|loop").option("-t, --time <HH:MM>", "Time to run (24-hour format)").option("-d, --day <day>", "Day of week (mon-sun) or day of month (1-31)").option("-i, --interval <seconds>", "Interval in seconds for loop mode").option("-z, --timezone <tz>", "IANA timezone").option("-p, --prompt <text>", "Prompt to run").option("-e, --enable", "Enable schedule immediately after creation").option("--notify-email", "Enable email notifications (default: false)").option("--no-notify-email", "Disable email notifications").option("--notify-slack", "Enable Slack notifications (default: false)").option("--no-notify-slack", "Disable Slack notifications").option(
2714
2795
  "--notify-slack-channel-id <channel-id>",
2715
2796
  "Slack channel ID for notifications (default: DM)"
2716
2797
  ).addHelpText(
@@ -2812,9 +2893,9 @@ Notes:
2812
2893
  );
2813
2894
 
2814
2895
  // src/commands/zero/schedule/list.ts
2815
- import { Command as Command41 } from "commander";
2896
+ import { Command as Command42 } from "commander";
2816
2897
  import chalk34 from "chalk";
2817
- var listCommand7 = new Command41().name("list").alias("ls").description("List all zero schedules").addHelpText(
2898
+ var listCommand7 = new Command42().name("list").alias("ls").description("List all zero schedules").addHelpText(
2818
2899
  "after",
2819
2900
  `
2820
2901
  Examples:
@@ -2868,7 +2949,7 @@ Examples:
2868
2949
  );
2869
2950
 
2870
2951
  // src/commands/zero/schedule/status.ts
2871
- import { Command as Command42 } from "commander";
2952
+ import { Command as Command43 } from "commander";
2872
2953
  import chalk35 from "chalk";
2873
2954
  function formatDateTimeStyled(dateStr) {
2874
2955
  if (!dateStr) return chalk35.dim("-");
@@ -2923,7 +3004,7 @@ function printTimeSchedule(schedule) {
2923
3004
  console.log(`${"Failures:".padEnd(16)}${failureText}`);
2924
3005
  }
2925
3006
  }
2926
- var statusCommand3 = new Command42().name("status").description("Show detailed status of a zero schedule").argument("<agent-id>", "Agent ID").option(
3007
+ var statusCommand3 = new Command43().name("status").description("Show detailed status of a zero schedule").argument("<agent-id>", "Agent ID").option(
2927
3008
  "-n, --name <schedule-name>",
2928
3009
  "Schedule name (required when agent has multiple schedules)"
2929
3010
  ).addHelpText(
@@ -2948,9 +3029,9 @@ Examples:
2948
3029
  );
2949
3030
 
2950
3031
  // src/commands/zero/schedule/delete.ts
2951
- import { Command as Command43 } from "commander";
3032
+ import { Command as Command44 } from "commander";
2952
3033
  import chalk36 from "chalk";
2953
- var deleteCommand3 = new Command43().name("delete").alias("rm").description("Delete a zero schedule").argument("<agent-id>", "Agent ID").option(
3034
+ var deleteCommand3 = new Command44().name("delete").alias("rm").description("Delete a zero schedule").argument("<agent-id>", "Agent ID").option(
2954
3035
  "-n, --name <schedule-name>",
2955
3036
  "Schedule name (required when agent has multiple schedules)"
2956
3037
  ).option("-y, --yes", "Skip confirmation prompt").addHelpText(
@@ -2992,9 +3073,9 @@ Notes:
2992
3073
  );
2993
3074
 
2994
3075
  // src/commands/zero/schedule/enable.ts
2995
- import { Command as Command44 } from "commander";
3076
+ import { Command as Command45 } from "commander";
2996
3077
  import chalk37 from "chalk";
2997
- var enableCommand = new Command44().name("enable").description("Enable a zero schedule").argument("<agent-id>", "Agent ID").option(
3078
+ var enableCommand = new Command45().name("enable").description("Enable a zero schedule").argument("<agent-id>", "Agent ID").option(
2998
3079
  "-n, --name <schedule-name>",
2999
3080
  "Schedule name (required when agent has multiple schedules)"
3000
3081
  ).addHelpText(
@@ -3018,9 +3099,9 @@ Examples:
3018
3099
  );
3019
3100
 
3020
3101
  // src/commands/zero/schedule/disable.ts
3021
- import { Command as Command45 } from "commander";
3102
+ import { Command as Command46 } from "commander";
3022
3103
  import chalk38 from "chalk";
3023
- var disableCommand = new Command45().name("disable").description("Disable a zero schedule").argument("<agent-id>", "Agent ID").option(
3104
+ var disableCommand = new Command46().name("disable").description("Disable a zero schedule").argument("<agent-id>", "Agent ID").option(
3024
3105
  "-n, --name <schedule-name>",
3025
3106
  "Schedule name (required when agent has multiple schedules)"
3026
3107
  ).addHelpText(
@@ -3044,7 +3125,7 @@ Examples:
3044
3125
  );
3045
3126
 
3046
3127
  // src/commands/zero/schedule/index.ts
3047
- var zeroScheduleCommand = new Command46().name("schedule").description("Create or manage recurring scheduled tasks").addCommand(setupCommand2).addCommand(listCommand7).addCommand(statusCommand3).addCommand(deleteCommand3).addCommand(enableCommand).addCommand(disableCommand).addHelpText(
3128
+ var zeroScheduleCommand = new Command47().name("schedule").description("Create or manage recurring scheduled tasks").addCommand(setupCommand2).addCommand(listCommand7).addCommand(statusCommand3).addCommand(deleteCommand3).addCommand(enableCommand).addCommand(disableCommand).addHelpText(
3048
3129
  "after",
3049
3130
  `
3050
3131
  Examples:
@@ -3057,12 +3138,12 @@ Examples:
3057
3138
  );
3058
3139
 
3059
3140
  // src/commands/zero/secret/index.ts
3060
- import { Command as Command50 } from "commander";
3141
+ import { Command as Command51 } from "commander";
3061
3142
 
3062
3143
  // src/commands/zero/secret/list.ts
3063
- import { Command as Command47 } from "commander";
3144
+ import { Command as Command48 } from "commander";
3064
3145
  import chalk39 from "chalk";
3065
- var listCommand8 = new Command47().name("list").alias("ls").description("List all secrets").action(
3146
+ var listCommand8 = new Command48().name("list").alias("ls").description("List all secrets").action(
3066
3147
  withErrorHandler(async () => {
3067
3148
  const result = await listZeroSecrets();
3068
3149
  if (result.secrets.length === 0) {
@@ -3115,9 +3196,9 @@ var listCommand8 = new Command47().name("list").alias("ls").description("List al
3115
3196
  );
3116
3197
 
3117
3198
  // src/commands/zero/secret/set.ts
3118
- import { Command as Command48 } from "commander";
3199
+ import { Command as Command49 } from "commander";
3119
3200
  import chalk40 from "chalk";
3120
- var setCommand4 = new Command48().name("set").description("Create or update a secret").argument("<name>", "Secret name (uppercase, e.g., MY_API_KEY)").option(
3201
+ var setCommand4 = new Command49().name("set").description("Create or update a secret").argument("<name>", "Secret name (uppercase, e.g., MY_API_KEY)").option(
3121
3202
  "-b, --body <value>",
3122
3203
  "Secret value (required in non-interactive mode)"
3123
3204
  ).option("-d, --description <description>", "Optional description").action(
@@ -3163,9 +3244,9 @@ var setCommand4 = new Command48().name("set").description("Create or update a se
3163
3244
  );
3164
3245
 
3165
3246
  // src/commands/zero/secret/delete.ts
3166
- import { Command as Command49 } from "commander";
3247
+ import { Command as Command50 } from "commander";
3167
3248
  import chalk41 from "chalk";
3168
- var deleteCommand4 = new Command49().name("delete").description("Delete a secret").argument("<name>", "Secret name to delete").option("-y, --yes", "Skip confirmation prompt").action(
3249
+ var deleteCommand4 = new Command50().name("delete").description("Delete a secret").argument("<name>", "Secret name to delete").option("-y, --yes", "Skip confirmation prompt").action(
3169
3250
  withErrorHandler(async (name, options) => {
3170
3251
  if (!options.yes) {
3171
3252
  if (!isInteractive()) {
@@ -3186,19 +3267,19 @@ var deleteCommand4 = new Command49().name("delete").description("Delete a secret
3186
3267
  );
3187
3268
 
3188
3269
  // src/commands/zero/secret/index.ts
3189
- var zeroSecretCommand = new Command50().name("secret").description("Read or write secrets (API keys, tokens)").addCommand(listCommand8).addCommand(setCommand4).addCommand(deleteCommand4);
3270
+ var zeroSecretCommand = new Command51().name("secret").description("Read or write secrets (API keys, tokens)").addCommand(listCommand8).addCommand(setCommand4).addCommand(deleteCommand4);
3190
3271
 
3191
3272
  // src/commands/zero/slack/index.ts
3192
- import { Command as Command53 } from "commander";
3273
+ import { Command as Command54 } from "commander";
3193
3274
 
3194
3275
  // src/commands/zero/slack/message/index.ts
3195
- import { Command as Command52 } from "commander";
3276
+ import { Command as Command53 } from "commander";
3196
3277
 
3197
3278
  // src/commands/zero/slack/message/send.ts
3198
3279
  import { readFileSync as readFileSync3 } from "fs";
3199
- import { Command as Command51 } from "commander";
3280
+ import { Command as Command52 } from "commander";
3200
3281
  import chalk42 from "chalk";
3201
- var sendCommand = new Command51().name("send").description("Send a message to a Slack channel").requiredOption("-c, --channel <id>", "Channel ID").option("-t, --text <message>", "Message text").option("--thread <ts>", "Thread timestamp for replies").option("--blocks <json>", "Block Kit JSON string").addHelpText(
3282
+ var sendCommand = new Command52().name("send").description("Send a message to a Slack channel").requiredOption("-c, --channel <id>", "Channel ID").option("-t, --text <message>", "Message text").option("--thread <ts>", "Thread timestamp for replies").option("--blocks <json>", "Block Kit JSON string").addHelpText(
3202
3283
  "after",
3203
3284
  `
3204
3285
  Examples:
@@ -3248,7 +3329,7 @@ Notes:
3248
3329
  );
3249
3330
 
3250
3331
  // src/commands/zero/slack/message/index.ts
3251
- var zeroSlackMessageCommand = new Command52().name("message").description("Manage Slack messages").addCommand(sendCommand).addHelpText(
3332
+ var zeroSlackMessageCommand = new Command53().name("message").description("Manage Slack messages").addCommand(sendCommand).addHelpText(
3252
3333
  "after",
3253
3334
  `
3254
3335
  Examples:
@@ -3256,7 +3337,7 @@ Examples:
3256
3337
  );
3257
3338
 
3258
3339
  // src/commands/zero/slack/index.ts
3259
- var zeroSlackCommand = new Command53().name("slack").description("Send messages to Slack channels as the bot").addCommand(zeroSlackMessageCommand).addHelpText(
3340
+ var zeroSlackCommand = new Command54().name("slack").description("Send messages to Slack channels as the bot").addCommand(zeroSlackMessageCommand).addHelpText(
3260
3341
  "after",
3261
3342
  `
3262
3343
  Examples:
@@ -3265,10 +3346,10 @@ Examples:
3265
3346
  );
3266
3347
 
3267
3348
  // src/commands/zero/variable/index.ts
3268
- import { Command as Command57 } from "commander";
3349
+ import { Command as Command58 } from "commander";
3269
3350
 
3270
3351
  // src/commands/zero/variable/list.ts
3271
- import { Command as Command54 } from "commander";
3352
+ import { Command as Command55 } from "commander";
3272
3353
  import chalk43 from "chalk";
3273
3354
  function truncateValue2(value, maxLength = 60) {
3274
3355
  if (value.length <= maxLength) {
@@ -3276,7 +3357,7 @@ function truncateValue2(value, maxLength = 60) {
3276
3357
  }
3277
3358
  return value.slice(0, maxLength - 15) + "... [truncated]";
3278
3359
  }
3279
- var listCommand9 = new Command54().name("list").alias("ls").description("List all variables").action(
3360
+ var listCommand9 = new Command55().name("list").alias("ls").description("List all variables").action(
3280
3361
  withErrorHandler(async () => {
3281
3362
  const result = await listZeroVariables();
3282
3363
  if (result.variables.length === 0) {
@@ -3304,9 +3385,9 @@ var listCommand9 = new Command54().name("list").alias("ls").description("List al
3304
3385
  );
3305
3386
 
3306
3387
  // src/commands/zero/variable/set.ts
3307
- import { Command as Command55 } from "commander";
3388
+ import { Command as Command56 } from "commander";
3308
3389
  import chalk44 from "chalk";
3309
- var setCommand5 = new Command55().name("set").description("Create or update a variable").argument("<name>", "Variable name (uppercase, e.g., MY_VAR)").argument("<value>", "Variable value").option("-d, --description <description>", "Optional description").action(
3390
+ var setCommand5 = new Command56().name("set").description("Create or update a variable").argument("<name>", "Variable name (uppercase, e.g., MY_VAR)").argument("<value>", "Variable value").option("-d, --description <description>", "Optional description").action(
3310
3391
  withErrorHandler(
3311
3392
  async (name, value, options) => {
3312
3393
  let variable;
@@ -3332,9 +3413,9 @@ var setCommand5 = new Command55().name("set").description("Create or update a va
3332
3413
  );
3333
3414
 
3334
3415
  // src/commands/zero/variable/delete.ts
3335
- import { Command as Command56 } from "commander";
3416
+ import { Command as Command57 } from "commander";
3336
3417
  import chalk45 from "chalk";
3337
- var deleteCommand5 = new Command56().name("delete").description("Delete a variable").argument("<name>", "Variable name to delete").option("-y, --yes", "Skip confirmation prompt").action(
3418
+ var deleteCommand5 = new Command57().name("delete").description("Delete a variable").argument("<name>", "Variable name to delete").option("-y, --yes", "Skip confirmation prompt").action(
3338
3419
  withErrorHandler(async (name, options) => {
3339
3420
  if (!options.yes) {
3340
3421
  if (!isInteractive()) {
@@ -3355,10 +3436,10 @@ var deleteCommand5 = new Command56().name("delete").description("Delete a variab
3355
3436
  );
3356
3437
 
3357
3438
  // src/commands/zero/variable/index.ts
3358
- var zeroVariableCommand = new Command57().name("variable").description("Read or write non-sensitive configuration values").addCommand(listCommand9).addCommand(setCommand5).addCommand(deleteCommand5);
3439
+ var zeroVariableCommand = new Command58().name("variable").description("Read or write non-sensitive configuration values").addCommand(listCommand9).addCommand(setCommand5).addCommand(deleteCommand5);
3359
3440
 
3360
3441
  // src/commands/zero/whoami.ts
3361
- import { Command as Command58 } from "commander";
3442
+ import { Command as Command59 } from "commander";
3362
3443
  import chalk46 from "chalk";
3363
3444
  function isInsideSandbox() {
3364
3445
  return !!process.env.ZERO_AGENT_ID;
@@ -3395,7 +3476,7 @@ async function showLocalInfo() {
3395
3476
  console.log(` Active: ${activeOrg}`);
3396
3477
  }
3397
3478
  }
3398
- var zeroWhoamiCommand = new Command58().name("whoami").description("Show agent identity, run ID, and capabilities").addHelpText(
3479
+ var zeroWhoamiCommand = new Command59().name("whoami").description("Show agent identity, run ID, and capabilities").addHelpText(
3399
3480
  "after",
3400
3481
  `
3401
3482
  Examples:
@@ -3415,10 +3496,10 @@ Notes:
3415
3496
  );
3416
3497
 
3417
3498
  // src/commands/zero/ask-user/index.ts
3418
- import { Command as Command60 } from "commander";
3499
+ import { Command as Command61 } from "commander";
3419
3500
 
3420
3501
  // src/commands/zero/ask-user/question.ts
3421
- import { Command as Command59 } from "commander";
3502
+ import { Command as Command60 } from "commander";
3422
3503
  import chalk47 from "chalk";
3423
3504
  function collectOption(value, previous) {
3424
3505
  const list = previous ?? [];
@@ -3430,7 +3511,7 @@ function collectDesc(value, previous) {
3430
3511
  list.push(value);
3431
3512
  return list;
3432
3513
  }
3433
- var questionCommand = new Command59().name("question").description("Ask the user a question and wait for the answer").argument("<question>", "The question to ask").option("--header <text>", "Short label displayed as chip/tag (max 12 chars)").option("--option <label>", "Add a choice option (repeatable)", collectOption).option(
3514
+ var questionCommand = new Command60().name("question").description("Ask the user a question and wait for the answer").argument("<question>", "The question to ask").option("--header <text>", "Short label displayed as chip/tag (max 12 chars)").option("--option <label>", "Add a choice option (repeatable)", collectOption).option(
3434
3515
  "--desc <text>",
3435
3516
  "Description for the preceding --option",
3436
3517
  collectDesc
@@ -3511,7 +3592,7 @@ Notes:
3511
3592
  );
3512
3593
 
3513
3594
  // src/commands/zero/ask-user/index.ts
3514
- var zeroAskUserCommand = new Command60().name("ask-user").description("Ask the user a question and wait for the answer").addCommand(questionCommand).addHelpText(
3595
+ var zeroAskUserCommand = new Command61().name("ask-user").description("Ask the user a question and wait for the answer").addCommand(questionCommand).addHelpText(
3515
3596
  "after",
3516
3597
  `
3517
3598
  Examples:
@@ -3522,9 +3603,234 @@ Notes:
3522
3603
  - The user's answer is printed to stdout for your consumption`
3523
3604
  );
3524
3605
 
3606
+ // src/commands/zero/skill/index.ts
3607
+ import { Command as Command67 } from "commander";
3608
+
3609
+ // src/commands/zero/skill/create.ts
3610
+ import { Command as Command62 } from "commander";
3611
+ import { readFileSync as readFileSync4, existsSync } from "fs";
3612
+ import { join as join2 } from "path";
3613
+ import chalk48 from "chalk";
3614
+ var createCommand2 = new Command62().name("create").description("Create a custom skill for a zero agent").argument("<name>", "Skill name (lowercase alphanumeric with hyphens)").requiredOption("--dir <path>", "Path to directory containing SKILL.md").option("--agent <id>", "Agent ID (defaults to $ZERO_AGENT_ID)").option("--display-name <name>", "Skill display name").option("--description <text>", "Skill description").addHelpText(
3615
+ "after",
3616
+ `
3617
+ Examples:
3618
+ zero skill create my-skill --dir ./skills/my-skill/
3619
+ zero skill create my-skill --dir ./skills/my-skill/ --agent <id>
3620
+ zero skill create my-skill --dir ./skills/my-skill/ --display-name "My Skill" --description "Does things"
3621
+
3622
+ Notes:
3623
+ - The directory must contain a SKILL.md file
3624
+ - Agent ID defaults to $ZERO_AGENT_ID if --agent is not provided`
3625
+ ).action(
3626
+ withErrorHandler(
3627
+ async (name, options) => {
3628
+ const agentId = options.agent ?? process.env.ZERO_AGENT_ID;
3629
+ if (!agentId) {
3630
+ throw new Error(
3631
+ "Agent ID required: use --agent <id> or set $ZERO_AGENT_ID"
3632
+ );
3633
+ }
3634
+ const skillMdPath = join2(options.dir, "SKILL.md");
3635
+ if (!existsSync(skillMdPath)) {
3636
+ throw new Error(`SKILL.md not found in ${options.dir}`);
3637
+ }
3638
+ const content = readFileSync4(skillMdPath, "utf-8");
3639
+ const skill = await createAgentSkill(agentId, {
3640
+ name,
3641
+ content,
3642
+ displayName: options.displayName,
3643
+ description: options.description
3644
+ });
3645
+ console.log(chalk48.green(`\u2713 Skill "${skill.name}" created`));
3646
+ console.log(` Name: ${skill.name}`);
3647
+ console.log(` Agent: ${agentId}`);
3648
+ if (skill.displayName) {
3649
+ console.log(` Display Name: ${skill.displayName}`);
3650
+ }
3651
+ if (skill.description) {
3652
+ console.log(` Description: ${skill.description}`);
3653
+ }
3654
+ }
3655
+ )
3656
+ );
3657
+
3658
+ // src/commands/zero/skill/edit.ts
3659
+ import { Command as Command63 } from "commander";
3660
+ import { readFileSync as readFileSync5, existsSync as existsSync2 } from "fs";
3661
+ import { join as join3 } from "path";
3662
+ import chalk49 from "chalk";
3663
+ var editCommand2 = new Command63().name("edit").description("Update a custom skill's content").argument("<name>", "Skill name").requiredOption(
3664
+ "--dir <path>",
3665
+ "Path to directory containing updated SKILL.md"
3666
+ ).option("--agent <id>", "Agent ID (defaults to $ZERO_AGENT_ID)").addHelpText(
3667
+ "after",
3668
+ `
3669
+ Examples:
3670
+ zero skill edit my-skill --dir ./skills/my-skill/
3671
+ zero skill edit my-skill --dir ./skills/my-skill/ --agent <id>`
3672
+ ).action(
3673
+ withErrorHandler(
3674
+ async (name, options) => {
3675
+ const agentId = options.agent ?? process.env.ZERO_AGENT_ID;
3676
+ if (!agentId) {
3677
+ throw new Error(
3678
+ "Agent ID required: use --agent <id> or set $ZERO_AGENT_ID"
3679
+ );
3680
+ }
3681
+ const skillMdPath = join3(options.dir, "SKILL.md");
3682
+ if (!existsSync2(skillMdPath)) {
3683
+ throw new Error(`SKILL.md not found in ${options.dir}`);
3684
+ }
3685
+ const content = readFileSync5(skillMdPath, "utf-8");
3686
+ await updateAgentSkill(agentId, name, { content });
3687
+ console.log(chalk49.green(`\u2713 Skill "${name}" updated`));
3688
+ }
3689
+ )
3690
+ );
3691
+
3692
+ // src/commands/zero/skill/view.ts
3693
+ import { Command as Command64 } from "commander";
3694
+ import chalk50 from "chalk";
3695
+ var viewCommand2 = new Command64().name("view").description("View a custom skill").argument("<name>", "Skill name").option("--agent <id>", "Agent ID (defaults to $ZERO_AGENT_ID)").addHelpText(
3696
+ "after",
3697
+ `
3698
+ Examples:
3699
+ zero skill view my-skill
3700
+ zero skill view my-skill --agent <id>`
3701
+ ).action(
3702
+ withErrorHandler(async (name, options) => {
3703
+ const agentId = options.agent ?? process.env.ZERO_AGENT_ID;
3704
+ if (!agentId) {
3705
+ throw new Error(
3706
+ "Agent ID required: use --agent <id> or set $ZERO_AGENT_ID"
3707
+ );
3708
+ }
3709
+ const skill = await getAgentSkill(agentId, name);
3710
+ console.log(chalk50.bold(skill.name));
3711
+ if (skill.displayName) console.log(chalk50.dim(skill.displayName));
3712
+ console.log();
3713
+ console.log(`Name: ${skill.name}`);
3714
+ if (skill.displayName) console.log(`Display Name: ${skill.displayName}`);
3715
+ if (skill.description) console.log(`Description: ${skill.description}`);
3716
+ console.log();
3717
+ if (skill.content) {
3718
+ console.log(chalk50.dim("\u2500\u2500 SKILL.md \u2500\u2500"));
3719
+ console.log(skill.content);
3720
+ } else {
3721
+ console.log(chalk50.dim("No content"));
3722
+ }
3723
+ })
3724
+ );
3725
+
3726
+ // src/commands/zero/skill/list.ts
3727
+ import { Command as Command65 } from "commander";
3728
+ import chalk51 from "chalk";
3729
+ var listCommand10 = new Command65().name("list").alias("ls").description("List custom skills for a zero agent").option("--agent <id>", "Agent ID (defaults to $ZERO_AGENT_ID)").addHelpText(
3730
+ "after",
3731
+ `
3732
+ Examples:
3733
+ zero skill list
3734
+ zero skill list --agent <id>`
3735
+ ).action(
3736
+ withErrorHandler(async (options) => {
3737
+ const agentId = options.agent ?? process.env.ZERO_AGENT_ID;
3738
+ if (!agentId) {
3739
+ throw new Error(
3740
+ "Agent ID required: use --agent <id> or set $ZERO_AGENT_ID"
3741
+ );
3742
+ }
3743
+ const skills = await listAgentSkills(agentId);
3744
+ if (skills.length === 0) {
3745
+ console.log(chalk51.dim("No custom skills found"));
3746
+ console.log(
3747
+ chalk51.dim(" Create one with: zero skill create <name> --dir <path>")
3748
+ );
3749
+ return;
3750
+ }
3751
+ const nameWidth = Math.max(4, ...skills.map((s) => s.name.length));
3752
+ const displayWidth = Math.max(
3753
+ 12,
3754
+ ...skills.map((s) => (s.displayName ?? "").length)
3755
+ );
3756
+ const header = [
3757
+ "NAME".padEnd(nameWidth),
3758
+ "DISPLAY NAME".padEnd(displayWidth),
3759
+ "DESCRIPTION"
3760
+ ].join(" ");
3761
+ console.log(chalk51.dim(header));
3762
+ for (const skill of skills) {
3763
+ const row = [
3764
+ skill.name.padEnd(nameWidth),
3765
+ (skill.displayName ?? "-").padEnd(displayWidth),
3766
+ skill.description ?? "-"
3767
+ ].join(" ");
3768
+ console.log(row);
3769
+ }
3770
+ })
3771
+ );
3772
+
3773
+ // src/commands/zero/skill/delete.ts
3774
+ import { Command as Command66 } from "commander";
3775
+ import chalk52 from "chalk";
3776
+ var deleteCommand6 = new Command66().name("delete").alias("rm").description("Delete a custom skill").argument("<name>", "Skill name").option("--agent <id>", "Agent ID (defaults to $ZERO_AGENT_ID)").option("-y, --yes", "Skip confirmation prompt").addHelpText(
3777
+ "after",
3778
+ `
3779
+ Examples:
3780
+ zero skill delete my-skill
3781
+ zero skill delete my-skill -y
3782
+ zero skill delete my-skill --agent <id>
3783
+
3784
+ Notes:
3785
+ - Use -y to skip confirmation in non-interactive mode`
3786
+ ).action(
3787
+ withErrorHandler(
3788
+ async (name, options) => {
3789
+ const agentId = options.agent ?? process.env.ZERO_AGENT_ID;
3790
+ if (!agentId) {
3791
+ throw new Error(
3792
+ "Agent ID required: use --agent <id> or set $ZERO_AGENT_ID"
3793
+ );
3794
+ }
3795
+ await getAgentSkill(agentId, name);
3796
+ if (!options.yes) {
3797
+ if (!isInteractive()) {
3798
+ throw new Error("--yes flag is required in non-interactive mode");
3799
+ }
3800
+ const confirmed = await promptConfirm(
3801
+ `Delete skill '${name}'?`,
3802
+ false
3803
+ );
3804
+ if (!confirmed) {
3805
+ console.log(chalk52.dim("Cancelled"));
3806
+ return;
3807
+ }
3808
+ }
3809
+ await deleteAgentSkill(agentId, name);
3810
+ console.log(chalk52.green(`\u2713 Skill "${name}" deleted`));
3811
+ }
3812
+ )
3813
+ );
3814
+
3815
+ // src/commands/zero/skill/index.ts
3816
+ var zeroSkillCommand = new Command67("skill").description("Manage custom skills for zero agents").addCommand(createCommand2).addCommand(editCommand2).addCommand(viewCommand2).addCommand(listCommand10).addCommand(deleteCommand6).addHelpText(
3817
+ "after",
3818
+ `
3819
+ Examples:
3820
+ Create from directory: zero skill create my-skill --dir ./skills/my-skill/
3821
+ List agent's skills: zero skill list --agent <id>
3822
+ View skill content: zero skill view my-skill
3823
+ Update skill content: zero skill edit my-skill --dir ./skills/my-skill/
3824
+ Delete a skill: zero skill delete my-skill -y
3825
+
3826
+ Notes:
3827
+ Agent ID comes from --agent flag or $ZERO_AGENT_ID environment variable`
3828
+ );
3829
+
3525
3830
  // src/zero.ts
3526
3831
  var COMMAND_CAPABILITY_MAP = {
3527
3832
  agent: "agent:read",
3833
+ skill: "agent:read",
3528
3834
  run: "agent-run:write",
3529
3835
  schedule: "schedule:read",
3530
3836
  doctor: null,
@@ -3544,7 +3850,8 @@ var DEFAULT_COMMANDS = [
3544
3850
  zeroSlackCommand,
3545
3851
  zeroVariableCommand,
3546
3852
  zeroWhoamiCommand,
3547
- zeroAskUserCommand
3853
+ zeroAskUserCommand,
3854
+ zeroSkillCommand
3548
3855
  ];
3549
3856
  function shouldHideCommand(name, payload) {
3550
3857
  if (!payload) return false;
@@ -3560,10 +3867,10 @@ function registerZeroCommands(prog, commands) {
3560
3867
  prog.addCommand(cmd, hidden ? { hidden: true } : {});
3561
3868
  }
3562
3869
  }
3563
- var program = new Command61();
3870
+ var program = new Command68();
3564
3871
  program.name("zero").description(
3565
3872
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
3566
- ).version("9.89.0").addHelpText(
3873
+ ).version("9.90.1").addHelpText(
3567
3874
  "after",
3568
3875
  `
3569
3876
  Examples: