@mifune/agro 0.16.0 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +6 -6
  2. package/dist/agro.js +76 -24
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @mifune/agro
2
2
 
3
- The **AGRO CLI** (`agro`) — create an [AGRO](https://agro.mifune.dev)
3
+ The **AGRO CLI** (`agro`) — create an [AGRO](https://github.com/mifunedev/agro)
4
4
  Docker sandbox for coding agents and drive its lifecycle from the command line.
5
5
 
6
6
  AGRO is a portable harness for running coding agents (Claude Code, Codex, Pi,
@@ -26,17 +26,17 @@ Or run it once without installing:
26
26
  npx @mifune/agro sandbox install docker
27
27
  ```
28
28
 
29
- Prefer a `curl | bash` bootstrap (also installs Node when missing)? `get-agro.sh`
29
+ Prefer a `curl | bash` bootstrap (also installs Node when missing)? `install.sh`
30
30
  installs the prebuilt `agro` artifact from the latest GitHub release — it never
31
31
  clones or builds on your machine:
32
32
 
33
33
  ```bash
34
- curl -fsSL https://agro.mifune.dev/get-agro.sh | bash
34
+ curl -fsSL https://github.com/mifunedev/agro/releases/latest/download/install.sh | bash
35
35
  ```
36
36
 
37
37
  ### Requirements
38
38
 
39
- - **Node.js ≥ 20** (22 recommended) on your `PATH`. Unlike the `get-agro.sh` bootstrap,
39
+ - **Node.js ≥ 20** (22 recommended) on your `PATH`. Unlike the `install.sh` bootstrap,
40
40
  npm will not install Node for you.
41
41
  - **Docker** and **git** for the sandbox lifecycle commands (`agro sandbox install`, `agro shell`).
42
42
 
@@ -147,8 +147,8 @@ The CLI writes no scaffold. It creates no `AGENTS.md`, no provider configuration
147
147
 
148
148
  ## Documentation
149
149
 
150
- - **Docs:** https://agro.mifune.dev
151
- - **Installation guide:** https://agro.mifune.dev/docs/installation
150
+ - **Docs:** https://github.com/mifunedev/agro/tree/main/docs
151
+ - **Installation guide:** https://github.com/mifunedev/agro/blob/main/docs/installation.md
152
152
  - **Source & issues:** https://github.com/mifunedev/agro
153
153
 
154
154
  ## License
package/dist/agro.js CHANGED
@@ -531,7 +531,7 @@ function refuseUnsupported(installation, bin) {
531
531
  return new Error(`${at} \u2014 rebuild from the checkout: npm --prefix .agro/cli run build`);
532
532
  default:
533
533
  return new Error(
534
- `unknown installation (${reason ?? target}) \u2014 install with npm install -g ${PACKAGE} or get-agro.sh`
534
+ `unknown installation (${reason ?? target}) \u2014 install with npm install -g ${PACKAGE} or install.sh`
535
535
  );
536
536
  }
537
537
  }
@@ -611,6 +611,15 @@ ${detail}`);
611
611
  function copyFile(deps, from, to) {
612
612
  deps.writeFile(to, deps.readFile(from), deps.stat(from).mode & 511);
613
613
  }
614
+ var ABSOLUTE_NODE_SHEBANG = /^#!\/\S*\/node$/;
615
+ function withPinnedShebang(current, artifact) {
616
+ const currentEnd = current.indexOf(10);
617
+ const artifactEnd = artifact.indexOf(10);
618
+ if (currentEnd < 0 || artifactEnd < 0) return artifact;
619
+ const firstLine = current.subarray(0, currentEnd);
620
+ if (!ABSOLUTE_NODE_SHEBANG.test(firstLine.toString("utf8"))) return artifact;
621
+ return Buffer.concat([firstLine, artifact.subarray(artifactEnd)]);
622
+ }
614
623
  function removeQuietly(deps, path4, io) {
615
624
  try {
616
625
  deps.unlink(path4);
@@ -629,7 +638,7 @@ async function upgradeStandalone(installation, opts, deps, io) {
629
638
  deps.access(dir, constants.W_OK);
630
639
  } catch {
631
640
  throw new Error(
632
- `${dir} is not writable; re-run as the user who owns ${target}, or reinstall into a writable directory with get-agro.sh`
641
+ `${dir} is not writable; re-run as the user who owns ${target}, or reinstall into a writable directory with install.sh`
633
642
  );
634
643
  }
635
644
  let artifact;
@@ -645,11 +654,11 @@ async function upgradeStandalone(installation, opts, deps, io) {
645
654
  let prevPresent = false;
646
655
  let replaced = false;
647
656
  try {
648
- deps.writeFile(tmp, artifact, 493);
649
- tmpPresent = true;
650
657
  if (artifact.subarray(0, 2).toString("utf8") !== "#!") {
651
658
  throw new Error(`invalid artifact from ${url}: no #! shebang`);
652
659
  }
660
+ deps.writeFile(tmp, withPinnedShebang(deps.readFile(target), artifact), 493);
661
+ tmpPresent = true;
653
662
  const probe = deps.runNode(tmp, ["--version"]);
654
663
  const available = versionOf(probe);
655
664
  if (parseSemver(available) === void 0) {
@@ -1403,10 +1412,10 @@ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readdirSync as read
1403
1412
  import { dirname as dirname4, join as join4, resolve as resolve5, sep as sep2 } from "node:path";
1404
1413
 
1405
1414
  // agro-asset:/home/runner/work/agro/agro/.devcontainer/docker-compose.yml
1406
- var docker_compose_default = 'name: ${SANDBOX_NAME:-agro}\n\nservices:\n sandbox:\n image: ${AGRO_SANDBOX_IMAGE:-sandbox-${SANDBOX_NAME:-agro}}\n pull_policy: ${AGRO_PULL_POLICY:-missing}\n container_name: ${SANDBOX_NAME:-agro}\n build:\n context: ${AGRO_REPO_DIR:-..}\n dockerfile: .devcontainer/Dockerfile\n volumes:\n - ${AGRO_HOME_MOUNT:-workspace}:/home/sandbox\n - ${AGRO_REPO_DIR:-..}:/home/sandbox/harness\n extra_hosts:\n - "host.docker.internal:host-gateway"\n environment:\n - SANDBOX_NAME=${SANDBOX_NAME:-agro}\n - SANDBOX_PASSWORD=${SANDBOX_PASSWORD:-test1234}\n - TZ=${TZ:-America/Los_Angeles}\n - CLAUDE_DANGEROUSLY_SKIP_PERMISSIONS=true\n - CC_SAFETY_NET_STRICT=1\n - CC_SAFETY_NET_WORKTREE=1\n - GIT_USER_NAME=${GIT_USER_NAME:-}\n - GIT_USER_EMAIL=${GIT_USER_EMAIL:-}\n - GH_TOKEN=${GH_TOKEN:-}\n stdin_open: true\n tty: true\n cgroup: private\n cap_add:\n - SYS_ADMIN\n security_opt:\n - apparmor=unconfined\n tmpfs:\n - /run\n - /run/lock\n - /sys/fs\n healthcheck:\n test: ["CMD", "bash", "-c", "exec bash /home/sandbox/harness/.agro/scripts/sandbox-healthcheck.sh"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 600s\n restart: unless-stopped\n\nvolumes:\n workspace:\n';
1415
+ var docker_compose_default = 'name: ${SANDBOX_NAME:-agro}\n\nservices:\n sandbox:\n image: ${AGRO_SANDBOX_IMAGE:-sandbox-${SANDBOX_NAME:-agro}}\n pull_policy: ${AGRO_PULL_POLICY:-missing}\n container_name: ${SANDBOX_NAME:-agro}\n build:\n context: ${AGRO_REPO_DIR:-..}\n dockerfile: .devcontainer/Dockerfile\n volumes:\n - ${AGRO_HOME_MOUNT:-workspace}:/home/sandbox\n - ${AGRO_REPO_DIR:-..}:/home/sandbox/harness\n extra_hosts:\n - "host.docker.internal:host-gateway"\n environment:\n - SANDBOX_NAME=${SANDBOX_NAME:-agro}\n - SANDBOX_PASSWORD=${SANDBOX_PASSWORD:-test1234}\n - TZ=${TZ:-America/Los_Angeles}\n - CLAUDE_DANGEROUSLY_SKIP_PERMISSIONS=true\n - CC_SAFETY_NET_STRICT=1\n - CC_SAFETY_NET_WORKTREE=1\n - GIT_USER_NAME=${GIT_USER_NAME:-}\n - GIT_USER_EMAIL=${GIT_USER_EMAIL:-}\n - GH_TOKEN=${GH_TOKEN:-}\n - TYPESAFE_API_KEY=${TYPESAFE_API_KEY:-}\n stdin_open: true\n tty: true\n cgroup: private\n cap_add:\n - SYS_ADMIN\n security_opt:\n - apparmor=unconfined\n tmpfs:\n - /run\n - /run/lock\n - /sys/fs\n healthcheck:\n test: ["CMD", "bash", "-c", "exec bash /home/sandbox/harness/.agro/scripts/sandbox-healthcheck.sh"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 600s\n restart: unless-stopped\n\nvolumes:\n workspace:\n';
1407
1416
 
1408
1417
  // agro-asset:/home/runner/work/agro/agro/.devcontainer/docker-compose.image-only.yml
1409
- var docker_compose_image_only_default = 'name: ${SANDBOX_NAME:-agro}\n\nservices:\n sandbox:\n image: ${AGRO_SANDBOX_IMAGE:-ghcr.io/mifunedev/agro:latest}\n pull_policy: ${AGRO_PULL_POLICY:-always}\n container_name: ${SANDBOX_NAME:-agro}\n volumes:\n - ${AGRO_HOME_MOUNT:-workspace}:/home/sandbox\n extra_hosts:\n - "host.docker.internal:host-gateway"\n environment:\n - SANDBOX_NAME=${SANDBOX_NAME:-agro}\n - SANDBOX_PASSWORD=${SANDBOX_PASSWORD:-test1234}\n - TZ=${TZ:-America/Los_Angeles}\n - CLAUDE_DANGEROUSLY_SKIP_PERMISSIONS=true\n - CC_SAFETY_NET_STRICT=1\n - CC_SAFETY_NET_WORKTREE=1\n - GIT_USER_NAME=${GIT_USER_NAME:-}\n - GIT_USER_EMAIL=${GIT_USER_EMAIL:-}\n - GH_TOKEN=${GH_TOKEN:-}\n stdin_open: true\n tty: true\n cgroup: private\n cap_add:\n - SYS_ADMIN\n security_opt:\n - apparmor=unconfined\n tmpfs:\n - /run\n - /run/lock\n - /sys/fs\n healthcheck:\n test: ["CMD", "bash", "-c", "exec bash /home/sandbox/harness/.agro/scripts/sandbox-healthcheck.sh"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 600s\n restart: unless-stopped\n\nvolumes:\n workspace:\n';
1418
+ var docker_compose_image_only_default = 'name: ${SANDBOX_NAME:-agro}\n\nservices:\n sandbox:\n image: ${AGRO_SANDBOX_IMAGE:-ghcr.io/mifunedev/agro:latest}\n pull_policy: ${AGRO_PULL_POLICY:-always}\n container_name: ${SANDBOX_NAME:-agro}\n volumes:\n - ${AGRO_HOME_MOUNT:-workspace}:/home/sandbox\n extra_hosts:\n - "host.docker.internal:host-gateway"\n environment:\n - SANDBOX_NAME=${SANDBOX_NAME:-agro}\n - SANDBOX_PASSWORD=${SANDBOX_PASSWORD:-test1234}\n - TZ=${TZ:-America/Los_Angeles}\n - CLAUDE_DANGEROUSLY_SKIP_PERMISSIONS=true\n - CC_SAFETY_NET_STRICT=1\n - CC_SAFETY_NET_WORKTREE=1\n - GIT_USER_NAME=${GIT_USER_NAME:-}\n - GIT_USER_EMAIL=${GIT_USER_EMAIL:-}\n - GH_TOKEN=${GH_TOKEN:-}\n - TYPESAFE_API_KEY=${TYPESAFE_API_KEY:-}\n stdin_open: true\n tty: true\n cgroup: private\n cap_add:\n - SYS_ADMIN\n security_opt:\n - apparmor=unconfined\n tmpfs:\n - /run\n - /run/lock\n - /sys/fs\n healthcheck:\n test: ["CMD", "bash", "-c", "exec bash /home/sandbox/harness/.agro/scripts/sandbox-healthcheck.sh"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 600s\n restart: unless-stopped\n\nvolumes:\n workspace:\n';
1410
1419
 
1411
1420
  // agro-asset:/home/runner/work/agro/agro/.devcontainer/docker-compose.ssh.yml
1412
1421
  var docker_compose_ssh_default = 'services:\n sandbox:\n ports:\n - "127.0.0.1:${SANDBOX_SSH_PORT:-2222}:22"\n';
@@ -1484,8 +1493,7 @@ if [ -f "$REPO_DIR/harness.yaml" ] && [ -f "$MIGRATOR" ]; then
1484
1493
  sh "$MIGRATOR" "$REPO_DIR" >&2 || true
1485
1494
  fi
1486
1495
 
1487
- ENV_FILE="$REPO_DIR/.env"
1488
- [ -f "$ENV_FILE" ] || ENV_FILE="$REPO_DIR/.devcontainer/.env"
1496
+ ENV_FILE="$(agro_env_file "$REPO_DIR")"
1489
1497
 
1490
1498
  compose_path() {
1491
1499
  case "$1" in
@@ -1632,6 +1640,14 @@ agro_config_file() {
1632
1640
  printf '%s\\n' "$1/$AGRO_CONFIG_FILE"
1633
1641
  }
1634
1642
 
1643
+ agro_env_file() {
1644
+ if [ -f "$1/.env" ]; then
1645
+ printf '%s\\n' "$1/.env"
1646
+ else
1647
+ printf '%s\\n' "$1/.devcontainer/.env"
1648
+ fi
1649
+ }
1650
+
1635
1651
  agro_env_value() {
1636
1652
  local key="AGRO_$1"
1637
1653
  printf '%s\\n' "\${!key:-}"
@@ -2222,7 +2238,7 @@ function resolveExecutionTarget(opts) {
2222
2238
  }
2223
2239
 
2224
2240
  // src/lib/version.ts
2225
- var AGRO_VERSION = true ? "0.16.0" : "0.0.0-dev";
2241
+ var AGRO_VERSION = true ? "0.16.2" : "0.0.0-dev";
2226
2242
  var OFFICIAL_IMAGE = "ghcr.io/mifunedev/agro";
2227
2243
  var RELEASE_VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[a-z][a-z0-9]*\.[0-9]+)?$/;
2228
2244
  function parseReleaseVersion(value) {
@@ -2852,6 +2868,7 @@ function sameRemote(url, owner, name) {
2852
2868
  }
2853
2869
 
2854
2870
  // src/commands/secret.ts
2871
+ import { spawnSync as spawnSync3 } from "node:child_process";
2855
2872
  import { existsSync as existsSync12 } from "node:fs";
2856
2873
  import { join as join7 } from "node:path";
2857
2874
 
@@ -2883,8 +2900,16 @@ function appendGitignoreLines(root, lines) {
2883
2900
  function secretsRoot(opts) {
2884
2901
  return opts.sandbox === void 0 ? resolveProjectRoot(opts.cwd) : resolveSandboxRoot({ name: opts.sandbox });
2885
2902
  }
2903
+ function isGitIgnored(root, path4) {
2904
+ const result = spawnSync3("git", ["check-ignore", "-q", "--no-index", path4], {
2905
+ cwd: root,
2906
+ stdio: "ignore"
2907
+ });
2908
+ return result.status === 0;
2909
+ }
2886
2910
  function ignoreSecretsFile(root) {
2887
2911
  if (!existsSync12(join7(root, ".git"))) return;
2912
+ if (isGitIgnored(root, ".env")) return;
2888
2913
  appendGitignoreLines(root, [".env"]);
2889
2914
  }
2890
2915
  function secretKeyList() {
@@ -3744,7 +3769,7 @@ var RUNTIME_CATALOG = Object.freeze([
3744
3769
  tier: "container",
3745
3770
  state: "active",
3746
3771
  provisionable: true,
3747
- docsPath: "docs/runtimes/docker.md"
3772
+ docsPath: "docs/runtimes/overview.md"
3748
3773
  }),
3749
3774
  Object.freeze({
3750
3775
  id: "microsandbox",
@@ -3752,7 +3777,7 @@ var RUNTIME_CATALOG = Object.freeze([
3752
3777
  tier: "microvm",
3753
3778
  state: "planned",
3754
3779
  provisionable: false,
3755
- notProvisionableReason: (bin) => `microsandbox is not a provisionable runtime yet; see docs/rfcs/rfc-runtime-support.md. Inside a sandbox run \`${bin} tool install microsandbox\`.`,
3780
+ notProvisionableReason: (bin) => `microsandbox is not a provisionable runtime yet; see https://github.com/mifunedev/agro/issues/592. Inside a sandbox run \`${bin} tool install microsandbox\`.`,
3756
3781
  docsPath: "docs/runtimes/microsandbox.md"
3757
3782
  })
3758
3783
  ]);
@@ -6351,11 +6376,11 @@ Remove ${entry.id} by hand: ${ROOT_TOOL_REMOVAL_DOCS}
6351
6376
  }
6352
6377
 
6353
6378
  // src/lib/remote.ts
6354
- import { spawnSync as spawnSync3 } from "node:child_process";
6379
+ import { spawnSync as spawnSync4 } from "node:child_process";
6355
6380
  var DEFAULT_REPO_URL = "https://github.com/mifunedev/agro";
6356
6381
  var DEFAULT_CLONE_TIMEOUT_MS = 12e4;
6357
6382
  var spawnRunner2 = (cmd, args, opts) => {
6358
- const r = spawnSync3(cmd, args, {
6383
+ const r = spawnSync4(cmd, args, {
6359
6384
  env: opts.env,
6360
6385
  timeout: opts.timeoutMs,
6361
6386
  stdio: ["ignore", "ignore", "pipe"],
@@ -6413,6 +6438,35 @@ function fetchRemoteSource(opts) {
6413
6438
  return opts.destDir;
6414
6439
  }
6415
6440
 
6441
+ // src/command-table.ts
6442
+ var CONFIG_VERBS = ["show", "set", "repo"];
6443
+ var CONFIG_INTEGRATIONS = ["langfuse"];
6444
+ var SECRET_VERBS = ["set", "list"];
6445
+ var LANGFUSE_VERBS = ["apply", "status", "disable"];
6446
+ var SANDBOX_SUBCOMMANDS = ["install", "list", "upgrade"];
6447
+ var WORKSPACE_SUBCOMMANDS = ["create", "list"];
6448
+ var HARNESS_SUBCOMMANDS = ["list", "install", "status", "uninstall"];
6449
+ var TOOL_SUBCOMMANDS = ["list", "install", "status", "uninstall"];
6450
+ function isOneOf(values, value) {
6451
+ return value !== void 0 && values.includes(value);
6452
+ }
6453
+ var AGRO_COMMANDS = Object.freeze({
6454
+ config: [...CONFIG_VERBS, ...CONFIG_INTEGRATIONS],
6455
+ secret: SECRET_VERBS,
6456
+ langfuse: LANGFUSE_VERBS,
6457
+ update: null,
6458
+ "self-upgrade": null,
6459
+ vendor: null,
6460
+ sandbox: SANDBOX_SUBCOMMANDS,
6461
+ shell: null,
6462
+ compose: null,
6463
+ workspace: WORKSPACE_SUBCOMMANDS,
6464
+ harness: HARNESS_SUBCOMMANDS,
6465
+ tool: TOOL_SUBCOMMANDS,
6466
+ gateway: null,
6467
+ ...Object.fromEntries(composeVerbs().map((verb) => [verb, null]))
6468
+ });
6469
+
6416
6470
  // src/cli.ts
6417
6471
  var DEFAULT_SOURCE_CONTROL_DIR = resolve11(
6418
6472
  dirname10(fileURLToPath(import.meta.url)),
@@ -6549,7 +6603,7 @@ The upgrade follows whichever mechanism installed this executable:
6549
6603
  npm-managed realpath under node_modules/${AGRO_PRODUCT.packageName}/: reads the registry
6550
6604
  version with \`npm view\`, then runs
6551
6605
  \`npm install -g --prefix <owning prefix> ${AGRO_PRODUCT.packageName}@<version>\`.
6552
- standalone a plain file (get-agro.sh): downloads AGRO_JS_URL (default
6606
+ standalone a plain file (install.sh): downloads AGRO_JS_URL (default
6553
6607
  ${DEFAULT_ARTIFACT_URL})
6554
6608
  into the same directory, checks its shebang and \`--version\`,
6555
6609
  renames it over the executable, and keeps <path>.prev until the
@@ -6807,7 +6861,6 @@ function extractSandboxFlag(command, rest) {
6807
6861
  }
6808
6862
  return { ok: true, args: sandbox === void 0 ? { rest: kept } : { rest: kept, sandbox } };
6809
6863
  }
6810
- var LANGFUSE_VERBS = ["apply", "status", "disable"];
6811
6864
  function parseLangfuseArgs(rest, bin = AGRO_PRODUCT.bin) {
6812
6865
  if (rest.length === 0 || isHelpFlag2(rest[0])) return { ok: true, args: { help: true } };
6813
6866
  const [head, ...tail] = rest;
@@ -6824,7 +6877,6 @@ function parseLangfuseArgs(rest, bin = AGRO_PRODUCT.bin) {
6824
6877
  }
6825
6878
  return { ok: true, args: { help: false, verb: head } };
6826
6879
  }
6827
- var CONFIG_VERBS = ["show", "set", "repo"];
6828
6880
  function parseConfigArgs(input, bin = AGRO_PRODUCT.bin) {
6829
6881
  const scoped = extractSandboxFlag(`${bin} config`, input);
6830
6882
  if (!scoped.ok) return scoped;
@@ -6876,7 +6928,6 @@ function parseConfigArgs(input, bin = AGRO_PRODUCT.bin) {
6876
6928
  }
6877
6929
  return { ok: true, args: { ...args, verb, key, value } };
6878
6930
  }
6879
- var SECRET_VERBS = ["set", "list"];
6880
6931
  function parseSecretArgs(input, bin = AGRO_PRODUCT.bin) {
6881
6932
  const scoped = extractSandboxFlag(`${bin} secret`, input);
6882
6933
  if (!scoped.ok) return scoped;
@@ -7086,7 +7137,7 @@ function parseWorkspaceArgs(rest, bin = AGRO_PRODUCT.bin) {
7086
7137
  return { ok: false, error: `${bin} workspace: --ref requires a branch or tag` };
7087
7138
  }
7088
7139
  const [sub, name, ...extra] = positionals;
7089
- if (sub !== "create" && sub !== "list") {
7140
+ if (!isOneOf(WORKSPACE_SUBCOMMANDS, sub)) {
7090
7141
  return {
7091
7142
  ok: false,
7092
7143
  error: `${bin} workspace: unknown subcommand "${sub}" \u2014 expected create or list`,
@@ -7172,7 +7223,7 @@ function parseHarnessArgs(rest, bin = AGRO_PRODUCT.bin) {
7172
7223
  };
7173
7224
  }
7174
7225
  const [sub, name, ...extra] = positionals;
7175
- if (sub !== "list" && sub !== "install" && sub !== "status" && sub !== "uninstall") {
7226
+ if (!isOneOf(HARNESS_SUBCOMMANDS, sub)) {
7176
7227
  return {
7177
7228
  ok: false,
7178
7229
  error: `${bin} harness: unknown subcommand "${sub}" \u2014 expected list, install, uninstall, or status`,
@@ -7229,7 +7280,7 @@ function parseToolArgs(rest, bin = AGRO_PRODUCT.bin) {
7229
7280
  return { ok: false, error: `${bin} tool: --path requires a directory` };
7230
7281
  }
7231
7282
  const [sub, name, ...extra] = positionals;
7232
- if (sub !== "list" && sub !== "install" && sub !== "status" && sub !== "uninstall") {
7283
+ if (!isOneOf(TOOL_SUBCOMMANDS, sub)) {
7233
7284
  return {
7234
7285
  ok: false,
7235
7286
  error: `${bin} tool: unknown subcommand "${sub}" \u2014 expected list, install, uninstall, or status`,
@@ -7320,6 +7371,7 @@ async function main(argv) {
7320
7371
  `);
7321
7372
  return 0;
7322
7373
  }
7374
+ if (!Object.hasOwn(AGRO_COMMANDS, first)) return unknownCommand(first, product);
7323
7375
  if (first === "config") {
7324
7376
  const parsed = parseConfigArgs(argv.slice(1), bin);
7325
7377
  if (!parsed.ok) {
@@ -7642,7 +7694,10 @@ async function main(argv) {
7642
7694
  }
7643
7695
  return runGateway(parsed.args.passthrough, { bin });
7644
7696
  }
7645
- process.stderr.write(`${bin}: unknown command "${first}"
7697
+ return unknownCommand(first, product);
7698
+ }
7699
+ function unknownCommand(first, product) {
7700
+ process.stderr.write(`${product.bin}: unknown command "${first}"
7646
7701
 
7647
7702
  `);
7648
7703
  printAgroHelp(product);
@@ -7664,9 +7719,6 @@ main(process.argv.slice(2)).then(
7664
7719
  }
7665
7720
  );
7666
7721
  export {
7667
- CONFIG_VERBS,
7668
- LANGFUSE_VERBS,
7669
- SECRET_VERBS,
7670
7722
  bundledPayloadExists,
7671
7723
  extractSandboxFlag,
7672
7724
  isHelpFlag2 as isHelpFlag,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mifune/agro",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "description": "AGRO CLI — create and manage sandboxes for coding agents.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/mifunedev/agro#readme",