@integrity-labs/agt-cli 0.27.36 → 0.27.37

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/dist/bin/agt.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  success,
28
28
  table,
29
29
  warn
30
- } from "../chunk-LASXZZS6.js";
30
+ } from "../chunk-J77QXLYC.js";
31
31
  import {
32
32
  CHANNEL_REGISTRY,
33
33
  DEPLOYMENT_TEMPLATES,
@@ -56,8 +56,8 @@ import {
56
56
  } from "../chunk-GVM2KJOA.js";
57
57
 
58
58
  // src/bin/agt.ts
59
- import { join as join15 } from "path";
60
- import { homedir as homedir6 } from "os";
59
+ import { join as join17 } from "path";
60
+ import { homedir as homedir7 } from "os";
61
61
  import { Command } from "commander";
62
62
 
63
63
  // src/commands/whoami.ts
@@ -551,11 +551,11 @@ async function lintCommand(path) {
551
551
  process.exitCode = 1;
552
552
  return;
553
553
  }
554
- const { readdirSync: readdirSync3, statSync: statSync2 } = await import("fs");
555
- const entries = readdirSync3(augmentedDir);
554
+ const { readdirSync: readdirSync4, statSync: statSync3 } = await import("fs");
555
+ const entries = readdirSync4(augmentedDir);
556
556
  for (const entry of entries) {
557
557
  const entryPath = join2(augmentedDir, entry);
558
- if (statSync2(entryPath).isDirectory()) {
558
+ if (statSync3(entryPath).isDirectory()) {
559
559
  dirs.push({ name: entry, dir: entryPath });
560
560
  }
561
561
  }
@@ -4658,7 +4658,7 @@ import { execFileSync, execSync } from "child_process";
4658
4658
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4659
4659
  import chalk18 from "chalk";
4660
4660
  import ora16 from "ora";
4661
- var cliVersion = true ? "0.27.36" : "dev";
4661
+ var cliVersion = true ? "0.27.37" : "dev";
4662
4662
  async function fetchLatestVersion() {
4663
4663
  const host2 = getHost();
4664
4664
  if (!host2) return null;
@@ -4889,6 +4889,147 @@ async function checkForUpdateOnStartup() {
4889
4889
  }
4890
4890
  }
4891
4891
 
4892
+ // src/commands/audit-subagents.ts
4893
+ import { homedir as homedir6 } from "os";
4894
+ import { join as join16 } from "path";
4895
+
4896
+ // src/lib/subagent-mcp-audit.ts
4897
+ import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
4898
+ import { join as join15 } from "path";
4899
+ function parseFrontmatter(content) {
4900
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
4901
+ if (!match) return null;
4902
+ const out = {};
4903
+ const lines = match[1].split(/\r?\n/);
4904
+ for (let i = 0; i < lines.length; i++) {
4905
+ const line = lines[i];
4906
+ const m = line.match(/^(name|tools|background):\s*(.*)$/);
4907
+ if (!m) continue;
4908
+ const [, key, rawValue] = m;
4909
+ const trimmed = rawValue.trim();
4910
+ if (key === "tools" && trimmed === "") {
4911
+ const items = [];
4912
+ let j = i + 1;
4913
+ while (j < lines.length) {
4914
+ const nextRaw = lines[j];
4915
+ const itemMatch = nextRaw.match(/^(\s+)-\s*(.+?)\s*$/);
4916
+ if (!itemMatch) break;
4917
+ items.push(itemMatch[2].replace(/^['"](.*)['"]$/, "$1"));
4918
+ j++;
4919
+ }
4920
+ if (items.length > 0) {
4921
+ out.tools = items.join(", ");
4922
+ i = j - 1;
4923
+ continue;
4924
+ }
4925
+ }
4926
+ out[key] = trimmed;
4927
+ }
4928
+ return out;
4929
+ }
4930
+ function toolsExcludeMcp(tools) {
4931
+ if (tools.length === 0) return false;
4932
+ if (/\bmcp__/.test(tools)) return false;
4933
+ if (/\*/.test(tools)) return false;
4934
+ if (/\bAll tools\b/i.test(tools)) return false;
4935
+ return true;
4936
+ }
4937
+ function findSubagentFiles(dir, depth = 0) {
4938
+ if (depth > 6) return [];
4939
+ let entries;
4940
+ try {
4941
+ entries = readdirSync3(dir);
4942
+ } catch {
4943
+ return [];
4944
+ }
4945
+ const out = [];
4946
+ const isAgentsDir = dir.endsWith("/agents") || dir.endsWith("\\agents");
4947
+ for (const entry of entries) {
4948
+ const full = join15(dir, entry);
4949
+ let s;
4950
+ try {
4951
+ s = statSync2(full);
4952
+ } catch {
4953
+ continue;
4954
+ }
4955
+ if (s.isDirectory()) {
4956
+ out.push(...findSubagentFiles(full, depth + 1));
4957
+ } else if (s.isFile() && isAgentsDir && entry.endsWith(".md")) {
4958
+ out.push(full);
4959
+ }
4960
+ }
4961
+ return out;
4962
+ }
4963
+ function auditSubagentMcpBindings(rootDirs) {
4964
+ const findings = [];
4965
+ const seen = /* @__PURE__ */ new Set();
4966
+ for (const root of rootDirs) {
4967
+ for (const file of findSubagentFiles(root)) {
4968
+ if (seen.has(file)) continue;
4969
+ seen.add(file);
4970
+ let content;
4971
+ try {
4972
+ content = readFileSync9(file, "utf-8");
4973
+ } catch {
4974
+ continue;
4975
+ }
4976
+ const fm = parseFrontmatter(content);
4977
+ if (!fm || typeof fm.tools !== "string") continue;
4978
+ if (!toolsExcludeMcp(fm.tools)) continue;
4979
+ findings.push({
4980
+ file,
4981
+ name: fm.name ?? "<unknown>",
4982
+ tools: fm.tools,
4983
+ reason: "restrictive-tools-no-mcp"
4984
+ });
4985
+ }
4986
+ }
4987
+ return findings;
4988
+ }
4989
+ function formatFinding(f) {
4990
+ return `[manager-worker] [subagent-mcp-audit] file=${f.file} name=${f.name} reason=${f.reason} tools=${JSON.stringify(f.tools)}`;
4991
+ }
4992
+
4993
+ // src/commands/audit-subagents.ts
4994
+ function defaultRoots() {
4995
+ const home = homedir6();
4996
+ return [
4997
+ join16(home, ".claude", "agents"),
4998
+ join16(home, ".claude", "plugins"),
4999
+ join16(process.cwd(), ".claude", "agents")
5000
+ ];
5001
+ }
5002
+ async function auditSubagentsCommand(options = {}) {
5003
+ const roots = defaultRoots();
5004
+ const findings = auditSubagentMcpBindings(roots);
5005
+ if (options.json) {
5006
+ process.stdout.write(`${JSON.stringify({ findings, roots }, null, 2)}
5007
+ `);
5008
+ } else if (findings.length === 0) {
5009
+ process.stdout.write("No restrictive sub-agents found \u2014 every sub-agent under the scanned roots either inherits the parent toolset or explicitly includes mcp__* wildcards.\n");
5010
+ } else {
5011
+ process.stdout.write(`Found ${findings.length} sub-agent${findings.length === 1 ? "" : "s"} whose tools allowlist excludes mcp__*:
5012
+
5013
+ `);
5014
+ for (const f of findings) {
5015
+ process.stdout.write(` \u2022 ${f.name} (${f.file})
5016
+ `);
5017
+ process.stdout.write(` tools: ${f.tools}
5018
+ `);
5019
+ }
5020
+ process.stdout.write(
5021
+ "\nThese sub-agents will return \"No such tool available.\" for every mcp__* call when dispatched from a managed agent. If the parent needs to do MCP-tool work, dispatch the Augmented plugin's `augmented-worker` sub-agent instead \u2014 it omits `tools:` so it inherits the parent's full toolset including every MCP server. See ENG-5897.\n"
5022
+ );
5023
+ for (const f of findings) {
5024
+ process.stderr.write(`${formatFinding(f)}
5025
+ `);
5026
+ }
5027
+ }
5028
+ if (options.strict && findings.length > 0) {
5029
+ process.exit(2);
5030
+ }
5031
+ }
5032
+
4892
5033
  // src/commands/integration.ts
4893
5034
  import chalk19 from "chalk";
4894
5035
  import ora17 from "ora";
@@ -5190,7 +5331,7 @@ function handleError(err) {
5190
5331
  }
5191
5332
 
5192
5333
  // src/bin/agt.ts
5193
- var cliVersion2 = true ? "0.27.36" : "dev";
5334
+ var cliVersion2 = true ? "0.27.37" : "dev";
5194
5335
  var program = new Command();
5195
5336
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
5196
5337
  program.hook("preAction", (thisCommand) => {
@@ -5272,16 +5413,16 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
5272
5413
  })
5273
5414
  );
5274
5415
  var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
5275
- manager.command("start").description("Start the manager daemon (polls API for config changes and detects local drift)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join15(homedir6(), ".augmented")).option("--supervise", "Wrap the manager in a respawn-on-clean-exit loop so auto-upgrades can restart it transparently (ENG-4488)", false).action(managerStartCommand);
5276
- manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join15(homedir6(), ".augmented")).action(managerStopCommand);
5277
- manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join15(homedir6(), ".augmented")).action(managerStatusCommand);
5278
- manager.command("watch").description("Live TUI dashboard \u2014 per-agent boxes, drill-in, log tail. Read-only (ENG-4555).").option("--config-dir <dir>", "Config directory for agent files", join15(homedir6(), ".augmented")).option("--no-tui", "Skip the TUI and stream the manager log to stdout instead (CI / scripts)").action(managerWatchCommand);
5279
- manager.command("install").description("Install OS-level supervisor (launchd LaunchAgent on macOS) so the manager auto-restarts after crash, reboot, or self-update (ENG-4593)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join15(homedir6(), ".augmented")).action(managerInstallCommand);
5416
+ manager.command("start").description("Start the manager daemon (polls API for config changes and detects local drift)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).option("--supervise", "Wrap the manager in a respawn-on-clean-exit loop so auto-upgrades can restart it transparently (ENG-4488)", false).action(managerStartCommand);
5417
+ manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).action(managerStopCommand);
5418
+ manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).action(managerStatusCommand);
5419
+ manager.command("watch").description("Live TUI dashboard \u2014 per-agent boxes, drill-in, log tail. Read-only (ENG-4555).").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).option("--no-tui", "Skip the TUI and stream the manager log to stdout instead (CI / scripts)").action(managerWatchCommand);
5420
+ manager.command("install").description("Install OS-level supervisor (launchd LaunchAgent on macOS) so the manager auto-restarts after crash, reboot, or self-update (ENG-4593)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join17(homedir7(), ".augmented")).action(managerInstallCommand);
5280
5421
  manager.command("uninstall").description("Remove the OS-level supervisor (launchctl unload + delete plist on macOS). Idempotent.").action(managerUninstallCommand);
5281
5422
  manager.command("install-system-unit").description("Install a system-level systemd unit (Linux, root) so the manager auto-starts on every boot. For headless EC2 hosts \u2014 survives reboot without `loginctl enable-linger`. (ENG-4706)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files (defaults to /root/.augmented or /home/<user>/.augmented)").option("--user <name>", "Unix user the manager runs as", "root").action(managerInstallSystemUnitCommand);
5282
5423
  manager.command("uninstall-system-unit").description("Remove the system-level systemd unit (Linux, root). Idempotent. (ENG-4706)").action(managerUninstallSystemUnitCommand);
5283
5424
  var agent = program.command("agent").description("Inspect and manage agents");
5284
- agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join15(homedir6(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
5425
+ agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join17(homedir7(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
5285
5426
  var kanban = program.command("kanban").description("Manage agent kanban boards");
5286
5427
  kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
5287
5428
  kanban.command("add <title>").description("Add a new item to an agent kanban board").requiredOption("--agent <code-name>", "Agent code name").option("--priority <1|2|3>", "Priority: 1=high, 2=medium, 3=low", "2").option("--status <status>", "Initial status: backlog | todo | in_progress", "todo").option("--description <text>", "Item description").option("--estimate <minutes>", "Estimated time in minutes").option("--deliverable <text>", "Expected output/deliverable").action(kanbanAddCommand);
@@ -5309,6 +5450,8 @@ integration.command("approve <request-id>").description("Approve a scope request
5309
5450
  integration.command("deny <request-id>").description("Deny a scope request").option("--reason <text>", "Denial reason").action(integrationDenyCommand);
5310
5451
  integration.command("enrol").description("Enrol an integration with an API key or webhook secret (no OAuth flow)").requiredOption("--def <code-name>", "Integration definition code_name (e.g. resend, xero)").requiredOption("--scope <org|team|agent>", "Install scope").option("--api-key <value>", "API key (sets auth_type=api_key)").option("--access-token <value>", "Bearer access token (sets auth_type=oauth2)").option("--webhook-secret <value>", "Webhook signing secret (sets auth_type=webhook)").option("--display-name <name>", "Override display name (defaults to the definition\u2019s display_name)").option("--agent <code-name>", "Agent code name (required for agent scope)").action(integrationEnrolCommand);
5311
5452
  program.command("update").description("Check for and install CLI updates").option("--force", "Update even if manager or agent sessions are running").action(updateCommand);
5453
+ var audit = program.command("audit").description("Operator audits \u2014 sub-agent MCP bindings, etc.");
5454
+ audit.command("subagents").description("Find sub-agents whose tools allowlist would block mcp__* calls on dispatch (ENG-5897)").option("--strict", "Exit with code 2 if any findings (suitable for CI gating)").option("--json", "Emit findings as JSON to stdout").action(auditSubagentsCommand);
5312
5455
  var skipUpdateCheck = process.argv.includes("--skip-update-check") || process.argv.includes("--json") || process.argv[2] === "update";
5313
5456
  if (!skipUpdateCheck) {
5314
5457
  checkForUpdateOnStartup().catch(() => {