@integrity-labs/agt-cli 0.26.2-eng5706.1 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/agt.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  success,
27
27
  table,
28
28
  warn
29
- } from "../chunk-LBYU24PW.js";
29
+ } from "../chunk-YWXPSVI5.js";
30
30
  import {
31
31
  CHANNEL_REGISTRY,
32
32
  DEPLOYMENT_TEMPLATES,
@@ -52,11 +52,11 @@ import {
52
52
  renderTemplate,
53
53
  resolveChannels,
54
54
  serializeManifestForSlackCli
55
- } from "../chunk-U3HCB23E.js";
55
+ } from "../chunk-BKLEFKUZ.js";
56
56
 
57
57
  // src/bin/agt.ts
58
- import { join as join10 } from "path";
59
- import { homedir as homedir3 } from "os";
58
+ import { join as join12 } from "path";
59
+ import { homedir as homedir5 } from "os";
60
60
  import { Command } from "commander";
61
61
 
62
62
  // src/commands/whoami.ts
@@ -1552,14 +1552,461 @@ async function provisionCommand(codeName, options) {
1552
1552
  info(` agt drift check ${agentData.code_name}`);
1553
1553
  }
1554
1554
 
1555
- // src/commands/drift.ts
1555
+ // src/commands/impersonate.ts
1556
1556
  import chalk10 from "chalk";
1557
1557
  import ora10 from "ora";
1558
+ import { spawn } from "child_process";
1559
+ import { writeFileSync as writeFileSync5 } from "fs";
1560
+ import { join as join7 } from "path";
1561
+
1562
+ // src/lib/impersonate-flag.ts
1563
+ var ENV_VAR = "AGT_IMPERSONATE_ENABLED";
1564
+ function impersonateEnabled() {
1565
+ const v = process.env[ENV_VAR];
1566
+ if (!v) return false;
1567
+ const trimmed = v.trim().toLowerCase();
1568
+ return !(trimmed === "" || trimmed === "0" || trimmed === "false" || trimmed === "no");
1569
+ }
1570
+ function requireImpersonateEnabled() {
1571
+ if (impersonateEnabled()) return;
1572
+ process.stderr.write(
1573
+ `
1574
+ The \`agt impersonate\` commands are gated behind a feature flag.
1575
+
1576
+ To enable them, set ${ENV_VAR}=1 in your environment:
1577
+
1578
+ export ${ENV_VAR}=1
1579
+
1580
+ These commands are part of the operator-impersonates-agent v0 flow
1581
+ (ENG-5687 / ENG-5688). The gating will be removed once the
1582
+ surrounding pieces (ENG-5689 channel-MCP refusal, ENG-5690 slash
1583
+ commands) land and the end-to-end smoke test has been run against
1584
+ production.
1585
+
1586
+ `
1587
+ );
1588
+ process.exit(2);
1589
+ }
1590
+
1591
+ // src/lib/impersonate-state.ts
1592
+ import {
1593
+ chmodSync,
1594
+ existsSync as existsSync2,
1595
+ mkdirSync as mkdirSync4,
1596
+ readFileSync as readFileSync2,
1597
+ renameSync,
1598
+ rmSync,
1599
+ writeFileSync as writeFileSync4
1600
+ } from "fs";
1601
+ import { homedir } from "os";
1602
+ import { join as join6 } from "path";
1603
+ var IMPERSONATE_ROOT = join6(homedir(), ".augmented-impersonate");
1604
+ var ACTIVE_DIR = join6(IMPERSONATE_ROOT, "active");
1605
+ var ACTIVE_MANIFEST_PATH = join6(ACTIVE_DIR, "manifest.json");
1606
+ var CODE_NAME_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
1607
+ function assertValidCodeName(codeName) {
1608
+ if (!CODE_NAME_RE.test(codeName)) {
1609
+ throw new Error(
1610
+ `Invalid agent code_name "${codeName}" \u2014 must be lowercase kebab-case (a-z, 0-9, hyphens; no leading/trailing/consecutive hyphens).`
1611
+ );
1612
+ }
1613
+ }
1614
+ function getImpersonateCodeNameDir(codeName) {
1615
+ assertValidCodeName(codeName);
1616
+ return join6(IMPERSONATE_ROOT, codeName);
1617
+ }
1618
+ function ensureCodeNameDir(codeName) {
1619
+ assertValidCodeName(codeName);
1620
+ const dir = getImpersonateCodeNameDir(codeName);
1621
+ mkdirSync4(dir, { recursive: true });
1622
+ return dir;
1623
+ }
1624
+ function readActiveManifest() {
1625
+ if (!existsSync2(ACTIVE_MANIFEST_PATH)) return null;
1626
+ try {
1627
+ const raw = readFileSync2(ACTIVE_MANIFEST_PATH, "utf-8");
1628
+ const parsed = JSON.parse(raw);
1629
+ const backupsOk = typeof parsed.backups === "object" && parsed.backups !== null && Object.values(parsed.backups).every(
1630
+ (v) => v === "had-file" || v === "was-symlink" || v === "didnt-exist"
1631
+ );
1632
+ 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
1633
+ // the right environment. Required, not optional, because writing the
1634
+ // wrong host on an existing session would point exit at a server
1635
+ // that has no record of the session — silently misleading.
1636
+ typeof parsed.host !== "string" || parsed.host.length === 0 || !backupsOk) {
1637
+ return null;
1638
+ }
1639
+ return parsed;
1640
+ } catch {
1641
+ return null;
1642
+ }
1643
+ }
1644
+ function writeActiveManifest(manifest) {
1645
+ mkdirSync4(ACTIVE_DIR, { recursive: true, mode: 448 });
1646
+ const tmp = ACTIVE_MANIFEST_PATH + ".tmp";
1647
+ writeFileSync4(tmp, JSON.stringify(manifest, null, 2), { mode: 384 });
1648
+ chmodSync(tmp, 384);
1649
+ renameSync(tmp, ACTIVE_MANIFEST_PATH);
1650
+ }
1651
+ function clearActiveManifest() {
1652
+ if (existsSync2(ACTIVE_MANIFEST_PATH)) {
1653
+ rmSync(ACTIVE_MANIFEST_PATH);
1654
+ }
1655
+ }
1656
+ function isExpired(manifest, now = Date.now()) {
1657
+ return manifest.expires_at * 1e3 <= now;
1658
+ }
1659
+
1660
+ // src/lib/impersonate-fs-ops.ts
1661
+ import {
1662
+ existsSync as existsSync3,
1663
+ lstatSync,
1664
+ readlinkSync,
1665
+ realpathSync,
1666
+ renameSync as renameSync2,
1667
+ symlinkSync,
1668
+ unlinkSync
1669
+ } from "fs";
1670
+ import { homedir as homedir2 } from "os";
1671
+ import { sep } from "path";
1672
+ var BACKUP_SUFFIX = ".pre-impersonate-backup";
1673
+ function swapInPersonaFile(projectPath, personaPath) {
1674
+ let kind;
1675
+ if (!lstatSafe(projectPath)) {
1676
+ kind = "didnt-exist";
1677
+ } else {
1678
+ const stat = lstatSync(projectPath);
1679
+ if (stat.isSymbolicLink()) {
1680
+ const target = readlinkSync(projectPath);
1681
+ const ourRoot = realpathSync(homedir2()) + sep + ".augmented-impersonate" + sep;
1682
+ let resolvedTarget;
1683
+ try {
1684
+ resolvedTarget = realpathSync(projectPath);
1685
+ } catch {
1686
+ throw new Error(
1687
+ `${projectPath} is a broken symlink (target ${target}). Resolve manually and retry.`
1688
+ );
1689
+ }
1690
+ if (resolvedTarget.startsWith(ourRoot)) {
1691
+ unlinkSync(projectPath);
1692
+ kind = "was-symlink";
1693
+ } else {
1694
+ throw new Error(
1695
+ `${projectPath} is a symlink to ${target} (resolved: ${resolvedTarget}). Refusing to replace it \u2014 it doesn't live under ${ourRoot}. Resolve manually and retry.`
1696
+ );
1697
+ }
1698
+ } else {
1699
+ const backupPath = projectPath + BACKUP_SUFFIX;
1700
+ if (existsSync3(backupPath)) {
1701
+ throw new Error(
1702
+ `${backupPath} already exists from a previous run. Remove it manually if you're sure it's stale, then retry.`
1703
+ );
1704
+ }
1705
+ renameSync2(projectPath, backupPath);
1706
+ kind = "had-file";
1707
+ }
1708
+ }
1709
+ symlinkSync(personaPath, projectPath, "file");
1710
+ return kind;
1711
+ }
1712
+ function restoreSwapped(projectPath, kind) {
1713
+ if (lstatSafe(projectPath)) {
1714
+ const stat = lstatSync(projectPath);
1715
+ if (stat.isSymbolicLink()) {
1716
+ unlinkSync(projectPath);
1717
+ } else {
1718
+ return;
1719
+ }
1720
+ }
1721
+ if (kind === "had-file") {
1722
+ const backupPath = projectPath + BACKUP_SUFFIX;
1723
+ if (existsSync3(backupPath)) {
1724
+ renameSync2(backupPath, projectPath);
1725
+ }
1726
+ }
1727
+ }
1728
+ function lstatSafe(path) {
1729
+ try {
1730
+ lstatSync(path);
1731
+ return true;
1732
+ } catch {
1733
+ return false;
1734
+ }
1735
+ }
1736
+
1737
+ // src/commands/impersonate.ts
1738
+ var SWAP_FILES = ["CLAUDE.md", ".mcp.json"];
1739
+ var AGENT_IMPERSONATION_HEADER = "X-Agent-Impersonation";
1740
+ var REDEEM_TOKEN_RE = /^[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4}$/i;
1741
+ async function impersonateConnectCommand(token, options = {}) {
1742
+ requireImpersonateEnabled();
1743
+ const json = isJsonMode();
1744
+ const shouldLaunchClaude = !options.noLaunch && !json;
1745
+ if (!REDEEM_TOKEN_RE.test(token)) {
1746
+ const msg = "Token is not in the expected XXXX-XXXX format. Copy the full `agt impersonate connect <token>` command from the webapp.";
1747
+ if (json) jsonOutput({ ok: false, error: msg });
1748
+ else error(msg);
1749
+ process.exitCode = 1;
1750
+ return;
1751
+ }
1752
+ const existing = readActiveManifest();
1753
+ if (existing) {
1754
+ const msg = `An impersonation session is already active (${existing.code_name}). Run \`agt impersonate exit\` first.`;
1755
+ if (json) jsonOutput({ ok: false, error: msg });
1756
+ else error(msg);
1757
+ process.exitCode = 1;
1758
+ return;
1759
+ }
1760
+ if (!json) console.log(chalk10.bold("\nAugmented \u2014 Impersonate\n"));
1761
+ const spinner = ora10({
1762
+ text: "Redeeming token\u2026",
1763
+ isSilent: json
1764
+ });
1765
+ spinner.start();
1766
+ const host2 = getHost();
1767
+ let bundle;
1768
+ try {
1769
+ const res = await fetch(`${host2}/impersonate/agent/redeem`, {
1770
+ method: "POST",
1771
+ headers: { "Content-Type": "application/json" },
1772
+ body: JSON.stringify({ redeem_token: token })
1773
+ });
1774
+ if (!res.ok) {
1775
+ const body = await res.json().catch(() => ({}));
1776
+ const detail = body["error"] ?? `HTTP ${res.status}`;
1777
+ throw new Error(`${detail} (HTTP ${res.status})`);
1778
+ }
1779
+ bundle = await res.json();
1780
+ } catch (err) {
1781
+ spinner.fail("Failed to redeem token.");
1782
+ const msg = err instanceof Error ? err.message : String(err);
1783
+ if (json) jsonOutput({ ok: false, error: msg });
1784
+ else error(msg);
1785
+ process.exitCode = 1;
1786
+ return;
1787
+ }
1788
+ spinner.text = "Writing persona files\u2026";
1789
+ const personaDir = ensureCodeNameDir(bundle.agent.code_name);
1790
+ writeFileSync5(
1791
+ join7(personaDir, "CLAUDE.md"),
1792
+ bundle.artifacts["CLAUDE.md"]
1793
+ );
1794
+ writeFileSync5(
1795
+ join7(personaDir, ".mcp.json"),
1796
+ bundle.artifacts[".mcp.json"]
1797
+ );
1798
+ spinner.text = "Swapping persona files\u2026";
1799
+ const projectCwd = process.cwd();
1800
+ const backups = {};
1801
+ const swapped = [];
1802
+ try {
1803
+ for (const file of SWAP_FILES) {
1804
+ const projectPath = join7(projectCwd, file);
1805
+ const kind = swapInPersonaFile(projectPath, join7(personaDir, file));
1806
+ backups[file] = kind;
1807
+ swapped.push({ file, kind });
1808
+ }
1809
+ const manifest = {
1810
+ code_name: bundle.agent.code_name,
1811
+ agent_id: bundle.agent.agent_id,
1812
+ team_id: bundle.agent.team_id,
1813
+ token: bundle.token,
1814
+ expires_at: bundle.expires_at,
1815
+ session_id: bundle.session_id,
1816
+ minted_at: (/* @__PURE__ */ new Date()).toISOString(),
1817
+ project_cwd: projectCwd,
1818
+ host: host2,
1819
+ backups
1820
+ };
1821
+ writeActiveManifest(manifest);
1822
+ } catch (err) {
1823
+ for (const { file, kind } of [...swapped].reverse()) {
1824
+ try {
1825
+ restoreSwapped(join7(projectCwd, file), kind);
1826
+ } catch {
1827
+ }
1828
+ }
1829
+ spinner.fail("Failed to enter impersonation; rolled back changes.");
1830
+ throw err;
1831
+ }
1832
+ spinner.stop();
1833
+ if (json) {
1834
+ jsonOutput({
1835
+ ok: true,
1836
+ code_name: bundle.agent.code_name,
1837
+ agent_id: bundle.agent.agent_id,
1838
+ session_id: bundle.session_id,
1839
+ expires_at: bundle.expires_at,
1840
+ project_cwd: projectCwd,
1841
+ host: host2,
1842
+ swapped_files: SWAP_FILES
1843
+ });
1844
+ return;
1845
+ }
1846
+ success(`Impersonating ${chalk10.bold(bundle.agent.code_name)}`);
1847
+ console.log();
1848
+ console.log(` Agent ID: ${chalk10.dim(bundle.agent.agent_id)}`);
1849
+ console.log(` Team: ${chalk10.dim(bundle.agent.team_id)}`);
1850
+ console.log(` Session: ${chalk10.dim(bundle.session_id)}`);
1851
+ console.log(
1852
+ ` Expires: ${chalk10.dim(new Date(bundle.expires_at * 1e3).toISOString())}`
1853
+ );
1854
+ console.log(` Project: ${chalk10.dim(projectCwd)}`);
1855
+ console.log(` Host: ${chalk10.dim(host2)}`);
1856
+ console.log(` Swapped: ${chalk10.dim(SWAP_FILES.join(", "))}`);
1857
+ console.log();
1858
+ if (!shouldLaunchClaude) {
1859
+ info(
1860
+ "Restart Claude Code to pick up the agent's persona + MCP server set. Claude Code 2.1.152 does not honour `tools/list_changed` in-session (spike PoC, ENG-4733)."
1861
+ );
1862
+ console.log();
1863
+ info("When done: `agt impersonate exit`");
1864
+ return;
1865
+ }
1866
+ info("Launching Claude Code\u2026 (use `--no-launch` next time to skip)");
1867
+ console.log();
1868
+ await new Promise((resolve2) => {
1869
+ const child = spawn("claude", {
1870
+ stdio: "inherit",
1871
+ cwd: projectCwd
1872
+ });
1873
+ child.on("error", (err) => {
1874
+ if (err.code === "ENOENT") {
1875
+ error(
1876
+ `\`claude\` binary not found on PATH. Start Claude Code yourself from ${projectCwd}, or install the CLI from claude.ai/code.`
1877
+ );
1878
+ process.exitCode = 1;
1879
+ } else {
1880
+ error(`Failed to launch Claude Code: ${err.message}`);
1881
+ process.exitCode = 1;
1882
+ }
1883
+ resolve2();
1884
+ });
1885
+ child.on("exit", (code, signal) => {
1886
+ if (code !== null && code !== 0) process.exitCode = code;
1887
+ if (signal) process.exitCode = 130;
1888
+ resolve2();
1889
+ });
1890
+ });
1891
+ console.log();
1892
+ info("When done: `agt impersonate exit` (still active).");
1893
+ }
1894
+ async function impersonateCurrentCommand() {
1895
+ requireImpersonateEnabled();
1896
+ const json = isJsonMode();
1897
+ const manifest = readActiveManifest();
1898
+ if (!manifest) {
1899
+ if (json) jsonOutput({ ok: true, active: null });
1900
+ else info("No active impersonation.");
1901
+ return;
1902
+ }
1903
+ const expired = isExpired(manifest);
1904
+ if (json) {
1905
+ jsonOutput({
1906
+ ok: true,
1907
+ active: {
1908
+ code_name: manifest.code_name,
1909
+ agent_id: manifest.agent_id,
1910
+ team_id: manifest.team_id,
1911
+ session_id: manifest.session_id,
1912
+ minted_at: manifest.minted_at,
1913
+ expires_at: manifest.expires_at,
1914
+ expired,
1915
+ project_cwd: manifest.project_cwd,
1916
+ host: manifest.host
1917
+ }
1918
+ });
1919
+ return;
1920
+ }
1921
+ console.log();
1922
+ console.log(chalk10.bold(`Impersonating: ${manifest.code_name}`));
1923
+ console.log(` Agent ID: ${chalk10.dim(manifest.agent_id)}`);
1924
+ console.log(` Team: ${chalk10.dim(manifest.team_id)}`);
1925
+ console.log(` Session: ${chalk10.dim(manifest.session_id)}`);
1926
+ console.log(` Minted at: ${chalk10.dim(manifest.minted_at)}`);
1927
+ console.log(
1928
+ ` Expires at: ${chalk10.dim(new Date(manifest.expires_at * 1e3).toISOString())} ` + (expired ? chalk10.red("(EXPIRED \u2014 run `agt impersonate exit`)") : "")
1929
+ );
1930
+ console.log(` Project: ${chalk10.dim(manifest.project_cwd)}`);
1931
+ console.log(` Host: ${chalk10.dim(manifest.host)}`);
1932
+ console.log();
1933
+ }
1934
+ async function impersonateExitCommand() {
1935
+ requireImpersonateEnabled();
1936
+ const json = isJsonMode();
1937
+ const manifest = readActiveManifest();
1938
+ if (!manifest) {
1939
+ if (json) jsonOutput({ ok: true, was_active: false });
1940
+ else info("No active impersonation to exit.");
1941
+ return;
1942
+ }
1943
+ let stopOk = true;
1944
+ let stopDetail = null;
1945
+ try {
1946
+ if (process.env["AGT_API_KEY"]) {
1947
+ await api.post("/impersonate/agent/stop", void 0, {
1948
+ [AGENT_IMPERSONATION_HEADER]: manifest.token
1949
+ });
1950
+ } else {
1951
+ const res = await fetch(`${manifest.host}/impersonate/agent/stop`, {
1952
+ method: "POST",
1953
+ headers: {
1954
+ "Content-Type": "application/json",
1955
+ [AGENT_IMPERSONATION_HEADER]: manifest.token
1956
+ }
1957
+ });
1958
+ if (!res.ok) {
1959
+ const body = await res.json().catch(() => ({}));
1960
+ const detail = body["error"] ?? `HTTP ${res.status}`;
1961
+ stopOk = false;
1962
+ stopDetail = `${detail} (HTTP ${res.status})`;
1963
+ }
1964
+ }
1965
+ } catch (err) {
1966
+ stopOk = false;
1967
+ stopDetail = err instanceof ApiError ? `${err.message} (HTTP ${err.status})` : err instanceof Error ? err.message : String(err);
1968
+ }
1969
+ const restored = [];
1970
+ for (const [file, kind] of Object.entries(manifest.backups)) {
1971
+ const projectPath = join7(manifest.project_cwd, file);
1972
+ try {
1973
+ restoreSwapped(projectPath, kind);
1974
+ restored.push(file);
1975
+ } catch (err) {
1976
+ const msg = err instanceof Error ? err.message : String(err);
1977
+ if (!json) error(`Failed to restore ${file}: ${msg}`);
1978
+ }
1979
+ }
1980
+ clearActiveManifest();
1981
+ if (json) {
1982
+ jsonOutput({
1983
+ ok: true,
1984
+ was_active: true,
1985
+ session_id: manifest.session_id,
1986
+ stop_acknowledged: stopOk,
1987
+ stop_detail: stopDetail,
1988
+ restored
1989
+ });
1990
+ return;
1991
+ }
1992
+ success(`Exited impersonation: ${manifest.code_name}`);
1993
+ if (restored.length > 0) {
1994
+ info(`Restored: ${restored.join(", ")}`);
1995
+ }
1996
+ if (!stopOk) {
1997
+ info(`Note: server-side stop not acknowledged (${stopDetail}). Token will expire naturally.`);
1998
+ }
1999
+ info("Restart Claude Code to pick up your original persona.");
2000
+ }
2001
+
2002
+ // src/commands/drift.ts
2003
+ import chalk11 from "chalk";
2004
+ import ora11 from "ora";
1558
2005
 
1559
2006
  // ../../packages/core/dist/drift/live-state-reader.js
1560
2007
  import { readFile } from "fs/promises";
1561
2008
  import { createHash } from "crypto";
1562
- import { join as join6 } from "path";
2009
+ import { join as join8 } from "path";
1563
2010
  import JSON5 from "json5";
1564
2011
  async function hashFile(filePath) {
1565
2012
  try {
@@ -1583,8 +2030,8 @@ async function readLiveState(options) {
1583
2030
  const toolsFile = trackedFiles.find((f) => f.includes("TOOLS")) ?? "TOOLS.md";
1584
2031
  const [frameworkConfig, charterHash, toolsHash] = await Promise.all([
1585
2032
  readJsonFile(options.configPath),
1586
- hashFile(join6(options.teamDir, charterFile)),
1587
- hashFile(join6(options.teamDir, toolsFile))
2033
+ hashFile(join8(options.teamDir, charterFile)),
2034
+ hashFile(join8(options.teamDir, toolsFile))
1588
2035
  ]);
1589
2036
  return {
1590
2037
  frameworkConfig,
@@ -1599,15 +2046,15 @@ var KEBAB_CASE_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
1599
2046
  function severityColor(severity) {
1600
2047
  switch (severity) {
1601
2048
  case "critical":
1602
- return chalk10.red(severity);
2049
+ return chalk11.red(severity);
1603
2050
  case "warning":
1604
- return chalk10.yellow(severity);
2051
+ return chalk11.yellow(severity);
1605
2052
  default:
1606
- return chalk10.dim(severity);
2053
+ return chalk11.dim(severity);
1607
2054
  }
1608
2055
  }
1609
2056
  function printDriftReport(report) {
1610
- console.log(chalk10.bold(`
2057
+ console.log(chalk11.bold(`
1611
2058
  Drift Report: ${report.codeName}
1612
2059
  `));
1613
2060
  info(`Agent ID: ${report.agentId}`);
@@ -1636,7 +2083,7 @@ async function driftCheckCommand(codeName, opts) {
1636
2083
  return;
1637
2084
  }
1638
2085
  const useJson = opts.json || isJsonMode();
1639
- const spinner = ora10({ text: `Checking drift for "${codeName}"\u2026`, isSilent: useJson });
2086
+ const spinner = ora11({ text: `Checking drift for "${codeName}"\u2026`, isSilent: useJson });
1640
2087
  spinner.start();
1641
2088
  try {
1642
2089
  const driftData = await api.get(`/agents/${encodeURIComponent(codeName)}/drift-data`);
@@ -1718,14 +2165,14 @@ async function driftWatchCommand(codeName, opts) {
1718
2165
  const trackedFiles = adapter.driftTrackedFiles();
1719
2166
  if (!useJson) {
1720
2167
  console.log(
1721
- chalk10.bold(`
2168
+ chalk11.bold(`
1722
2169
  Watching drift for "${codeName}" every ${intervalSec}s. Press Ctrl+C to stop.
1723
2170
  `)
1724
2171
  );
1725
2172
  }
1726
2173
  let previousFindingCount = -1;
1727
2174
  const runCheck = async () => {
1728
- const spinner = ora10({ text: `Checking drift for "${codeName}"\u2026`, isSilent: useJson });
2175
+ const spinner = ora11({ text: `Checking drift for "${codeName}"\u2026`, isSilent: useJson });
1729
2176
  spinner.start();
1730
2177
  try {
1731
2178
  const driftData = await api.get(`/agents/${encodeURIComponent(codeName)}/drift-data`);
@@ -1789,19 +2236,19 @@ Watching drift for "${codeName}" every ${intervalSec}s. Press Ctrl+C to stop.
1789
2236
  }, intervalSec * 1e3);
1790
2237
  process.on("SIGINT", () => {
1791
2238
  clearInterval(timer);
1792
- if (!useJson) console.log(chalk10.dim("\nStopped watching."));
2239
+ if (!useJson) console.log(chalk11.dim("\nStopped watching."));
1793
2240
  process.exit(0);
1794
2241
  });
1795
2242
  }
1796
2243
 
1797
2244
  // src/commands/host.ts
1798
- import chalk11 from "chalk";
1799
- import ora11 from "ora";
2245
+ import chalk12 from "chalk";
2246
+ import ora12 from "ora";
1800
2247
  async function hostListCommand() {
1801
2248
  const teamSlug = requireTeam();
1802
2249
  if (!teamSlug) return;
1803
2250
  const json = isJsonMode();
1804
- const spinner = ora11({ text: "Fetching hosts\u2026", isSilent: json });
2251
+ const spinner = ora12({ text: "Fetching hosts\u2026", isSilent: json });
1805
2252
  spinner.start();
1806
2253
  try {
1807
2254
  const data = await api.get("/hosts");
@@ -1819,10 +2266,10 @@ async function hostListCommand() {
1819
2266
  return;
1820
2267
  }
1821
2268
  const rows = data.hosts.map((h) => {
1822
- const status = h.status === "active" ? chalk11.green("active") : chalk11.red("decommissioned");
2269
+ const status = h.status === "active" ? chalk12.green("active") : chalk12.red("decommissioned");
1823
2270
  const agents = String(h.agents);
1824
- const lastSeen = h.last_seen_at ? new Date(h.last_seen_at).toLocaleDateString() : chalk11.dim("never");
1825
- const prefix = h.key_prefix ? `tlk_${h.key_prefix}\u2026` : chalk11.dim("none");
2271
+ const lastSeen = h.last_seen_at ? new Date(h.last_seen_at).toLocaleDateString() : chalk12.dim("never");
2272
+ const prefix = h.key_prefix ? `tlk_${h.key_prefix}\u2026` : chalk12.dim("none");
1826
2273
  return [h.name, status, agents, lastSeen, prefix];
1827
2274
  });
1828
2275
  table(["Name", "Status", "Agents", "Last Seen", "Key"], rows);
@@ -1849,14 +2296,14 @@ async function hostAssignCommand(hostName, agentCodeNames, opts) {
1849
2296
  process.exitCode = 1;
1850
2297
  return;
1851
2298
  }
1852
- const spinner = ora11({ text: "Assigning agents\u2026", isSilent: json });
2299
+ const spinner = ora12({ text: "Assigning agents\u2026", isSilent: json });
1853
2300
  spinner.start();
1854
2301
  try {
1855
2302
  await api.post(`/hosts/${encodeURIComponent(hostName)}/assign`, {
1856
2303
  agents: agentCodeNames,
1857
2304
  force: opts.force
1858
2305
  });
1859
- spinner.succeed(`Agents assigned to ${chalk11.bold(hostName)}.`);
2306
+ spinner.succeed(`Agents assigned to ${chalk12.bold(hostName)}.`);
1860
2307
  if (json) {
1861
2308
  jsonOutput({ ok: true, host: hostName, assigned: agentCodeNames });
1862
2309
  return;
@@ -1887,13 +2334,13 @@ async function hostUnassignCommand(hostName, agentCodeNames) {
1887
2334
  process.exitCode = 1;
1888
2335
  return;
1889
2336
  }
1890
- const spinner = ora11({ text: "Unassigning agents\u2026", isSilent: json });
2337
+ const spinner = ora12({ text: "Unassigning agents\u2026", isSilent: json });
1891
2338
  spinner.start();
1892
2339
  try {
1893
2340
  await api.post(`/hosts/${encodeURIComponent(hostName)}/unassign`, {
1894
2341
  agents: agentCodeNames
1895
2342
  });
1896
- spinner.succeed(`Agents unassigned from ${chalk11.bold(hostName)}.`);
2343
+ spinner.succeed(`Agents unassigned from ${chalk12.bold(hostName)}.`);
1897
2344
  if (json) {
1898
2345
  jsonOutput({ ok: true, host: hostName, unassigned: agentCodeNames });
1899
2346
  return;
@@ -1913,7 +2360,7 @@ async function hostUnassignCommand(hostName, agentCodeNames) {
1913
2360
  }
1914
2361
  async function hostAgentsCommand(hostName) {
1915
2362
  const json = isJsonMode();
1916
- const spinner = ora11({ text: "Fetching host agents\u2026", isSilent: json });
2363
+ const spinner = ora12({ text: "Fetching host agents\u2026", isSilent: json });
1917
2364
  spinner.start();
1918
2365
  try {
1919
2366
  const hostId = await getHostId();
@@ -1952,7 +2399,7 @@ async function hostAgentsCommand(hostName) {
1952
2399
  return;
1953
2400
  }
1954
2401
  const rows = agents.map((a) => {
1955
- const statusColor = a.status === "active" ? chalk11.green : chalk11.yellow;
2402
+ const statusColor = a.status === "active" ? chalk12.green : chalk12.yellow;
1956
2403
  return [
1957
2404
  a.code_name,
1958
2405
  a.display_name,
@@ -1975,11 +2422,11 @@ async function hostRotateKeyCommand(hostName) {
1975
2422
  const teamSlug = requireTeam();
1976
2423
  if (!teamSlug) return;
1977
2424
  const json = isJsonMode();
1978
- const spinner = ora11({ text: "Rotating host key\u2026", isSilent: json });
2425
+ const spinner = ora12({ text: "Rotating host key\u2026", isSilent: json });
1979
2426
  spinner.start();
1980
2427
  try {
1981
2428
  const data = await api.post(`/hosts/${encodeURIComponent(hostName)}/rotate-key`);
1982
- spinner.succeed(`Key rotated for ${chalk11.bold(hostName)}.`);
2429
+ spinner.succeed(`Key rotated for ${chalk12.bold(hostName)}.`);
1983
2430
  if (json) {
1984
2431
  jsonOutput({
1985
2432
  ok: true,
@@ -1989,12 +2436,12 @@ async function hostRotateKeyCommand(hostName) {
1989
2436
  return;
1990
2437
  }
1991
2438
  console.log();
1992
- info(`Host: ${chalk11.bold(hostName)}`);
2439
+ info(`Host: ${chalk12.bold(hostName)}`);
1993
2440
  info(`Prefix: ${data.key.prefix}`);
1994
2441
  console.log();
1995
- console.log(chalk11.yellow.bold(" Save this key now \u2014 it will not be shown again:"));
2442
+ console.log(chalk12.yellow.bold(" Save this key now \u2014 it will not be shown again:"));
1996
2443
  console.log();
1997
- console.log(` ${chalk11.green.bold(data.key.raw_key)}`);
2444
+ console.log(` ${chalk12.green.bold(data.key.raw_key)}`);
1998
2445
  console.log();
1999
2446
  } catch (err) {
2000
2447
  spinner.fail("Failed to rotate key.");
@@ -2010,11 +2457,11 @@ async function hostDecommissionCommand(hostName) {
2010
2457
  const teamSlug = requireTeam();
2011
2458
  if (!teamSlug) return;
2012
2459
  const json = isJsonMode();
2013
- const spinner = ora11({ text: "Decommissioning host\u2026", isSilent: json });
2460
+ const spinner = ora12({ text: "Decommissioning host\u2026", isSilent: json });
2014
2461
  spinner.start();
2015
2462
  try {
2016
2463
  await api.post(`/hosts/${encodeURIComponent(hostName)}/decommission`);
2017
- spinner.succeed(`Host "${chalk11.bold(hostName)}" decommissioned.`);
2464
+ spinner.succeed(`Host "${chalk12.bold(hostName)}" decommissioned.`);
2018
2465
  if (json) {
2019
2466
  jsonOutput({
2020
2467
  ok: true,
@@ -2024,7 +2471,7 @@ async function hostDecommissionCommand(hostName) {
2024
2471
  return;
2025
2472
  }
2026
2473
  info(`Host: ${hostName}`);
2027
- info(`Status: ${chalk11.red("decommissioned")}`);
2474
+ info(`Status: ${chalk12.red("decommissioned")}`);
2028
2475
  info("API key revoked. Agents remain assigned for audit visibility.");
2029
2476
  info("Reassign agents to another host with `agt host assign --force`.");
2030
2477
  } catch (err) {
@@ -2039,8 +2486,8 @@ async function hostDecommissionCommand(hostName) {
2039
2486
  }
2040
2487
 
2041
2488
  // src/commands/host-pair.ts
2042
- import { spawn, spawnSync } from "child_process";
2043
- import chalk12 from "chalk";
2489
+ import { spawn as spawn2, spawnSync } from "child_process";
2490
+ import chalk13 from "chalk";
2044
2491
  async function hostPairCommand(name, opts) {
2045
2492
  const teamSlug = requireTeam();
2046
2493
  if (!teamSlug) return;
@@ -2110,17 +2557,17 @@ async function hostPairCommand(name, opts) {
2110
2557
  });
2111
2558
  return;
2112
2559
  }
2113
- info(`Pairing Claude Code on ${chalk12.bold(name)} (${instanceId}, ${region})`);
2114
- info(`Local port ${chalk12.cyan(String(localPort))} will be forwarded to the host.`);
2560
+ info(`Pairing Claude Code on ${chalk13.bold(name)} (${instanceId}, ${region})`);
2561
+ info(`Local port ${chalk13.cyan(String(localPort))} will be forwarded to the host.`);
2115
2562
  console.log();
2116
- console.log(chalk12.dim("In the shell that opens, run:"));
2117
- console.log(` ${chalk12.cyan(`CLAUDE_CODE_OAUTH_PORT=${localPort} claude /login`)}`);
2118
- console.log(chalk12.dim("Then click the printed URL on this machine. The OAuth callback"));
2119
- console.log(chalk12.dim(`will reach Claude Code via the port-forward tunnel.`));
2563
+ console.log(chalk13.dim("In the shell that opens, run:"));
2564
+ console.log(` ${chalk13.cyan(`CLAUDE_CODE_OAUTH_PORT=${localPort} claude /login`)}`);
2565
+ console.log(chalk13.dim("Then click the printed URL on this machine. The OAuth callback"));
2566
+ console.log(chalk13.dim(`will reach Claude Code via the port-forward tunnel.`));
2120
2567
  console.log();
2121
- console.log(chalk12.dim("Exit the shell (Ctrl+D) when Claude Code reports successful login."));
2568
+ console.log(chalk13.dim("Exit the shell (Ctrl+D) when Claude Code reports successful login."));
2122
2569
  console.log();
2123
- const tunnel = spawn(
2570
+ const tunnel = spawn2(
2124
2571
  "aws",
2125
2572
  [
2126
2573
  "ssm",
@@ -2139,7 +2586,7 @@ async function hostPairCommand(name, opts) {
2139
2586
  tunnel.stderr?.on("data", (buf) => {
2140
2587
  const line = buf.toString().trim();
2141
2588
  if (line.startsWith("An error occurred")) {
2142
- console.error(chalk12.red(`[tunnel] ${line}`));
2589
+ console.error(chalk13.red(`[tunnel] ${line}`));
2143
2590
  }
2144
2591
  });
2145
2592
  await new Promise((r) => setTimeout(r, 1500));
@@ -2149,7 +2596,7 @@ async function hostPairCommand(name, opts) {
2149
2596
  return;
2150
2597
  }
2151
2598
  if (opts.noShell) {
2152
- console.log(chalk12.dim("--no-shell set; tunnel is running. Press Ctrl+C to exit."));
2599
+ console.log(chalk13.dim("--no-shell set; tunnel is running. Press Ctrl+C to exit."));
2153
2600
  await new Promise((resolve2) => {
2154
2601
  const onSignal = () => {
2155
2602
  terminate(tunnel);
@@ -2177,7 +2624,7 @@ function preflightAws() {
2177
2624
  }
2178
2625
  function runInteractive(cmd, args) {
2179
2626
  return new Promise((resolve2) => {
2180
- const child = spawn(cmd, args, { stdio: "inherit" });
2627
+ const child = spawn2(cmd, args, { stdio: "inherit" });
2181
2628
  child.on("exit", (code) => resolve2(code ?? 0));
2182
2629
  child.on("error", () => resolve2(1));
2183
2630
  });
@@ -2193,15 +2640,15 @@ function terminate(child) {
2193
2640
  // src/commands/manager-watch.tsx
2194
2641
  import { useEffect, useState, useMemo } from "react";
2195
2642
  import { render, Box, Text, useApp, useInput } from "ink";
2196
- import { existsSync as existsSync2, readFileSync as readFileSync2, statSync, openSync, readSync, closeSync } from "fs";
2197
- import { homedir } from "os";
2198
- import { join as join7 } from "path";
2643
+ import { existsSync as existsSync4, readFileSync as readFileSync3, statSync, openSync, readSync, closeSync } from "fs";
2644
+ import { homedir as homedir3 } from "os";
2645
+ import { join as join9 } from "path";
2199
2646
  import { jsx, jsxs } from "react/jsx-runtime";
2200
2647
  var REFRESH_MS = 1e3;
2201
2648
  var LOG_TAIL_LINES = 200;
2202
2649
  var DETAIL_RECENT_LINES = 50;
2203
2650
  function managerWatchCommand(opts = {}) {
2204
- const configDir = opts.configDir ?? join7(homedir(), ".augmented");
2651
+ const configDir = opts.configDir ?? join9(homedir3(), ".augmented");
2205
2652
  const paths = getManagerPaths(configDir);
2206
2653
  const isTty = process.stdout.isTTY === true && process.stdin.isTTY === true;
2207
2654
  if (opts.noTui || !isTty) {
@@ -2225,15 +2672,15 @@ function managerWatchCommand(opts = {}) {
2225
2672
  }
2226
2673
  function readState(stateFile) {
2227
2674
  try {
2228
- if (!existsSync2(stateFile)) return null;
2229
- const raw = readFileSync2(stateFile, "utf-8");
2675
+ if (!existsSync4(stateFile)) return null;
2676
+ const raw = readFileSync3(stateFile, "utf-8");
2230
2677
  return JSON.parse(raw);
2231
2678
  } catch {
2232
2679
  return null;
2233
2680
  }
2234
2681
  }
2235
2682
  function tailLogFile(logFile, lines) {
2236
- if (!existsSync2(logFile)) return [];
2683
+ if (!existsSync4(logFile)) return [];
2237
2684
  try {
2238
2685
  const fileSize = statSync(logFile).size;
2239
2686
  if (fileSize === 0) return [];
@@ -2474,7 +2921,7 @@ function truncate(s, max) {
2474
2921
  return s.length > max ? `${s.slice(0, Math.max(0, max - 1))}\u2026` : s;
2475
2922
  }
2476
2923
  function streamLogFile(logFile) {
2477
- if (!existsSync2(logFile)) {
2924
+ if (!existsSync4(logFile)) {
2478
2925
  process.stderr.write(`No manager log found at ${logFile}.
2479
2926
  Start the manager first: agt manager start
2480
2927
  `);
@@ -2483,7 +2930,7 @@ Start the manager first: agt manager start
2483
2930
  }
2484
2931
  let lastSize = 0;
2485
2932
  try {
2486
- const initial = readFileSync2(logFile, "utf-8");
2933
+ const initial = readFileSync3(logFile, "utf-8");
2487
2934
  process.stdout.write(initial);
2488
2935
  lastSize = statSync(logFile).size;
2489
2936
  } catch (err) {
@@ -2518,16 +2965,16 @@ Start the manager first: agt manager start
2518
2965
  }
2519
2966
 
2520
2967
  // src/commands/agent.ts
2521
- import chalk13 from "chalk";
2968
+ import chalk14 from "chalk";
2522
2969
  import JSON52 from "json5";
2523
- import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
2524
- import { join as join8 } from "path";
2970
+ import { readFileSync as readFileSync4, existsSync as existsSync5 } from "fs";
2971
+ import { join as join10 } from "path";
2525
2972
  async function agentShowCommand(codeName, opts) {
2526
2973
  const json = isJsonMode();
2527
- const unifiedDir = join8(opts.configDir, codeName, "provision");
2528
- const legacyDir = join8(opts.configDir, codeName, "claudecode", "provision");
2529
- const agentDir = existsSync3(unifiedDir) ? unifiedDir : legacyDir;
2530
- const hasLocalConfig = existsSync3(agentDir);
2974
+ const unifiedDir = join10(opts.configDir, codeName, "provision");
2975
+ const legacyDir = join10(opts.configDir, codeName, "claudecode", "provision");
2976
+ const agentDir = existsSync5(unifiedDir) ? unifiedDir : legacyDir;
2977
+ const hasLocalConfig = existsSync5(agentDir);
2531
2978
  let apiChannels = null;
2532
2979
  let apiAgent = null;
2533
2980
  if (getApiKey()) {
@@ -2560,34 +3007,34 @@ async function agentShowCommand(codeName, opts) {
2560
3007
  let openclawConfig = null;
2561
3008
  let agentState = null;
2562
3009
  if (hasLocalConfig) {
2563
- const charterPath = join8(agentDir, "CHARTER.md");
2564
- if (existsSync3(charterPath)) {
2565
- const raw = readFileSync3(charterPath, "utf-8");
3010
+ const charterPath = join10(agentDir, "CHARTER.md");
3011
+ if (existsSync5(charterPath)) {
3012
+ const raw = readFileSync4(charterPath, "utf-8");
2566
3013
  const parsed = extractFrontmatter(raw);
2567
3014
  if (parsed.frontmatter) {
2568
3015
  charter = parsed.frontmatter;
2569
3016
  }
2570
3017
  }
2571
- const toolsPath = join8(agentDir, "TOOLS.md");
2572
- if (existsSync3(toolsPath)) {
2573
- const raw = readFileSync3(toolsPath, "utf-8");
3018
+ const toolsPath = join10(agentDir, "TOOLS.md");
3019
+ if (existsSync5(toolsPath)) {
3020
+ const raw = readFileSync4(toolsPath, "utf-8");
2574
3021
  const parsed = extractFrontmatter(raw);
2575
3022
  if (parsed.frontmatter) {
2576
3023
  tools = parsed.frontmatter;
2577
3024
  }
2578
3025
  }
2579
- const openclawPath = join8(agentDir, "openclaw.json5");
2580
- if (existsSync3(openclawPath)) {
3026
+ const openclawPath = join10(agentDir, "openclaw.json5");
3027
+ if (existsSync5(openclawPath)) {
2581
3028
  try {
2582
- const raw = readFileSync3(openclawPath, "utf-8");
3029
+ const raw = readFileSync4(openclawPath, "utf-8");
2583
3030
  openclawConfig = JSON52.parse(raw);
2584
3031
  } catch {
2585
3032
  }
2586
3033
  }
2587
- const statePath = join8(opts.configDir, "manager-state.json");
2588
- if (existsSync3(statePath)) {
3034
+ const statePath = join10(opts.configDir, "manager-state.json");
3035
+ if (existsSync5(statePath)) {
2589
3036
  try {
2590
- const raw = readFileSync3(statePath, "utf-8");
3037
+ const raw = readFileSync4(statePath, "utf-8");
2591
3038
  const state = JSON.parse(raw);
2592
3039
  agentState = state.agents?.find((a) => a.codeName === codeName) ?? null;
2593
3040
  } catch {
@@ -2654,7 +3101,7 @@ async function agentShowCommand(codeName, opts) {
2654
3101
  return;
2655
3102
  }
2656
3103
  const displayName = apiAgent?.display_name ?? charter?.display_name ?? codeName;
2657
- console.log(chalk13.bold(`
3104
+ console.log(chalk14.bold(`
2658
3105
  Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "\n");
2659
3106
  if (charter || apiAgent) {
2660
3107
  const agentId = apiAgent?.agent_id ?? charter?.agent_id;
@@ -2686,7 +3133,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
2686
3133
  info("No agent metadata available");
2687
3134
  }
2688
3135
  const filtered = opts.allChannels ? channelRows : channelRows.filter((c) => c.enabled);
2689
- console.log(chalk13.bold("\nChannels:"));
3136
+ console.log(chalk14.bold("\nChannels:"));
2690
3137
  if (filtered.length === 0) {
2691
3138
  info("(none enabled)");
2692
3139
  } else {
@@ -2702,7 +3149,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
2702
3149
  );
2703
3150
  }
2704
3151
  if (tools) {
2705
- console.log(chalk13.bold("\nTools:"));
3152
+ console.log(chalk14.bold("\nTools:"));
2706
3153
  if (tools.tools.length === 0) {
2707
3154
  info("(none configured)");
2708
3155
  } else {
@@ -2713,7 +3160,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
2713
3160
  }
2714
3161
  if (tools.global_controls) {
2715
3162
  const gc = tools.global_controls;
2716
- console.log(chalk13.bold("\nGlobal Controls:"));
3163
+ console.log(chalk14.bold("\nGlobal Controls:"));
2717
3164
  info(`Network: ${gc.default_network_policy === "deny" ? "deny-by-default" : "allow-by-default"}`);
2718
3165
  info(`Timeout: ${gc.default_timeout_ms}ms`);
2719
3166
  info(`Rate: ${gc.default_rate_limit_rpm} rpm`);
@@ -2729,8 +3176,8 @@ function formatTimestamp(iso) {
2729
3176
  }
2730
3177
 
2731
3178
  // src/commands/kanban-recurring.ts
2732
- import chalk14 from "chalk";
2733
- import ora12 from "ora";
3179
+ import chalk15 from "chalk";
3180
+ import ora13 from "ora";
2734
3181
  async function resolveAgentId(codeName) {
2735
3182
  try {
2736
3183
  const data = await api.get(`/agents/${codeName}`);
@@ -2741,10 +3188,10 @@ async function resolveAgentId(codeName) {
2741
3188
  }
2742
3189
  }
2743
3190
  function priorityLabel(p) {
2744
- return p === 1 ? chalk14.red("HIGH") : p === 3 ? chalk14.dim("LOW") : chalk14.yellow("MED");
3191
+ return p === 1 ? chalk15.red("HIGH") : p === 3 ? chalk15.dim("LOW") : chalk15.yellow("MED");
2745
3192
  }
2746
3193
  function formatSpawnTime(isoDate, timezone) {
2747
- if (!isoDate) return chalk14.dim("\u2014");
3194
+ if (!isoDate) return chalk15.dim("\u2014");
2748
3195
  try {
2749
3196
  return new Intl.DateTimeFormat("en-AU", {
2750
3197
  dateStyle: "medium",
@@ -2785,7 +3232,7 @@ async function kanbanRecurringAddCommand(title, opts) {
2785
3232
  return;
2786
3233
  }
2787
3234
  }
2788
- const spinner = ora12({ text: "Creating recurring template\u2026", isSilent: json });
3235
+ const spinner = ora13({ text: "Creating recurring template\u2026", isSilent: json });
2789
3236
  spinner.start();
2790
3237
  const agentId = await resolveAgentId(opts.agent);
2791
3238
  if (!agentId) {
@@ -2809,8 +3256,8 @@ async function kanbanRecurringAddCommand(title, opts) {
2809
3256
  jsonOutput({ ok: true, template: data.template });
2810
3257
  return;
2811
3258
  }
2812
- success(`Recurring task created: ${chalk14.bold(title)}`);
2813
- info(`Schedule: ${chalk14.cyan(data.template.natural_language ?? data.template.expression ?? data.template.every_interval ?? "")}`);
3259
+ success(`Recurring task created: ${chalk15.bold(title)}`);
3260
+ info(`Schedule: ${chalk15.cyan(data.template.natural_language ?? data.template.expression ?? data.template.every_interval ?? "")}`);
2814
3261
  info(`Next spawn: ${formatSpawnTime(data.template.next_spawn_at, data.template.timezone)}`);
2815
3262
  info(`Timezone: ${data.template.timezone}`);
2816
3263
  } catch (err) {
@@ -2827,7 +3274,7 @@ async function kanbanRecurringListCommand(opts) {
2827
3274
  const teamSlug = requireTeam();
2828
3275
  if (!teamSlug) return;
2829
3276
  const json = isJsonMode();
2830
- const spinner = ora12({ text: "Fetching recurring templates\u2026", isSilent: json });
3277
+ const spinner = ora13({ text: "Fetching recurring templates\u2026", isSilent: json });
2831
3278
  spinner.start();
2832
3279
  const agentId = await resolveAgentId(opts.agent);
2833
3280
  if (!agentId) {
@@ -2853,7 +3300,7 @@ async function kanbanRecurringListCommand(opts) {
2853
3300
  t.title,
2854
3301
  t.natural_language ?? t.expression ?? t.every_interval ?? "\u2014",
2855
3302
  priorityLabel(t.priority),
2856
- t.enabled ? chalk14.green("Active") : chalk14.dim("Disabled"),
3303
+ t.enabled ? chalk15.green("Active") : chalk15.dim("Disabled"),
2857
3304
  formatSpawnTime(t.next_spawn_at, t.timezone),
2858
3305
  String(t.spawn_count)
2859
3306
  ]);
@@ -2875,7 +3322,7 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
2875
3322
  const teamSlug = requireTeam();
2876
3323
  if (!teamSlug) return;
2877
3324
  const json = isJsonMode();
2878
- const spinner = ora12({ text: "Disabling recurring template\u2026", isSilent: json });
3325
+ const spinner = ora13({ text: "Disabling recurring template\u2026", isSilent: json });
2879
3326
  spinner.start();
2880
3327
  const agentId = await resolveAgentId(opts.agent);
2881
3328
  if (!agentId) {
@@ -2910,7 +3357,7 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
2910
3357
  if (json) {
2911
3358
  jsonOutput({ ok: true, id: match.id, title: match.title, enabled: false });
2912
3359
  } else {
2913
- success(`Disabled: ${chalk14.bold(match.title)}`);
3360
+ success(`Disabled: ${chalk15.bold(match.title)}`);
2914
3361
  }
2915
3362
  } catch (err) {
2916
3363
  spinner.fail("Failed to disable recurring template");
@@ -2924,24 +3371,24 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
2924
3371
  }
2925
3372
 
2926
3373
  // src/commands/setup.ts
2927
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, accessSync, constants as fsConstants } from "fs";
2928
- import { join as join9, dirname } from "path";
2929
- import { homedir as homedir2 } from "os";
2930
- import chalk15 from "chalk";
2931
- import ora13 from "ora";
3374
+ import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, accessSync, constants as fsConstants } from "fs";
3375
+ import { join as join11, dirname } from "path";
3376
+ import { homedir as homedir4 } from "os";
3377
+ import chalk16 from "chalk";
3378
+ import ora14 from "ora";
2932
3379
  function detectShellProfile() {
2933
3380
  const shell = process.env["SHELL"] ?? "";
2934
- const home = homedir2();
3381
+ const home = homedir4();
2935
3382
  if (shell.includes("zsh")) {
2936
- return join9(home, ".zshrc");
3383
+ return join11(home, ".zshrc");
2937
3384
  }
2938
3385
  if (shell.includes("fish")) {
2939
- const fishConfig = join9(home, ".config", "fish", "config.fish");
3386
+ const fishConfig = join11(home, ".config", "fish", "config.fish");
2940
3387
  return fishConfig;
2941
3388
  }
2942
- const bashrc = join9(home, ".bashrc");
2943
- if (existsSync4(bashrc)) return bashrc;
2944
- return join9(home, ".bash_profile");
3389
+ const bashrc = join11(home, ".bashrc");
3390
+ if (existsSync6(bashrc)) return bashrc;
3391
+ return join11(home, ".bash_profile");
2945
3392
  }
2946
3393
  function maybeWriteSystemWideEnv(apiUrl, apiKey, consoleUrl) {
2947
3394
  const empty = { etcEnvironment: false, profileD: false, bashrc: false };
@@ -2967,14 +3414,14 @@ function quoteForFishShell(value) {
2967
3414
  }
2968
3415
  function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
2969
3416
  const envPath = "/etc/environment";
2970
- if (!existsSync4(envPath)) return false;
3417
+ if (!existsSync6(envPath)) return false;
2971
3418
  try {
2972
3419
  accessSync(envPath, fsConstants.W_OK);
2973
3420
  } catch {
2974
3421
  return false;
2975
3422
  }
2976
3423
  try {
2977
- const current = readFileSync4(envPath, "utf-8");
3424
+ const current = readFileSync5(envPath, "utf-8");
2978
3425
  const stripped = current.split(/\r?\n/).filter((line) => !/^\s*(?:export\s+)?AGT_(?:HOST|API_KEY|CONSOLE_URL)=/.test(line)).join("\n");
2979
3426
  const base = stripped.endsWith("\n") || stripped.length === 0 ? stripped : `${stripped}
2980
3427
  `;
@@ -2985,7 +3432,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
2985
3432
  if (consoleUrl) lines.push(`AGT_CONSOLE_URL=${quoteForEtcEnvironment(consoleUrl)}`);
2986
3433
  const appended = `${base}${lines.join("\n")}
2987
3434
  `;
2988
- writeFileSync4(envPath, appended, { mode: 420 });
3435
+ writeFileSync6(envPath, appended, { mode: 420 });
2989
3436
  return true;
2990
3437
  } catch {
2991
3438
  return false;
@@ -2993,7 +3440,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
2993
3440
  }
2994
3441
  function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
2995
3442
  const profileD = "/etc/profile.d";
2996
- if (!existsSync4(profileD)) return false;
3443
+ if (!existsSync6(profileD)) return false;
2997
3444
  try {
2998
3445
  accessSync(profileD, fsConstants.W_OK);
2999
3446
  } catch {
@@ -3008,7 +3455,7 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
3008
3455
  ];
3009
3456
  if (consoleUrl) lines.push(`export AGT_CONSOLE_URL=${quoteForPosixShell(consoleUrl)}`);
3010
3457
  lines.push("");
3011
- writeFileSync4(scriptPath, lines.join("\n"), { mode: 420 });
3458
+ writeFileSync6(scriptPath, lines.join("\n"), { mode: 420 });
3012
3459
  return true;
3013
3460
  } catch {
3014
3461
  return false;
@@ -3016,14 +3463,14 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
3016
3463
  }
3017
3464
  function ensureBashrcSourcesProfileD() {
3018
3465
  const bashrc = "/etc/bashrc";
3019
- if (!existsSync4(bashrc)) return false;
3466
+ if (!existsSync6(bashrc)) return false;
3020
3467
  try {
3021
3468
  accessSync(bashrc, fsConstants.W_OK);
3022
3469
  } catch {
3023
3470
  return false;
3024
3471
  }
3025
3472
  try {
3026
- const current = readFileSync4(bashrc, "utf-8");
3473
+ const current = readFileSync5(bashrc, "utf-8");
3027
3474
  const marker = "# Augmented (agt) \u2014 source system-wide AGT env";
3028
3475
  if (current.includes(marker)) return true;
3029
3476
  const snippet = [
@@ -3034,7 +3481,7 @@ function ensureBashrcSourcesProfileD() {
3034
3481
  "fi",
3035
3482
  ""
3036
3483
  ].join("\n");
3037
- writeFileSync4(bashrc, current + snippet);
3484
+ writeFileSync6(bashrc, current + snippet);
3038
3485
  return true;
3039
3486
  } catch {
3040
3487
  return false;
@@ -3081,10 +3528,10 @@ async function setupCommand(token) {
3081
3528
  if (!apiUrl) {
3082
3529
  apiUrl = "https://api.augmented.team";
3083
3530
  if (!json) {
3084
- info(`No AGT_HOST set \u2014 using default: ${chalk15.bold(apiUrl)}`);
3531
+ info(`No AGT_HOST set \u2014 using default: ${chalk16.bold(apiUrl)}`);
3085
3532
  }
3086
3533
  }
3087
- const spinner = ora13({ text: "Exchanging provisioning token\u2026", isSilent: json });
3534
+ const spinner = ora14({ text: "Exchanging provisioning token\u2026", isSilent: json });
3088
3535
  spinner.start();
3089
3536
  let setupResult;
3090
3537
  try {
@@ -3112,17 +3559,17 @@ async function setupCommand(token) {
3112
3559
  const finalApiUrl = setupResult.api_url || apiUrl;
3113
3560
  process.env["AGT_HOST"] = finalApiUrl;
3114
3561
  process.env["AGT_API_KEY"] = setupResult.api_key;
3115
- const verifySpinner = ora13({ text: "Verifying connection\u2026", isSilent: json });
3562
+ const verifySpinner = ora14({ text: "Verifying connection\u2026", isSilent: json });
3116
3563
  verifySpinner.start();
3117
3564
  try {
3118
3565
  const exchange = await exchangeApiKey(setupResult.api_key);
3119
3566
  verifySpinner.succeed("Connection verified");
3120
3567
  if (!json) {
3121
- info(`Host: ${chalk15.bold(setupResult.host_name)}`);
3568
+ info(`Host: ${chalk16.bold(setupResult.host_name)}`);
3122
3569
  info(`Host ID: ${exchange.hostId}`);
3123
- info(`Team: ${chalk15.bold(exchange.teamSlug ?? setupResult.team_slug ?? "unknown")}`);
3570
+ info(`Team: ${chalk16.bold(exchange.teamSlug ?? setupResult.team_slug ?? "unknown")}`);
3124
3571
  if (exchange.userEmail) {
3125
- info(`User: ${chalk15.bold(exchange.userEmail)}`);
3572
+ info(`User: ${chalk16.bold(exchange.userEmail)}`);
3126
3573
  }
3127
3574
  }
3128
3575
  } catch (err) {
@@ -3150,11 +3597,11 @@ async function setupCommand(token) {
3150
3597
  }
3151
3598
  const exportLines = buildExportLines(shell, finalApiUrl, setupResult.api_key, consoleUrl);
3152
3599
  const profileDir = dirname(profilePath);
3153
- if (!existsSync4(profileDir)) {
3154
- mkdirSync4(profileDir, { recursive: true });
3600
+ if (!existsSync6(profileDir)) {
3601
+ mkdirSync5(profileDir, { recursive: true });
3155
3602
  }
3156
3603
  const marker = "# Augmented (agt) host configuration";
3157
- const current = existsSync4(profilePath) ? readFileSync4(profilePath, "utf-8") : "";
3604
+ const current = existsSync6(profilePath) ? readFileSync5(profilePath, "utf-8") : "";
3158
3605
  let updated;
3159
3606
  if (current.includes(marker)) {
3160
3607
  updated = current.replace(
@@ -3167,10 +3614,10 @@ async function setupCommand(token) {
3167
3614
  } else {
3168
3615
  updated = current + exportLines;
3169
3616
  }
3170
- writeFileSync4(profilePath, updated.endsWith("\n") ? updated : `${updated}
3617
+ writeFileSync6(profilePath, updated.endsWith("\n") ? updated : `${updated}
3171
3618
  `);
3172
3619
  if (!json) {
3173
- success(`Environment variables written to ${chalk15.bold(profilePath)}`);
3620
+ success(`Environment variables written to ${chalk16.bold(profilePath)}`);
3174
3621
  }
3175
3622
  const sys = maybeWriteSystemWideEnv(finalApiUrl, setupResult.api_key, consoleUrl);
3176
3623
  const valueChannelsWritten = sys.etcEnvironment || sys.profileD;
@@ -3182,10 +3629,10 @@ async function setupCommand(token) {
3182
3629
  ].filter(Boolean).join(" + ");
3183
3630
  success(`System-wide env updated: ${channels2}`);
3184
3631
  }
3185
- const managerSpinner = ora13({ text: "Starting manager daemon\u2026", isSilent: json });
3632
+ const managerSpinner = ora14({ text: "Starting manager daemon\u2026", isSilent: json });
3186
3633
  managerSpinner.start();
3187
3634
  try {
3188
- const configDir = join9(homedir2(), ".augmented");
3635
+ const configDir = join11(homedir4(), ".augmented");
3189
3636
  const { pid } = startWatchdog({ intervalMs: 1e4, configDir, detached: true });
3190
3637
  managerSpinner.succeed(`Manager started (PID ${pid})`);
3191
3638
  } catch (err) {
@@ -3210,21 +3657,21 @@ async function setupCommand(token) {
3210
3657
  process.exit(0);
3211
3658
  } else {
3212
3659
  console.log();
3213
- console.log(chalk15.green.bold(" Setup complete!"));
3660
+ console.log(chalk16.green.bold(" Setup complete!"));
3214
3661
  console.log();
3215
3662
  if (setupResult.agents.length > 0) {
3216
- info(`Agents: ${setupResult.agents.map((a) => chalk15.cyan(a)).join(", ")}`);
3663
+ info(`Agents: ${setupResult.agents.map((a) => chalk16.cyan(a)).join(", ")}`);
3217
3664
  } else {
3218
3665
  info("No agents assigned yet. Assign agents in the dashboard or with: agt host assign");
3219
3666
  }
3220
3667
  console.log();
3221
- info(`Restart your shell or run: ${chalk15.bold(`source ${profilePath}`)}`);
3668
+ info(`Restart your shell or run: ${chalk16.bold(`source ${profilePath}`)}`);
3222
3669
  }
3223
3670
  }
3224
3671
 
3225
3672
  // src/commands/kanban.ts
3226
- import chalk16 from "chalk";
3227
- import ora14 from "ora";
3673
+ import chalk17 from "chalk";
3674
+ import ora15 from "ora";
3228
3675
  async function resolveAgentId2(codeName) {
3229
3676
  try {
3230
3677
  const data = await api.get(`/agents/${codeName}`);
@@ -3234,14 +3681,14 @@ async function resolveAgentId2(codeName) {
3234
3681
  }
3235
3682
  }
3236
3683
  function priorityLabel2(p) {
3237
- return p === 1 ? chalk16.red("HIGH") : p === 3 ? chalk16.dim("LOW") : chalk16.yellow("MED");
3684
+ return p === 1 ? chalk17.red("HIGH") : p === 3 ? chalk17.dim("LOW") : chalk17.yellow("MED");
3238
3685
  }
3239
3686
  function statusLabel(s) {
3240
3687
  const map = {
3241
- in_progress: chalk16.blue("In Progress"),
3242
- todo: chalk16.green("To Do"),
3243
- backlog: chalk16.dim("Backlog"),
3244
- done: chalk16.gray("Done")
3688
+ in_progress: chalk17.blue("In Progress"),
3689
+ todo: chalk17.green("To Do"),
3690
+ backlog: chalk17.dim("Backlog"),
3691
+ done: chalk17.gray("Done")
3245
3692
  };
3246
3693
  return map[s] ?? s;
3247
3694
  }
@@ -3249,7 +3696,7 @@ async function kanbanListCommand(opts) {
3249
3696
  const teamSlug = requireTeam();
3250
3697
  if (!teamSlug) return;
3251
3698
  const json = isJsonMode();
3252
- const spinner = ora14({ text: "Fetching kanban board\u2026", isSilent: json });
3699
+ const spinner = ora15({ text: "Fetching kanban board\u2026", isSilent: json });
3253
3700
  spinner.start();
3254
3701
  const agentId = await resolveAgentId2(opts.agent);
3255
3702
  if (!agentId) {
@@ -3277,7 +3724,7 @@ async function kanbanListCommand(opts) {
3277
3724
  item.estimated_minutes ? `~${item.estimated_minutes}min` : "",
3278
3725
  item.id.slice(0, 8)
3279
3726
  ]);
3280
- console.log(chalk16.bold(`
3727
+ console.log(chalk17.bold(`
3281
3728
  Kanban: ${opts.agent}
3282
3729
  `));
3283
3730
  table(["Pri", "Status", "Title", "Est", "ID"], rows);
@@ -3517,7 +3964,7 @@ function getAcpAgent(name) {
3517
3964
  }
3518
3965
 
3519
3966
  // ../../packages/core/dist/acp/client.js
3520
- import { spawn as spawn2 } from "child_process";
3967
+ import { spawn as spawn3 } from "child_process";
3521
3968
  function resolveAgentCommand(agentName) {
3522
3969
  const adapter = getAcpAgent(agentName);
3523
3970
  if (adapter) {
@@ -3533,7 +3980,7 @@ function resolveAgentCommand(agentName) {
3533
3980
  }
3534
3981
  async function runAcpx(args, options = {}) {
3535
3982
  return new Promise((resolve2) => {
3536
- const child = spawn2("acpx", args, {
3983
+ const child = spawn3("acpx", args, {
3537
3984
  cwd: options.cwd,
3538
3985
  stdio: ["pipe", "pipe", "pipe"],
3539
3986
  env: { ...process.env }
@@ -3733,10 +4180,10 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
3733
4180
 
3734
4181
  // src/commands/update.ts
3735
4182
  import { execFileSync, execSync } from "child_process";
3736
- import { existsSync as existsSync5, realpathSync } from "fs";
3737
- import chalk17 from "chalk";
3738
- import ora15 from "ora";
3739
- var cliVersion = true ? "0.26.2-eng5706.1" : "dev";
4183
+ import { existsSync as existsSync7, realpathSync as realpathSync2 } from "fs";
4184
+ import chalk18 from "chalk";
4185
+ import ora16 from "ora";
4186
+ var cliVersion = true ? "0.27.0" : "dev";
3740
4187
  async function fetchLatestVersion() {
3741
4188
  const host2 = getHost();
3742
4189
  if (!host2) return null;
@@ -3800,7 +4247,7 @@ function detectActiveSessions() {
3800
4247
  }
3801
4248
  function detectInstallSource() {
3802
4249
  try {
3803
- const resolved = realpathSync(process.argv[1] ?? "");
4250
+ const resolved = realpathSync2(process.argv[1] ?? "");
3804
4251
  if (/\/Cellar\/[^/]+\//.test(resolved)) {
3805
4252
  return "brew";
3806
4253
  }
@@ -3840,7 +4287,7 @@ function performUpdate(version) {
3840
4287
  function detectBrewOwner() {
3841
4288
  for (const prefix of ["/home/linuxbrew/.linuxbrew", "/opt/homebrew", "/usr/local"]) {
3842
4289
  const cellar = `${prefix}/Cellar`;
3843
- if (!existsSync5(cellar)) continue;
4290
+ if (!existsSync7(cellar)) continue;
3844
4291
  try {
3845
4292
  return execSync(`stat -c %U "${cellar}" 2>/dev/null || stat -f %Su "${cellar}"`, { encoding: "utf-8" }).trim() || null;
3846
4293
  } catch {
@@ -3850,7 +4297,7 @@ function detectBrewOwner() {
3850
4297
  }
3851
4298
  async function updateCommand(opts = {}) {
3852
4299
  const json = isJsonMode();
3853
- const spinner = ora15({ text: "Checking for updates\u2026", isSilent: json });
4300
+ const spinner = ora16({ text: "Checking for updates\u2026", isSilent: json });
3854
4301
  spinner.start();
3855
4302
  const versionInfo = await fetchLatestVersion();
3856
4303
  if (!versionInfo) {
@@ -3869,13 +4316,13 @@ async function updateCommand(opts = {}) {
3869
4316
  if (json) {
3870
4317
  jsonOutput({ ok: true, current: cliVersion, latest: versionInfo.latest, update_available: false });
3871
4318
  } else {
3872
- success(`You're on the latest version (${chalk17.bold(cliVersion)})`);
4319
+ success(`You're on the latest version (${chalk18.bold(cliVersion)})`);
3873
4320
  }
3874
4321
  return;
3875
4322
  }
3876
4323
  spinner.stop();
3877
4324
  if (!json) {
3878
- info(`Update available: ${chalk17.dim(cliVersion)} \u2192 ${chalk17.bold.green(versionInfo.latest)}`);
4325
+ info(`Update available: ${chalk18.dim(cliVersion)} \u2192 ${chalk18.bold.green(versionInfo.latest)}`);
3879
4326
  if (versionInfo.changelog_url) {
3880
4327
  info(`Changelog: ${versionInfo.changelog_url}`);
3881
4328
  }
@@ -3886,16 +4333,16 @@ async function updateCommand(opts = {}) {
3886
4333
  if (!json) {
3887
4334
  warn("Active processes detected:");
3888
4335
  if (managerPid) {
3889
- console.error(chalk17.yellow(` \u2022 Manager process running (PID ${managerPid})`));
4336
+ console.error(chalk18.yellow(` \u2022 Manager process running (PID ${managerPid})`));
3890
4337
  }
3891
4338
  if (tmuxSessions.length > 0) {
3892
- console.error(chalk17.yellow(` \u2022 ${tmuxSessions.length} active agent session(s): ${tmuxSessions.join(", ")}`));
4339
+ console.error(chalk18.yellow(` \u2022 ${tmuxSessions.length} active agent session(s): ${tmuxSessions.join(", ")}`));
3893
4340
  }
3894
4341
  console.error();
3895
4342
  warn("Updating while the manager is running will leave it on the old version until restarted.");
3896
4343
  warn("Active agent sessions will continue with stale MCP servers.");
3897
4344
  console.error();
3898
- info(`Run ${chalk17.bold("agt update --force")} to update anyway, then restart the manager.`);
4345
+ info(`Run ${chalk18.bold("agt update --force")} to update anyway, then restart the manager.`);
3899
4346
  } else {
3900
4347
  jsonOutput({
3901
4348
  ok: false,
@@ -3913,7 +4360,7 @@ async function updateCommand(opts = {}) {
3913
4360
  return;
3914
4361
  }
3915
4362
  }
3916
- const updateSpinner = ora15({ text: "Installing update\u2026", isSilent: json });
4363
+ const updateSpinner = ora16({ text: "Installing update\u2026", isSilent: json });
3917
4364
  updateSpinner.start();
3918
4365
  try {
3919
4366
  performUpdate(versionInfo.latest);
@@ -3927,8 +4374,8 @@ async function updateCommand(opts = {}) {
3927
4374
  updated: true
3928
4375
  });
3929
4376
  } else {
3930
- success(`Updated to ${chalk17.bold(versionInfo.latest)}`);
3931
- info(`If you have a running manager, restart it: ${chalk17.bold("agt manager stop && agt manager start")}`);
4377
+ success(`Updated to ${chalk18.bold(versionInfo.latest)}`);
4378
+ info(`If you have a running manager, restart it: ${chalk18.bold("agt manager stop && agt manager start")}`);
3932
4379
  }
3933
4380
  } catch (err) {
3934
4381
  updateSpinner.fail("Update failed");
@@ -3959,8 +4406,8 @@ async function checkForUpdateOnStartup() {
3959
4406
  if (!versionInfo) return;
3960
4407
  if (isNewerVersion(cliVersion, versionInfo.latest)) {
3961
4408
  console.error(
3962
- chalk17.yellow(`
3963
- Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${chalk17.bold("agt update")} to install.`) + chalk17.dim("\n Note: Restart the manager after updating.\n")
4409
+ chalk18.yellow(`
4410
+ Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${chalk18.bold("agt update")} to install.`) + chalk18.dim("\n Note: Restart the manager after updating.\n")
3964
4411
  );
3965
4412
  }
3966
4413
  } catch {
@@ -3968,11 +4415,11 @@ async function checkForUpdateOnStartup() {
3968
4415
  }
3969
4416
 
3970
4417
  // src/commands/integration.ts
3971
- import chalk18 from "chalk";
3972
- import ora16 from "ora";
4418
+ import chalk19 from "chalk";
4419
+ import ora17 from "ora";
3973
4420
  async function integrationListCommand() {
3974
4421
  const json = isJsonMode();
3975
- const spinner = ora16({ text: "Fetching integrations\u2026", isSilent: json }).start();
4422
+ const spinner = ora17({ text: "Fetching integrations\u2026", isSilent: json }).start();
3976
4423
  try {
3977
4424
  const data = await api.get("/integrations/bindings");
3978
4425
  spinner.stop();
@@ -3984,11 +4431,11 @@ async function integrationListCommand() {
3984
4431
  info("No integrations found for this team.");
3985
4432
  return;
3986
4433
  }
3987
- console.log(chalk18.bold("\nAvailable Integrations:\n"));
4434
+ console.log(chalk19.bold("\nAvailable Integrations:\n"));
3988
4435
  for (const p of data) {
3989
- const statusColor = p.status === "published" ? chalk18.green : p.status === "archived" ? chalk18.gray : chalk18.yellow;
4436
+ const statusColor = p.status === "published" ? chalk19.green : p.status === "archived" ? chalk19.gray : chalk19.yellow;
3990
4437
  console.log(
3991
- ` ${chalk18.bold(p.name)} ${chalk18.dim(`(${p.slug})`)} ${statusColor(p.status)} v${p.version} ${chalk18.dim(`${p.skills?.length ?? 0} skills, ${p.defined_scopes?.length ?? 0} scopes`)}`
4438
+ ` ${chalk19.bold(p.name)} ${chalk19.dim(`(${p.slug})`)} ${statusColor(p.status)} v${p.version} ${chalk19.dim(`${p.skills?.length ?? 0} skills, ${p.defined_scopes?.length ?? 0} scopes`)}`
3992
4439
  );
3993
4440
  }
3994
4441
  console.log();
@@ -3999,7 +4446,7 @@ async function integrationListCommand() {
3999
4446
  }
4000
4447
  async function integrationShowCommand(slug) {
4001
4448
  const json = isJsonMode();
4002
- const spinner = ora16({ text: "Fetching integration\u2026", isSilent: json }).start();
4449
+ const spinner = ora17({ text: "Fetching integration\u2026", isSilent: json }).start();
4003
4450
  try {
4004
4451
  const all = await api.get("/integrations/bindings");
4005
4452
  const integration2 = all.find((p) => p.slug === slug);
@@ -4015,21 +4462,21 @@ async function integrationShowCommand(slug) {
4015
4462
  jsonOutput({ integration: integration2, scopes });
4016
4463
  return;
4017
4464
  }
4018
- console.log(chalk18.bold(`
4019
- ${integration2.name}`), chalk18.dim(`(${integration2.slug})`));
4020
- if (integration2.description) console.log(chalk18.dim(integration2.description));
4465
+ console.log(chalk19.bold(`
4466
+ ${integration2.name}`), chalk19.dim(`(${integration2.slug})`));
4467
+ if (integration2.description) console.log(chalk19.dim(integration2.description));
4021
4468
  console.log();
4022
4469
  console.log(` Status: ${integration2.status} v${integration2.version}`);
4023
4470
  console.log(` Category: ${integration2.category}`);
4024
4471
  console.log(` Toolkits: ${integration2.required_toolkits.join(", ") || "none"}`);
4025
4472
  console.log(` Skills: ${integration2.skills?.length ?? 0}`);
4026
4473
  if (scopes.length > 0) {
4027
- console.log(chalk18.bold("\n Permission Scopes:\n"));
4474
+ console.log(chalk19.bold("\n Permission Scopes:\n"));
4028
4475
  for (const s of scopes) {
4029
- const roleColor = s.can_grant ? chalk18.green : chalk18.red;
4030
- const overrideTag = s.is_overridden ? chalk18.cyan(" [team override]") : "";
4476
+ const roleColor = s.can_grant ? chalk19.green : chalk19.red;
4477
+ const overrideTag = s.is_overridden ? chalk19.cyan(" [team override]") : "";
4031
4478
  console.log(
4032
- ` ${chalk18.bold(s.id)} ${s.name} min: ${roleColor(s.effective_min_role)}${overrideTag} ${s.can_grant ? chalk18.green("\u2713 grantable") : chalk18.red("\u2717 needs approval")}`
4479
+ ` ${chalk19.bold(s.id)} ${s.name} min: ${roleColor(s.effective_min_role)}${overrideTag} ${s.can_grant ? chalk19.green("\u2713 grantable") : chalk19.red("\u2717 needs approval")}`
4033
4480
  );
4034
4481
  }
4035
4482
  }
@@ -4041,7 +4488,7 @@ ${integration2.name}`), chalk18.dim(`(${integration2.slug})`));
4041
4488
  }
4042
4489
  async function integrationInstallCommand(slug, options) {
4043
4490
  const json = isJsonMode();
4044
- const spinner = ora16({ text: "Installing integration\u2026", isSilent: json }).start();
4491
+ const spinner = ora17({ text: "Installing integration\u2026", isSilent: json }).start();
4045
4492
  try {
4046
4493
  const all = await api.get("/integrations/bindings");
4047
4494
  const integration2 = all.find((p) => p.slug === slug);
@@ -4080,7 +4527,7 @@ async function integrationInstallCommand(slug, options) {
4080
4527
  const needsApproval = err.body["needs_approval"];
4081
4528
  error("Some scopes exceed your role ceiling:");
4082
4529
  for (const s of needsApproval) {
4083
- console.log(chalk18.yellow(` - ${s}`));
4530
+ console.log(chalk19.yellow(` - ${s}`));
4084
4531
  }
4085
4532
  info("To request elevated scopes, use the web dashboard or contact your team admin.");
4086
4533
  process.exitCode = 1;
@@ -4091,7 +4538,7 @@ async function integrationInstallCommand(slug, options) {
4091
4538
  }
4092
4539
  async function integrationUninstallCommand(slug, options) {
4093
4540
  const json = isJsonMode();
4094
- const spinner = ora16({ text: "Uninstalling integration\u2026", isSilent: json }).start();
4541
+ const spinner = ora17({ text: "Uninstalling integration\u2026", isSilent: json }).start();
4095
4542
  try {
4096
4543
  const all = await api.get("/integrations/bindings");
4097
4544
  const integration2 = all.find((p) => p.slug === slug);
@@ -4122,7 +4569,7 @@ async function integrationUninstallCommand(slug, options) {
4122
4569
  }
4123
4570
  async function integrationRequestsCommand() {
4124
4571
  const json = isJsonMode();
4125
- const spinner = ora16({ text: "Fetching scope requests\u2026", isSilent: json }).start();
4572
+ const spinner = ora17({ text: "Fetching scope requests\u2026", isSilent: json }).start();
4126
4573
  try {
4127
4574
  const requests = await api.get("/integrations/bindings/scope-requests");
4128
4575
  spinner.stop();
@@ -4134,10 +4581,10 @@ async function integrationRequestsCommand() {
4134
4581
  info("No pending scope requests.");
4135
4582
  return;
4136
4583
  }
4137
- console.log(chalk18.bold("\nPending Scope Requests:\n"));
4584
+ console.log(chalk19.bold("\nPending Scope Requests:\n"));
4138
4585
  for (const r of requests) {
4139
- console.log(` ${chalk18.bold(r.id)} scopes: ${r.requested_scopes.join(", ")}`);
4140
- if (r.reason) console.log(` reason: ${chalk18.dim(r.reason)}`);
4586
+ console.log(` ${chalk19.bold(r.id)} scopes: ${r.requested_scopes.join(", ")}`);
4587
+ if (r.reason) console.log(` reason: ${chalk19.dim(r.reason)}`);
4141
4588
  console.log(` status: ${r.status} requested: ${r.created_at}`);
4142
4589
  console.log();
4143
4590
  }
@@ -4148,7 +4595,7 @@ async function integrationRequestsCommand() {
4148
4595
  }
4149
4596
  async function integrationApproveCommand(requestId, options) {
4150
4597
  const json = isJsonMode();
4151
- const spinner = ora16({ text: "Approving request\u2026", isSilent: json }).start();
4598
+ const spinner = ora17({ text: "Approving request\u2026", isSilent: json }).start();
4152
4599
  try {
4153
4600
  const result = await api.put(`/integrations/bindings/scope-requests/${requestId}`, {
4154
4601
  status: "approved",
@@ -4167,7 +4614,7 @@ async function integrationApproveCommand(requestId, options) {
4167
4614
  }
4168
4615
  async function integrationDenyCommand(requestId, options) {
4169
4616
  const json = isJsonMode();
4170
- const spinner = ora16({ text: "Denying request\u2026", isSilent: json }).start();
4617
+ const spinner = ora17({ text: "Denying request\u2026", isSilent: json }).start();
4171
4618
  try {
4172
4619
  const result = await api.put(`/integrations/bindings/scope-requests/${requestId}`, {
4173
4620
  status: "denied",
@@ -4209,7 +4656,7 @@ async function integrationEnrolCommand(options) {
4209
4656
  const [secretKey, secretValue] = secrets[0];
4210
4657
  const credentials = { [secretKey]: secretValue };
4211
4658
  const authType = options.authType ?? (options.webhookSecret ? "webhook" : options.apiKey ? "api_key" : "oauth2");
4212
- const spinner = ora16({ text: `Enrolling ${options.def} at ${apiScope} scope\u2026`, isSilent: json }).start();
4659
+ const spinner = ora17({ text: `Enrolling ${options.def} at ${apiScope} scope\u2026`, isSilent: json }).start();
4213
4660
  try {
4214
4661
  let agentId;
4215
4662
  if (apiScope === "agent") {
@@ -4268,7 +4715,7 @@ function handleError(err) {
4268
4715
  }
4269
4716
 
4270
4717
  // src/bin/agt.ts
4271
- var cliVersion2 = true ? "0.26.2-eng5706.1" : "dev";
4718
+ var cliVersion2 = true ? "0.27.0" : "dev";
4272
4719
  var program = new Command();
4273
4720
  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");
4274
4721
  program.hook("preAction", (thisCommand) => {
@@ -4283,6 +4730,24 @@ var team = program.command("team").description("Manage teams");
4283
4730
  team.command("list").description("List teams you belong to").action(teamListCommand);
4284
4731
  team.command("create <name>").description("Create a new team and set it as active").action(teamCreateCommand);
4285
4732
  team.command("switch <slug>").description("Switch the active team").action(teamSwitchCommand);
4733
+ var impersonate = program.command("impersonate").description(
4734
+ "Operate as a managed agent locally (experimental, gated by AGT_IMPERSONATE_ENABLED)"
4735
+ );
4736
+ impersonate.command("connect <token>").description(
4737
+ "Redeem a XXXX-XXXX token from the webapp, render the agent's CLAUDE.md + .mcp.json, swap them into the current project, and launch Claude Code (use --no-launch to skip the launch)"
4738
+ ).option(
4739
+ "--no-launch",
4740
+ "Skip launching Claude Code after the swap (operator manages their own session)"
4741
+ ).action(
4742
+ (token, opts) => (
4743
+ // Commander negates --no-FLAG into opts.flag, so --no-launch arrives
4744
+ // as opts.launch === false. Translate to the command's noLaunch
4745
+ // option, defaulting to launching when the flag isn't passed.
4746
+ impersonateConnectCommand(token, { noLaunch: opts.launch === false })
4747
+ )
4748
+ );
4749
+ impersonate.command("current").description('Print the active impersonation (or "none")').action(impersonateCurrentCommand);
4750
+ impersonate.command("exit").description("End the active impersonation, restore project files, and notify the server").action(impersonateExitCommand);
4286
4751
  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);
4287
4752
  program.command("lint").argument("[path]", "Path to agent directory (default: all agents in .augmented/)").description("Lint CHARTER.md and TOOLS.md files").action(lintCommand);
4288
4753
  var channels = program.command("channels").description("Manage and inspect channel configuration");
@@ -4315,16 +4780,16 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
4315
4780
  })
4316
4781
  );
4317
4782
  var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
4318
- 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", join10(homedir3(), ".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);
4319
- manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join10(homedir3(), ".augmented")).action(managerStopCommand);
4320
- manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join10(homedir3(), ".augmented")).action(managerStatusCommand);
4321
- 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", join10(homedir3(), ".augmented")).option("--no-tui", "Skip the TUI and stream the manager log to stdout instead (CI / scripts)").action(managerWatchCommand);
4322
- 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", join10(homedir3(), ".augmented")).action(managerInstallCommand);
4783
+ 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", join12(homedir5(), ".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);
4784
+ manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join12(homedir5(), ".augmented")).action(managerStopCommand);
4785
+ manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join12(homedir5(), ".augmented")).action(managerStatusCommand);
4786
+ 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", join12(homedir5(), ".augmented")).option("--no-tui", "Skip the TUI and stream the manager log to stdout instead (CI / scripts)").action(managerWatchCommand);
4787
+ 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", join12(homedir5(), ".augmented")).action(managerInstallCommand);
4323
4788
  manager.command("uninstall").description("Remove the OS-level supervisor (launchctl unload + delete plist on macOS). Idempotent.").action(managerUninstallCommand);
4324
4789
  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);
4325
4790
  manager.command("uninstall-system-unit").description("Remove the system-level systemd unit (Linux, root). Idempotent. (ENG-4706)").action(managerUninstallSystemUnitCommand);
4326
4791
  var agent = program.command("agent").description("Inspect and manage agents");
4327
- agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join10(homedir3(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
4792
+ agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join12(homedir5(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
4328
4793
  var kanban = program.command("kanban").description("Manage agent kanban boards");
4329
4794
  kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
4330
4795
  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);