@integrity-labs/agt-cli 0.27.58 → 0.27.60

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-XX2LDA5B.js";
30
+ } from "../chunk-2YSXMB7P.js";
31
31
  import {
32
32
  CHANNEL_REGISTRY,
33
33
  DEPLOYMENT_TEMPLATES,
@@ -53,7 +53,7 @@ import {
53
53
  renderTemplate,
54
54
  resolveChannels,
55
55
  serializeManifestForSlackCli
56
- } from "../chunk-G3DT2L7S.js";
56
+ } from "../chunk-2SCU5NZO.js";
57
57
 
58
58
  // src/bin/agt.ts
59
59
  import { join as join18 } from "path";
@@ -551,8 +551,8 @@ async function lintCommand(path) {
551
551
  process.exitCode = 1;
552
552
  return;
553
553
  }
554
- const { readdirSync: readdirSync5, statSync: statSync4 } = await import("fs");
555
- const entries = readdirSync5(augmentedDir);
554
+ const { readdirSync: readdirSync6, statSync: statSync4 } = await import("fs");
555
+ const entries = readdirSync6(augmentedDir);
556
556
  for (const entry of entries) {
557
557
  const entryPath = join2(augmentedDir, entry);
558
558
  if (statSync4(entryPath).isDirectory()) {
@@ -1614,10 +1614,12 @@ production.
1614
1614
  }
1615
1615
 
1616
1616
  // src/lib/impersonate-state.ts
1617
+ import { createHash } from "crypto";
1617
1618
  import {
1618
1619
  chmodSync,
1619
1620
  existsSync as existsSync2,
1620
1621
  mkdirSync as mkdirSync4,
1622
+ readdirSync,
1621
1623
  readFileSync as readFileSync2,
1622
1624
  renameSync,
1623
1625
  rmSync,
@@ -1628,6 +1630,12 @@ import { join as join6 } from "path";
1628
1630
  var IMPERSONATE_ROOT = join6(homedir(), ".augmented-impersonate");
1629
1631
  var ACTIVE_DIR = join6(IMPERSONATE_ROOT, "active");
1630
1632
  var ACTIVE_MANIFEST_PATH = join6(ACTIVE_DIR, "manifest.json");
1633
+ var SESSION_FILE_PREFIX = "session-";
1634
+ var SESSION_FILE_SUFFIX = ".json";
1635
+ function sessionManifestPath(projectCwd) {
1636
+ const hash = createHash("sha256").update(projectCwd).digest("hex").slice(0, 16);
1637
+ return join6(ACTIVE_DIR, `${SESSION_FILE_PREFIX}${hash}${SESSION_FILE_SUFFIX}`);
1638
+ }
1631
1639
  var CODE_NAME_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
1632
1640
  function assertValidCodeName(codeName) {
1633
1641
  if (!CODE_NAME_RE.test(codeName)) {
@@ -1651,36 +1659,84 @@ function ensureImpersonateWorkdir(codeName) {
1651
1659
  mkdirSync4(dir, { recursive: true });
1652
1660
  return dir;
1653
1661
  }
1654
- function readActiveManifest() {
1655
- if (!existsSync2(ACTIVE_MANIFEST_PATH)) return null;
1662
+ function validateManifest(parsed) {
1663
+ if (typeof parsed !== "object" || parsed === null) return null;
1664
+ const m = parsed;
1665
+ const backupsOk = typeof m.backups === "object" && m.backups !== null && Object.values(m.backups).every(
1666
+ (v) => v === "had-file" || v === "was-symlink" || v === "didnt-exist"
1667
+ );
1668
+ if (typeof m.code_name !== "string" || typeof m.agent_id !== "string" || typeof m.team_id !== "string" || typeof m.token !== "string" || typeof m.expires_at !== "number" || typeof m.session_id !== "string" || typeof m.minted_at !== "string" || typeof m.project_cwd !== "string" || // ENG-5688 (redesigned): host required so `exit` calls /stop against
1669
+ // the right environment. Required, not optional, because writing the
1670
+ // wrong host on an existing session would point exit at a server
1671
+ // that has no record of the session — silently misleading.
1672
+ typeof m.host !== "string" || m.host.length === 0 || !backupsOk) {
1673
+ return null;
1674
+ }
1675
+ return parsed;
1676
+ }
1677
+ function readManifestFile(path) {
1678
+ if (!existsSync2(path)) return null;
1656
1679
  try {
1657
- const raw = readFileSync2(ACTIVE_MANIFEST_PATH, "utf-8");
1658
- const parsed = JSON.parse(raw);
1659
- const backupsOk = typeof parsed.backups === "object" && parsed.backups !== null && Object.values(parsed.backups).every(
1660
- (v) => v === "had-file" || v === "was-symlink" || v === "didnt-exist"
1661
- );
1662
- if (typeof parsed.code_name !== "string" || typeof parsed.agent_id !== "string" || typeof parsed.team_id !== "string" || typeof parsed.token !== "string" || typeof parsed.expires_at !== "number" || typeof parsed.session_id !== "string" || typeof parsed.minted_at !== "string" || typeof parsed.project_cwd !== "string" || // ENG-5688 (redesigned): host required so `exit` calls /stop against
1663
- // the right environment. Required, not optional, because writing the
1664
- // wrong host on an existing session would point exit at a server
1665
- // that has no record of the session — silently misleading.
1666
- typeof parsed.host !== "string" || parsed.host.length === 0 || !backupsOk) {
1667
- return null;
1668
- }
1669
- return parsed;
1680
+ return validateManifest(JSON.parse(readFileSync2(path, "utf-8")));
1670
1681
  } catch {
1671
1682
  return null;
1672
1683
  }
1673
1684
  }
1685
+ function migrateLegacyManifest() {
1686
+ if (!existsSync2(ACTIVE_MANIFEST_PATH)) return;
1687
+ const legacy = readManifestFile(ACTIVE_MANIFEST_PATH);
1688
+ try {
1689
+ if (!legacy) {
1690
+ rmSync(ACTIVE_MANIFEST_PATH, { force: true });
1691
+ return;
1692
+ }
1693
+ const target = sessionManifestPath(legacy.project_cwd);
1694
+ if (!existsSync2(target)) {
1695
+ mkdirSync4(ACTIVE_DIR, { recursive: true, mode: 448 });
1696
+ renameSync(ACTIVE_MANIFEST_PATH, target);
1697
+ chmodSync(target, 384);
1698
+ } else {
1699
+ rmSync(ACTIVE_MANIFEST_PATH, { force: true });
1700
+ }
1701
+ } catch {
1702
+ }
1703
+ }
1704
+ function readActiveManifest(projectCwd) {
1705
+ migrateLegacyManifest();
1706
+ return readManifestFile(sessionManifestPath(projectCwd));
1707
+ }
1708
+ function listActiveManifests() {
1709
+ migrateLegacyManifest();
1710
+ let entries;
1711
+ try {
1712
+ entries = readdirSync(ACTIVE_DIR);
1713
+ } catch {
1714
+ return [];
1715
+ }
1716
+ const out = [];
1717
+ for (const entry of entries) {
1718
+ if (!entry.startsWith(SESSION_FILE_PREFIX) || !entry.endsWith(SESSION_FILE_SUFFIX)) {
1719
+ continue;
1720
+ }
1721
+ const manifest = readManifestFile(join6(ACTIVE_DIR, entry));
1722
+ if (manifest) out.push(manifest);
1723
+ }
1724
+ return out;
1725
+ }
1674
1726
  function writeActiveManifest(manifest) {
1727
+ migrateLegacyManifest();
1675
1728
  mkdirSync4(ACTIVE_DIR, { recursive: true, mode: 448 });
1676
- const tmp = ACTIVE_MANIFEST_PATH + ".tmp";
1729
+ const path = sessionManifestPath(manifest.project_cwd);
1730
+ const tmp = path + ".tmp";
1677
1731
  writeFileSync4(tmp, JSON.stringify(manifest, null, 2), { mode: 384 });
1678
1732
  chmodSync(tmp, 384);
1679
- renameSync(tmp, ACTIVE_MANIFEST_PATH);
1733
+ renameSync(tmp, path);
1680
1734
  }
1681
- function clearActiveManifest() {
1682
- if (existsSync2(ACTIVE_MANIFEST_PATH)) {
1683
- rmSync(ACTIVE_MANIFEST_PATH);
1735
+ function clearActiveManifest(projectCwd) {
1736
+ migrateLegacyManifest();
1737
+ const path = sessionManifestPath(projectCwd);
1738
+ if (existsSync2(path)) {
1739
+ rmSync(path);
1684
1740
  }
1685
1741
  }
1686
1742
  function isExpired(manifest, now = Date.now()) {
@@ -1780,7 +1836,7 @@ import {
1780
1836
  copyFileSync,
1781
1837
  existsSync as existsSync4,
1782
1838
  mkdirSync as mkdirSync5,
1783
- readdirSync,
1839
+ readdirSync as readdirSync2,
1784
1840
  readFileSync as readFileSync3,
1785
1841
  renameSync as renameSync3,
1786
1842
  rmdirSync,
@@ -1838,7 +1894,7 @@ function unregisterIntroduceHook(backup) {
1838
1894
  if (created_claude_dir) {
1839
1895
  const claudeDir = dirOf(settings_path);
1840
1896
  try {
1841
- if (existsSync4(claudeDir) && readdirSync(claudeDir).length === 0) {
1897
+ if (existsSync4(claudeDir) && readdirSync2(claudeDir).length === 0) {
1842
1898
  rmdirSync(claudeDir);
1843
1899
  }
1844
1900
  } catch {
@@ -1874,7 +1930,7 @@ import {
1874
1930
  copyFileSync as copyFileSync2,
1875
1931
  existsSync as existsSync5,
1876
1932
  mkdirSync as mkdirSync6,
1877
- readdirSync as readdirSync2,
1933
+ readdirSync as readdirSync3,
1878
1934
  readFileSync as readFileSync4,
1879
1935
  renameSync as renameSync4,
1880
1936
  rmdirSync as rmdirSync2,
@@ -1944,7 +2000,7 @@ function unregisterStatusLine(backup) {
1944
2000
  if (created_claude_dir) {
1945
2001
  const claudeDir = dirname2(settings_path);
1946
2002
  try {
1947
- if (existsSync5(claudeDir) && readdirSync2(claudeDir).length === 0) {
2003
+ if (existsSync5(claudeDir) && readdirSync3(claudeDir).length === 0) {
1948
2004
  rmdirSync2(claudeDir);
1949
2005
  }
1950
2006
  } catch {
@@ -2115,13 +2171,15 @@ async function impersonateConnectCommand(token, options = {}) {
2115
2171
  process.exitCode = 1;
2116
2172
  return;
2117
2173
  }
2118
- const existing = readActiveManifest();
2119
- if (existing) {
2120
- const msg = `An impersonation session is already active (${existing.code_name}). Run \`agt impersonate exit\` first.`;
2121
- if (json) jsonOutput({ ok: false, error: msg });
2122
- else error(msg);
2123
- process.exitCode = 1;
2124
- return;
2174
+ if (!options.workdir) {
2175
+ const existing = readActiveManifest(process.cwd());
2176
+ if (existing) {
2177
+ const msg = `An impersonation session is already active in this directory (${existing.code_name}). Run \`agt impersonate exit\` here first, or connect from a different directory.`;
2178
+ if (json) jsonOutput({ ok: false, error: msg });
2179
+ else error(msg);
2180
+ process.exitCode = 1;
2181
+ return;
2182
+ }
2125
2183
  }
2126
2184
  if (!options.workdir) {
2127
2185
  const workTreeRoot = findGitWorkTreeRoot(process.cwd());
@@ -2182,6 +2240,15 @@ async function impersonateConnectCommand(token, options = {}) {
2182
2240
  );
2183
2241
  spinner.text = "Swapping persona files\u2026";
2184
2242
  const projectCwd = options.workdir ? ensureImpersonateWorkdir(bundle.agent.code_name) : process.cwd();
2243
+ const existingForTarget = readActiveManifest(projectCwd);
2244
+ if (existingForTarget) {
2245
+ spinner.fail("Impersonation already active for this agent.");
2246
+ const msg = `An impersonation session is already active in ${projectCwd} (${existingForTarget.code_name}). Run \`agt impersonate exit\` there first.`;
2247
+ if (json) jsonOutput({ ok: false, error: msg });
2248
+ else error(msg);
2249
+ process.exitCode = 1;
2250
+ return;
2251
+ }
2185
2252
  const backups = {};
2186
2253
  const swapped = [];
2187
2254
  let hookBackup;
@@ -2303,33 +2370,8 @@ async function impersonateConnectCommand(token, options = {}) {
2303
2370
  console.log();
2304
2371
  info("When done: `agt impersonate exit` (still active).");
2305
2372
  }
2306
- async function impersonateCurrentCommand() {
2307
- requireImpersonateEnabled();
2308
- const json = isJsonMode();
2309
- const manifest = readActiveManifest();
2310
- if (!manifest) {
2311
- if (json) jsonOutput({ ok: true, active: null });
2312
- else info("No active impersonation.");
2313
- return;
2314
- }
2373
+ function printManifestText(manifest) {
2315
2374
  const expired = isExpired(manifest);
2316
- if (json) {
2317
- jsonOutput({
2318
- ok: true,
2319
- active: {
2320
- code_name: manifest.code_name,
2321
- agent_id: manifest.agent_id,
2322
- team_id: manifest.team_id,
2323
- session_id: manifest.session_id,
2324
- minted_at: manifest.minted_at,
2325
- expires_at: manifest.expires_at,
2326
- expired,
2327
- project_cwd: manifest.project_cwd,
2328
- host: manifest.host
2329
- }
2330
- });
2331
- return;
2332
- }
2333
2375
  console.log();
2334
2376
  console.log(chalk10.bold(`Impersonating: ${manifest.code_name}`));
2335
2377
  console.log(` Agent ID: ${chalk10.dim(manifest.agent_id)}`);
@@ -2343,10 +2385,83 @@ async function impersonateCurrentCommand() {
2343
2385
  console.log(` Host: ${chalk10.dim(manifest.host)}`);
2344
2386
  console.log();
2345
2387
  }
2346
- async function impersonateExitCommand() {
2388
+ function manifestToJson(manifest) {
2389
+ return {
2390
+ code_name: manifest.code_name,
2391
+ agent_id: manifest.agent_id,
2392
+ team_id: manifest.team_id,
2393
+ session_id: manifest.session_id,
2394
+ minted_at: manifest.minted_at,
2395
+ expires_at: manifest.expires_at,
2396
+ expired: isExpired(manifest),
2397
+ project_cwd: manifest.project_cwd,
2398
+ host: manifest.host
2399
+ };
2400
+ }
2401
+ async function impersonateCurrentCommand(opts = {}) {
2402
+ requireImpersonateEnabled();
2403
+ const json = isJsonMode();
2404
+ if (opts.all) {
2405
+ const manifests = listActiveManifests();
2406
+ if (json) {
2407
+ jsonOutput({ ok: true, active: manifests.map(manifestToJson) });
2408
+ return;
2409
+ }
2410
+ if (manifests.length === 0) {
2411
+ info("No active impersonations.");
2412
+ return;
2413
+ }
2414
+ console.log();
2415
+ console.log(chalk10.bold(`Active impersonations (${manifests.length}):`));
2416
+ for (const m of manifests) printManifestText(m);
2417
+ return;
2418
+ }
2419
+ const manifest = readActiveManifest(process.cwd());
2420
+ if (!manifest) {
2421
+ const others = listActiveManifests();
2422
+ if (json) {
2423
+ jsonOutput({ ok: true, active: null, others_active: others.length });
2424
+ return;
2425
+ }
2426
+ if (others.length > 0) {
2427
+ info(
2428
+ `No active impersonation in this directory \u2014 ${others.length} active elsewhere. Run \`agt impersonate current --all\` to list them.`
2429
+ );
2430
+ } else {
2431
+ info("No active impersonation.");
2432
+ }
2433
+ return;
2434
+ }
2435
+ if (json) {
2436
+ jsonOutput({ ok: true, active: manifestToJson(manifest) });
2437
+ return;
2438
+ }
2439
+ printManifestText(manifest);
2440
+ }
2441
+ async function impersonateExitCommand(opts = {}) {
2347
2442
  requireImpersonateEnabled();
2348
2443
  const json = isJsonMode();
2349
- const manifest = readActiveManifest();
2444
+ if (opts.all) {
2445
+ const manifests = listActiveManifests();
2446
+ if (manifests.length === 0) {
2447
+ if (json) jsonOutput({ ok: true, was_active: false, exited: [] });
2448
+ else info("No active impersonation to exit.");
2449
+ return;
2450
+ }
2451
+ const exited = [];
2452
+ for (const manifest2 of manifests) {
2453
+ await performImpersonateExit(manifest2, { json, silent: true });
2454
+ exited.push(manifest2.code_name);
2455
+ }
2456
+ if (json) {
2457
+ jsonOutput({ ok: true, was_active: true, exited });
2458
+ } else {
2459
+ success(`Exited ${exited.length} impersonation session(s): ${exited.join(", ")}`);
2460
+ info("Restart Claude Code to pick up your original persona.");
2461
+ }
2462
+ return;
2463
+ }
2464
+ const manifest = readActiveManifest(process.cwd());
2350
2465
  if (!manifest) {
2351
2466
  if (json) jsonOutput({ ok: true, was_active: false });
2352
2467
  else info("No active impersonation to exit.");
@@ -2412,7 +2527,7 @@ async function performImpersonateExit(manifest, opts) {
2412
2527
  if (!json) error(`Failed to remove introduce hook: ${msg}`);
2413
2528
  }
2414
2529
  }
2415
- clearActiveManifest();
2530
+ clearActiveManifest(manifest.project_cwd);
2416
2531
  if (silent) return;
2417
2532
  if (json) {
2418
2533
  jsonOutput({
@@ -2435,28 +2550,31 @@ async function performImpersonateExit(manifest, opts) {
2435
2550
  info("Restart Claude Code to pick up your original persona.");
2436
2551
  }
2437
2552
  async function autoExitExpiredImpersonation() {
2438
- let manifest;
2553
+ let manifests;
2439
2554
  try {
2440
- manifest = readActiveManifest();
2555
+ manifests = listActiveManifests();
2441
2556
  } catch {
2442
2557
  return;
2443
2558
  }
2444
- if (!manifest || !isExpired(manifest)) return;
2445
- try {
2446
- if (!isJsonMode()) {
2447
- console.error(
2448
- chalk10.cyan(
2449
- `\u2139 Impersonation session for ${manifest.code_name} expired \u2014 auto-exiting and restoring your files.`
2450
- )
2451
- );
2559
+ const expired = manifests.filter((m) => isExpired(m));
2560
+ if (expired.length === 0) return;
2561
+ for (const manifest of expired) {
2562
+ try {
2563
+ if (!isJsonMode()) {
2564
+ console.error(
2565
+ chalk10.cyan(
2566
+ `\u2139 Impersonation session for ${manifest.code_name} expired \u2014 auto-exiting and restoring your files.`
2567
+ )
2568
+ );
2569
+ }
2570
+ await performImpersonateExit(manifest, { json: isJsonMode(), silent: true });
2571
+ } catch {
2452
2572
  }
2453
- await performImpersonateExit(manifest, { json: isJsonMode(), silent: true });
2454
- } catch {
2455
2573
  }
2456
2574
  }
2457
2575
  async function impersonateIntroduceCommand() {
2458
2576
  try {
2459
- const manifest = readActiveManifest();
2577
+ const manifest = readActiveManifest(process.cwd());
2460
2578
  if (!manifest || isExpired(manifest)) return;
2461
2579
  const cwd = manifest.project_cwd;
2462
2580
  const identity = readClaudeMdIdentity(join10(cwd, "CLAUDE.md"));
@@ -2529,13 +2647,13 @@ import ora11 from "ora";
2529
2647
 
2530
2648
  // ../../packages/core/dist/drift/live-state-reader.js
2531
2649
  import { readFile } from "fs/promises";
2532
- import { createHash } from "crypto";
2650
+ import { createHash as createHash2 } from "crypto";
2533
2651
  import { join as join11 } from "path";
2534
2652
  import JSON5 from "json5";
2535
2653
  async function hashFile(filePath) {
2536
2654
  try {
2537
2655
  const content = await readFile(filePath);
2538
- return createHash("sha256").update(content).digest("hex");
2656
+ return createHash2("sha256").update(content).digest("hex");
2539
2657
  } catch {
2540
2658
  return null;
2541
2659
  }
@@ -4720,7 +4838,7 @@ import { execFileSync, execSync } from "child_process";
4720
4838
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4721
4839
  import chalk18 from "chalk";
4722
4840
  import ora16 from "ora";
4723
- var cliVersion = true ? "0.27.58" : "dev";
4841
+ var cliVersion = true ? "0.27.60" : "dev";
4724
4842
  async function fetchLatestVersion() {
4725
4843
  const host2 = getHost();
4726
4844
  if (!host2) return null;
@@ -4956,7 +5074,7 @@ import { homedir as homedir6 } from "os";
4956
5074
  import { join as join16 } from "path";
4957
5075
 
4958
5076
  // src/lib/subagent-mcp-audit.ts
4959
- import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
5077
+ import { readdirSync as readdirSync4, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
4960
5078
  import { join as join15 } from "path";
4961
5079
  function parseFrontmatter(content) {
4962
5080
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
@@ -5000,7 +5118,7 @@ function findSubagentFiles(dir, depth = 0) {
5000
5118
  if (depth > 6) return [];
5001
5119
  let entries;
5002
5120
  try {
5003
- entries = readdirSync3(dir);
5121
+ entries = readdirSync4(dir);
5004
5122
  } catch {
5005
5123
  return [];
5006
5124
  }
@@ -5093,7 +5211,7 @@ async function auditSubagentsCommand(options = {}) {
5093
5211
  }
5094
5212
 
5095
5213
  // src/lib/mcp-render-allowlist-audit.ts
5096
- import { readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync3 } from "fs";
5214
+ import { readdirSync as readdirSync5, readFileSync as readFileSync10, statSync as statSync3 } from "fs";
5097
5215
  import { homedir as homedir7 } from "os";
5098
5216
  import { join as join17 } from "path";
5099
5217
  function expectedWildcard(serverKey) {
@@ -5118,7 +5236,7 @@ function auditMcpRenderAllowlist(rootDir = join17(homedir7(), ".augmented")) {
5118
5236
  const findings = [];
5119
5237
  let entries;
5120
5238
  try {
5121
- entries = readdirSync4(rootDir);
5239
+ entries = readdirSync5(rootDir);
5122
5240
  } catch {
5123
5241
  return findings;
5124
5242
  }
@@ -5498,7 +5616,7 @@ function handleError(err) {
5498
5616
  }
5499
5617
 
5500
5618
  // src/bin/agt.ts
5501
- var cliVersion2 = true ? "0.27.58" : "dev";
5619
+ var cliVersion2 = true ? "0.27.60" : "dev";
5502
5620
  var program = new Command();
5503
5621
  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");
5504
5622
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -5551,8 +5669,12 @@ impersonate.command("connect <token>").description(
5551
5669
  })
5552
5670
  )
5553
5671
  );
5554
- impersonate.command("current").description('Print the active impersonation (or "none")').action(impersonateCurrentCommand);
5555
- impersonate.command("exit").description("End the active impersonation, restore project files, and notify the server").action(impersonateExitCommand);
5672
+ impersonate.command("current").description('Print the active impersonation for this directory (or "none")').option("--all", "List every active impersonation session on this machine").action(
5673
+ (opts) => impersonateCurrentCommand({ all: opts.all === true })
5674
+ );
5675
+ impersonate.command("exit").description("End this directory's impersonation, restore project files, and notify the server").option("--all", "Exit every active impersonation session on this machine").action(
5676
+ (opts) => impersonateExitCommand({ all: opts.all === true })
5677
+ );
5556
5678
  impersonate.command("introduce", { hidden: true }).description("Print the impersonated agent's self-introduction (SessionStart hook target)").action(impersonateIntroduceCommand);
5557
5679
  program.command("init").description("Create a new agent (interactive wizard, or non-interactive with --name)").option("--name <display-name>", "Agent display name (triggers non-interactive mode)").option("--code-name <code-name>", "Agent code name (kebab-case, derived from --name if omitted)").option("--description <text>", "Short agent description").option("--env <environment>", "Environment: dev | stage | prod", "dev").option("--risk-tier <tier>", "Risk tier: Low | Medium | High", "Low").option("--budget-type <type>", "Budget type: tokens | dollars | both", "tokens").option("--budget-tokens <number>", "Token budget limit", "10000").option("--budget-dollars <number>", "Dollar budget limit", "10").option("--budget-window <window>", "Budget window: daily | weekly | monthly", "daily").option("--budget-enforcement <mode>", "Budget enforcement: block | throttle | alert | degrade", "block").option("--channels <list>", "Comma-separated channel IDs").option("--logging <mode>", "Logging mode: redacted | hash-only | full-local", "redacted").action(initCommand);
5558
5680
  program.command("lint").argument("[path]", "Path to agent directory (default: all agents in .augmented/)").description("Lint CHARTER.md and TOOLS.md files").action(lintCommand);