@phnx-labs/agents-cli 1.20.33 → 1.20.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +32 -2
  3. package/dist/commands/computer-actions.d.ts +15 -0
  4. package/dist/commands/computer-actions.js +120 -22
  5. package/dist/commands/computer.d.ts +23 -0
  6. package/dist/commands/computer.js +45 -3
  7. package/dist/commands/cost.js +17 -12
  8. package/dist/commands/doctor.d.ts +11 -0
  9. package/dist/commands/doctor.js +108 -14
  10. package/dist/commands/events.d.ts +16 -0
  11. package/dist/commands/events.js +173 -0
  12. package/dist/commands/exec.js +6 -1
  13. package/dist/commands/hosts.js +28 -24
  14. package/dist/commands/import.js +1 -1
  15. package/dist/commands/inspect.d.ts +2 -0
  16. package/dist/commands/inspect.js +54 -7
  17. package/dist/commands/logs.d.ts +17 -0
  18. package/dist/commands/logs.js +139 -0
  19. package/dist/commands/models.d.ts +3 -0
  20. package/dist/commands/models.js +27 -8
  21. package/dist/commands/permissions.js +9 -2
  22. package/dist/commands/repo.d.ts +34 -0
  23. package/dist/commands/repo.js +243 -65
  24. package/dist/commands/resource-view.d.ts +20 -0
  25. package/dist/commands/resource-view.js +90 -28
  26. package/dist/commands/rules.js +1 -1
  27. package/dist/commands/secrets-migrate.js +23 -11
  28. package/dist/commands/secrets.d.ts +20 -0
  29. package/dist/commands/secrets.js +93 -17
  30. package/dist/commands/sessions-resume.d.ts +2 -0
  31. package/dist/commands/sessions-resume.js +209 -0
  32. package/dist/commands/sessions-tail.d.ts +10 -0
  33. package/dist/commands/sessions-tail.js +11 -0
  34. package/dist/commands/sessions.d.ts +73 -1
  35. package/dist/commands/sessions.js +273 -53
  36. package/dist/commands/status.d.ts +12 -0
  37. package/dist/commands/status.js +81 -0
  38. package/dist/commands/teams.js +70 -6
  39. package/dist/commands/versions.js +2 -1
  40. package/dist/commands/view.d.ts +42 -0
  41. package/dist/commands/view.js +213 -83
  42. package/dist/commands/wallet.d.ts +6 -0
  43. package/dist/commands/wallet.js +22 -5
  44. package/dist/index.js +61 -32
  45. package/dist/lib/acp/harnesses.d.ts +1 -1
  46. package/dist/lib/acp/harnesses.js +2 -2
  47. package/dist/lib/agents.d.ts +12 -0
  48. package/dist/lib/agents.js +145 -41
  49. package/dist/lib/browser/cdp.js +5 -1
  50. package/dist/lib/browser/chrome.js +20 -0
  51. package/dist/lib/browser/drivers/ssh.d.ts +27 -0
  52. package/dist/lib/browser/drivers/ssh.js +94 -19
  53. package/dist/lib/browser/ipc.d.ts +3 -0
  54. package/dist/lib/browser/ipc.js +13 -9
  55. package/dist/lib/browser/service.js +71 -15
  56. package/dist/lib/daemon.d.ts +35 -0
  57. package/dist/lib/daemon.js +33 -5
  58. package/dist/lib/devices/connect.d.ts +3 -2
  59. package/dist/lib/devices/connect.js +5 -3
  60. package/dist/lib/doctor-diff.js +29 -2
  61. package/dist/lib/drift-sync.d.ts +43 -0
  62. package/dist/lib/drift-sync.js +179 -0
  63. package/dist/lib/events.d.ts +9 -2
  64. package/dist/lib/events.js +70 -11
  65. package/dist/lib/exec.d.ts +15 -0
  66. package/dist/lib/exec.js +43 -11
  67. package/dist/lib/hooks.js +8 -2
  68. package/dist/lib/hosts/dispatch.js +6 -7
  69. package/dist/lib/hosts/logs.d.ts +16 -0
  70. package/dist/lib/hosts/logs.js +45 -0
  71. package/dist/lib/hosts/progress.d.ts +66 -0
  72. package/dist/lib/hosts/progress.js +125 -17
  73. package/dist/lib/hosts/ready.d.ts +23 -2
  74. package/dist/lib/hosts/ready.js +35 -13
  75. package/dist/lib/hosts/reconcile.d.ts +53 -0
  76. package/dist/lib/hosts/reconcile.js +81 -0
  77. package/dist/lib/hosts/tasks.d.ts +8 -0
  78. package/dist/lib/hosts/tasks.js +14 -0
  79. package/dist/lib/permissions.d.ts +4 -0
  80. package/dist/lib/permissions.js +35 -0
  81. package/dist/lib/picker.d.ts +24 -0
  82. package/dist/lib/picker.js +124 -0
  83. package/dist/lib/platform/winpath.d.ts +31 -2
  84. package/dist/lib/platform/winpath.js +133 -24
  85. package/dist/lib/plugin-marketplace.d.ts +30 -0
  86. package/dist/lib/plugin-marketplace.js +215 -2
  87. package/dist/lib/plugins.d.ts +5 -0
  88. package/dist/lib/plugins.js +45 -4
  89. package/dist/lib/pwsh.d.ts +11 -0
  90. package/dist/lib/pwsh.js +13 -0
  91. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  92. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  93. package/dist/lib/secrets/agent.d.ts +42 -1
  94. package/dist/lib/secrets/agent.js +89 -11
  95. package/dist/lib/secrets/bundles.js +40 -9
  96. package/dist/lib/secrets/filestore.js +31 -1
  97. package/dist/lib/secrets/index.d.ts +33 -1
  98. package/dist/lib/secrets/index.js +90 -9
  99. package/dist/lib/secrets/windows.d.ts +74 -0
  100. package/dist/lib/secrets/windows.js +440 -0
  101. package/dist/lib/session/active.d.ts +7 -0
  102. package/dist/lib/session/active.js +11 -3
  103. package/dist/lib/session/discover.js +94 -0
  104. package/dist/lib/session/parse.d.ts +6 -0
  105. package/dist/lib/session/parse.js +283 -2
  106. package/dist/lib/session/pid-registry.d.ts +21 -0
  107. package/dist/lib/session/pid-registry.js +80 -0
  108. package/dist/lib/session/remote-active.d.ts +26 -0
  109. package/dist/lib/session/remote-active.js +141 -0
  110. package/dist/lib/session/remote.js +2 -6
  111. package/dist/lib/session/render.js +1 -1
  112. package/dist/lib/session/sync/config.d.ts +8 -0
  113. package/dist/lib/session/sync/config.js +11 -2
  114. package/dist/lib/session/types.d.ts +1 -1
  115. package/dist/lib/session/types.js +1 -1
  116. package/dist/lib/shims.d.ts +30 -2
  117. package/dist/lib/shims.js +107 -50
  118. package/dist/lib/ssh-exec.d.ts +26 -3
  119. package/dist/lib/ssh-exec.js +45 -3
  120. package/dist/lib/ssh-tunnel.d.ts +24 -5
  121. package/dist/lib/ssh-tunnel.js +60 -62
  122. package/dist/lib/staleness/writers/hooks.js +1 -1
  123. package/dist/lib/startup/command-registry.d.ts +3 -0
  124. package/dist/lib/startup/command-registry.js +6 -0
  125. package/dist/lib/sync-status.d.ts +102 -0
  126. package/dist/lib/sync-status.js +135 -0
  127. package/dist/lib/teams/agents.d.ts +24 -0
  128. package/dist/lib/teams/agents.js +30 -1
  129. package/dist/lib/teams/registry.js +25 -9
  130. package/dist/lib/terminal/backends/ghostty.d.ts +6 -0
  131. package/dist/lib/terminal/backends/ghostty.js +69 -0
  132. package/dist/lib/terminal/backends/index.d.ts +18 -0
  133. package/dist/lib/terminal/backends/index.js +29 -0
  134. package/dist/lib/terminal/backends/iterm.d.ts +6 -0
  135. package/dist/lib/terminal/backends/iterm.js +62 -0
  136. package/dist/lib/terminal/backends/tmux.d.ts +14 -0
  137. package/dist/lib/terminal/backends/tmux.js +23 -0
  138. package/dist/lib/terminal/engine.d.ts +39 -0
  139. package/dist/lib/terminal/engine.js +54 -0
  140. package/dist/lib/terminal/index.d.ts +14 -0
  141. package/dist/lib/terminal/index.js +5 -0
  142. package/dist/lib/terminal/policy.d.ts +11 -0
  143. package/dist/lib/terminal/policy.js +11 -0
  144. package/dist/lib/terminal/quote.d.ts +11 -0
  145. package/dist/lib/terminal/quote.js +13 -0
  146. package/dist/lib/terminal/shell.d.ts +6 -0
  147. package/dist/lib/terminal/shell.js +23 -0
  148. package/dist/lib/terminal/transport.d.ts +15 -0
  149. package/dist/lib/terminal/transport.js +40 -0
  150. package/dist/lib/terminal/types.d.ts +59 -0
  151. package/dist/lib/terminal/types.js +13 -0
  152. package/dist/lib/types.d.ts +27 -1
  153. package/dist/lib/usage.d.ts +30 -0
  154. package/dist/lib/usage.js +159 -2
  155. package/dist/lib/versions.d.ts +7 -3
  156. package/dist/lib/versions.js +10 -5
  157. package/dist/lib/whats-new.d.ts +9 -0
  158. package/dist/lib/whats-new.js +35 -0
  159. package/package.json +1 -1
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `agents logs` — unified, discoverable run-log viewer.
3
+ *
4
+ * Resolves a run across two substrates and shows (or `-f` follows) its log:
5
+ * - host-dispatch tasks (`agents run --host`) → combined-stdout log, offset-tailed
6
+ * - sessions (the local index) → transcript, tailed via the sessions tailer
7
+ *
8
+ * `[id]`/`--session` load directly (host task tried first, then session). With no
9
+ * id, `--host`/`--agent`/`--version` filter a merged candidate list; one match is
10
+ * shown, several open the fuzzy picker (or, non-TTY, print the list).
11
+ *
12
+ * Additive: `agents hosts logs` and `agents sessions tail` are unchanged and share
13
+ * the same underlying helpers (showHostTaskLog / streamSessionTail).
14
+ */
15
+ import type { Command } from 'commander';
16
+ /** Register the top-level `agents logs` command. */
17
+ export declare function registerLogsCommand(program: Command): void;
@@ -0,0 +1,139 @@
1
+ /**
2
+ * `agents logs` — unified, discoverable run-log viewer.
3
+ *
4
+ * Resolves a run across two substrates and shows (or `-f` follows) its log:
5
+ * - host-dispatch tasks (`agents run --host`) → combined-stdout log, offset-tailed
6
+ * - sessions (the local index) → transcript, tailed via the sessions tailer
7
+ *
8
+ * `[id]`/`--session` load directly (host task tried first, then session). With no
9
+ * id, `--host`/`--agent`/`--version` filter a merged candidate list; one match is
10
+ * shown, several open the fuzzy picker (or, non-TTY, print the list).
11
+ *
12
+ * Additive: `agents hosts logs` and `agents sessions tail` are unchanged and share
13
+ * the same underlying helpers (showHostTaskLog / streamSessionTail).
14
+ */
15
+ import chalk from 'chalk';
16
+ import { discoverSessions, resolveSessionById } from '../lib/session/discover.js';
17
+ import { parseAgentFilter, renderSessionLog } from './sessions.js';
18
+ import { streamSessionTail, isTailable } from './sessions-tail.js';
19
+ import { showHostTaskLog } from '../lib/hosts/logs.js';
20
+ import { listTasks } from '../lib/hosts/tasks.js';
21
+ import { itemPicker } from '../lib/picker.js';
22
+ /** Compact one-line label used by both the picker and the non-TTY list. */
23
+ function candidateLabel(c) {
24
+ if (c.kind === 'task') {
25
+ const t = c.task;
26
+ const status = t.status === 'completed' ? chalk.green(t.status)
27
+ : t.status === 'failed' ? chalk.red(t.status)
28
+ : chalk.yellow(t.status);
29
+ return `${chalk.gray('task')} ${t.id.slice(0, 8).padEnd(9)} ${t.host.padEnd(14)} ${t.agent.padEnd(8)} ${status} ${t.prompt.slice(0, 40)}`;
30
+ }
31
+ const s = c.session;
32
+ const ver = s.version ? chalk.gray(`@${s.version}`) : '';
33
+ const title = s.label || s.topic || '';
34
+ return `${chalk.gray('sess')} ${s.shortId.padEnd(9)} ${(s.agent + ver).padEnd(14)} ${chalk.gray(s.timestamp.slice(0, 16))} ${title.slice(0, 40)}`;
35
+ }
36
+ /** Show a resolved session — follow (tail) or render its transcript. */
37
+ async function showSession(session, follow) {
38
+ if (follow) {
39
+ if (!isTailable(session.agent)) {
40
+ console.error(chalk.red(`Tailing is supported for claude and codex sessions only (got ${session.agent}).`));
41
+ process.exit(2);
42
+ }
43
+ await streamSessionTail(session, {});
44
+ return;
45
+ }
46
+ await renderSessionLog(session);
47
+ }
48
+ async function showCandidate(c, follow) {
49
+ if (c.kind === 'task') {
50
+ const res = await showHostTaskLog(c.task.id, follow);
51
+ if (res.exitCode !== undefined)
52
+ process.exitCode = res.exitCode;
53
+ return;
54
+ }
55
+ await showSession(c.session, follow);
56
+ }
57
+ /** Resolve an explicit id/--session: host task first, then a session. */
58
+ async function showById(id, follow) {
59
+ const hostRes = await showHostTaskLog(id, follow);
60
+ if (hostRes.found) {
61
+ if (hostRes.exitCode !== undefined)
62
+ process.exitCode = hostRes.exitCode;
63
+ return;
64
+ }
65
+ const sessions = await discoverSessions({ all: true, limit: 5000 });
66
+ const matches = resolveSessionById(sessions, id);
67
+ if (matches.length === 0) {
68
+ console.error(chalk.red(`No run or session found matching "${id}".`));
69
+ process.exit(1);
70
+ }
71
+ await showSession(matches[0], follow);
72
+ }
73
+ async function runLogs(id, opts) {
74
+ const follow = !!opts.follow;
75
+ const directId = opts.session ?? id;
76
+ if (directId) {
77
+ await showById(directId, follow);
78
+ return;
79
+ }
80
+ const { agent, version } = parseAgentFilter(opts.agent);
81
+ const wantVersion = opts.version ?? version;
82
+ // Host tasks carry no session-index metadata; sessions carry no host tag.
83
+ // So --host scopes to dispatched tasks, and --version to sessions.
84
+ const candidates = [];
85
+ let tasks = listTasks();
86
+ if (opts.host)
87
+ tasks = tasks.filter((t) => t.host === opts.host);
88
+ if (agent)
89
+ tasks = tasks.filter((t) => t.agent === agent);
90
+ for (const t of tasks)
91
+ candidates.push({ kind: 'task', task: t });
92
+ if (!opts.host) {
93
+ const sessions = await discoverSessions({ agent, version: wantVersion, limit: 50 });
94
+ for (const s of sessions)
95
+ candidates.push({ kind: 'session', session: s });
96
+ }
97
+ if (candidates.length === 0) {
98
+ console.error(chalk.yellow('No matching runs. Dispatch one: agents run <agent> "<task>" [--host <name>]'));
99
+ process.exit(1);
100
+ }
101
+ if (candidates.length === 1) {
102
+ await showCandidate(candidates[0], follow);
103
+ return;
104
+ }
105
+ // Multiple sessions matched → picker if interactive, else a list to pick from.
106
+ if (!process.stdin.isTTY) {
107
+ console.error(chalk.yellow(`${candidates.length} runs match. Pass an id or --session <id>:`));
108
+ for (const c of candidates.slice(0, 30))
109
+ console.error(' ' + candidateLabel(c));
110
+ process.exit(1);
111
+ }
112
+ const picked = await itemPicker({
113
+ message: 'Select a run to view its log:',
114
+ items: candidates,
115
+ filter: (query) => {
116
+ const q = query.trim().toLowerCase();
117
+ if (!q)
118
+ return candidates;
119
+ return candidates.filter((c) => candidateLabel(c).toLowerCase().includes(q));
120
+ },
121
+ labelFor: (c) => candidateLabel(c),
122
+ shortIdFor: (c) => (c.kind === 'task' ? c.task.id : c.session.shortId),
123
+ });
124
+ if (!picked)
125
+ return;
126
+ await showCandidate(picked.item, follow);
127
+ }
128
+ /** Register the top-level `agents logs` command. */
129
+ export function registerLogsCommand(program) {
130
+ program
131
+ .command('logs [id]')
132
+ .description('Show a run’s log — a host-dispatch task or a session. -f to follow a live one.')
133
+ .option('--host <name>', 'Scope to runs dispatched to a host')
134
+ .option('-a, --agent <agent>', 'Filter by agent (e.g. claude, codex@0.116.0)')
135
+ .option('--version <version>', 'Filter by agent version')
136
+ .option('--session <id>', 'Select a session/run by id (same as the positional id)')
137
+ .option('-f, --follow', 'Follow live output')
138
+ .action((id, opts) => runLogs(id, opts));
139
+ }
@@ -8,3 +8,6 @@
8
8
  import type { Command } from 'commander';
9
9
  /** Register the hidden `agents models` command. */
10
10
  export declare function registerModelsCommand(program: Command): void;
11
+ export declare function formatModelSourceLine(kind: string, sourcePath: string, width?: number): string;
12
+ export declare function formatModelAliasLines(parts: string[], width?: number): string[];
13
+ export declare function formatModelSummaryLine(star: string, id: string, displayName?: string, alias?: string, width?: number): string;
@@ -11,6 +11,8 @@ import { homeDir } from '../lib/platform/index.js';
11
11
  import { resolveAgentName, formatAgentError, agentLabel, } from '../lib/agents.js';
12
12
  import { listInstalledVersions, getGlobalDefault, resolveVersion, resolveVersionAlias } from '../lib/versions.js';
13
13
  import { getModelCatalog, locateModelSource } from '../lib/models.js';
14
+ import { terminalWidth, truncateToWidth, stringWidth } from '../lib/session/width.js';
15
+ import { wrapJoined } from './inspect.js';
14
16
  const MODEL_CAPABLE_AGENTS = ['claude', 'codex', 'gemini', 'opencode', 'cursor', 'openclaw', 'antigravity', 'kimi'];
15
17
  /**
16
18
  * Agents that don't necessarily install under ~/.agents/versions (cursor ships
@@ -131,21 +133,19 @@ function printCatalog(agent, version, isDefault, options) {
131
133
  console.log(chalk.yellow(` No models extracted from ${src.kind} at ${src.path}.`));
132
134
  return;
133
135
  }
134
- console.log(chalk.gray(` source: ${src.kind} (${shortPath(src.path)})`));
136
+ console.log(chalk.gray(formatModelSourceLine(src.kind, shortPath(src.path))));
135
137
  if (Object.keys(catalog.aliases).length > 0) {
136
138
  const parts = Object.entries(catalog.aliases).map(([alias, id]) => `${chalk.cyan(alias)}=${id}`);
137
- console.log(chalk.gray(` aliases: `) + parts.join(', '));
139
+ for (const line of formatModelAliasLines(parts))
140
+ console.log(line);
138
141
  }
139
142
  console.log();
140
143
  for (const model of catalog.models) {
141
144
  const star = model.isDefault ? chalk.green('*') : ' ';
142
- const display = model.displayName && model.displayName !== model.id
143
- ? chalk.gray(` (${model.displayName})`)
144
- : '';
145
- const aliasTag = model.alias ? chalk.cyan(` [${model.alias}]`) : '';
146
- console.log(` ${star} ${chalk.bold(model.id)}${display}${aliasTag}`);
145
+ console.log(formatModelSummaryLine(star, model.id, model.displayName, model.alias));
147
146
  if (model.description) {
148
- console.log(chalk.gray(` ${model.description}`));
147
+ const descPrefix = ' ';
148
+ console.log(chalk.gray(descPrefix + truncateToWidth(model.description, Math.max(1, terminalWidth() - stringWidth(descPrefix)))));
149
149
  }
150
150
  if (options.cloud && model.perCloud) {
151
151
  const c = model.perCloud;
@@ -175,3 +175,22 @@ function printCatalog(agent, version, isDefault, options) {
175
175
  function shortPath(p) {
176
176
  return p.replace(homeDir(), '~');
177
177
  }
178
+ export function formatModelSourceLine(kind, sourcePath, width = terminalWidth()) {
179
+ const prefix = ` source: ${kind} (`;
180
+ const suffix = ')';
181
+ const room = Math.max(1, width - stringWidth(prefix) - stringWidth(suffix));
182
+ return prefix + truncateToWidth(sourcePath, room) + suffix;
183
+ }
184
+ export function formatModelAliasLines(parts, width = terminalWidth()) {
185
+ return wrapJoined(chalk.gray(' aliases: '), parts, ', ', width);
186
+ }
187
+ export function formatModelSummaryLine(star, id, displayName, alias, width = terminalWidth()) {
188
+ const display = displayName && displayName !== id ? ` (${displayName})` : '';
189
+ const aliasTag = alias ? ` [${alias}]` : '';
190
+ const prefix = ` ${star} `;
191
+ const plain = `${id}${display}${aliasTag}`;
192
+ if (stringWidth(plain) > Math.max(1, width - stringWidth(prefix))) {
193
+ return prefix + truncateToWidth(plain, Math.max(1, width - stringWidth(prefix)));
194
+ }
195
+ return prefix + chalk.bold(id) + chalk.gray(display) + chalk.cyan(aliasTag);
196
+ }
@@ -1,5 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import ora from 'ora';
3
+ import { terminalWidth, truncateToWidth, stringWidth } from '../lib/session/width.js';
3
4
  import * as fs from 'fs';
4
5
  import * as os from 'os';
5
6
  import * as path from 'path';
@@ -191,9 +192,15 @@ When to use:
191
192
  return;
192
193
  }
193
194
  console.log(chalk.bold('Installed Permission Sets:\n'));
195
+ const permCols = terminalWidth();
194
196
  for (const perm of sets) {
195
- const desc = perm.set.description ? ` - ${chalk.gray(perm.set.description)}` : '';
196
- console.log(` ${chalk.cyan(perm.name)}${desc}`);
197
+ const prefix = ` ${chalk.cyan(perm.name)}`;
198
+ // Cap the description to the line so a prose-paragraph set (400+ chars) can't smear.
199
+ const budget = permCols - stringWidth(prefix) - 3;
200
+ const desc = perm.set.description && budget > 3
201
+ ? ` - ${chalk.gray(truncateToWidth(perm.set.description, budget))}`
202
+ : '';
203
+ console.log(`${prefix}${desc}`);
197
204
  console.log(` ${chalk.gray(`${perm.set.allow.length} allow, ${perm.set.deny?.length || 0} deny rules`)}`);
198
205
  }
199
206
  }
@@ -28,6 +28,36 @@ export declare function resourceUnit(file: string): {
28
28
  kind: RepoResourceKind;
29
29
  unit: string;
30
30
  };
31
+ /** One resource kind + action, collapsed to a unit count (e.g. 2 new skills). */
32
+ export interface CountedResource {
33
+ action: ChangeAction;
34
+ kind: RepoResourceKind;
35
+ count: number;
36
+ }
37
+ /** Resource-level summary of a changed-file set. */
38
+ export interface ResourceDelta {
39
+ /** Counts in display order (grouped new -> changed -> removed, then RESOURCE_ORDER). */
40
+ counts: CountedResource[];
41
+ /** Total distinct resource units changed. */
42
+ total: number;
43
+ }
44
+ /**
45
+ * Collapse a changed-file set to distinct resource units, then count them by
46
+ * (action, kind). A skill whose three files all changed counts as one changed
47
+ * skill; a unit with mixed add+modify reads as a single change. This is the
48
+ * shared structured core behind every SYNC / CHANGES rendering.
49
+ */
50
+ export declare function resourceDelta(entries: {
51
+ action: ChangeAction;
52
+ file: string;
53
+ }[]): ResourceDelta;
54
+ /**
55
+ * Kind-only brief for the compact (wide-terminal) layout: `(24 skills, 9 commands, +20)`
56
+ * — the top `maxKinds` kinds by display order, with a `+N` remainder. Drops the
57
+ * new/changed verb (the arrow already carries direction) to stay short. Returns
58
+ * '' when there is nothing to summarize.
59
+ */
60
+ export declare function deltaBrief(delta: ResourceDelta, maxKinds?: number): string;
31
61
  /**
32
62
  * Render a set of changed files as a resource-level summary, e.g.
33
63
  * `2 new skills, 1 changed hook`. Counts distinct resource units (a skill whose
@@ -39,6 +69,10 @@ export declare function formatResourceDelta(entries: {
39
69
  action: ChangeAction;
40
70
  file: string;
41
71
  }[], maxParts?: number): string;
72
+ /** `owner/repo` from a git URL, for the compact card header. Falls back to the raw URL. */
73
+ export declare function repoSlug(url: string): string;
74
+ /** Pack colored phrases into `, `-joined lines no wider than `width`. */
75
+ export declare function wrapPhrases(parts: string[], width: number): string[];
42
76
  /** Register the `agents repo` command tree. */
43
77
  export declare function registerRepoCommands(program: Command): void;
44
78
  export {};