@phnx-labs/agents-cli 1.20.72 → 1.20.73

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 (219) hide show
  1. package/CHANGELOG.md +299 -0
  2. package/README.md +40 -4
  3. package/dist/bin/agents +0 -0
  4. package/dist/commands/activity.d.ts +12 -0
  5. package/dist/commands/activity.js +68 -0
  6. package/dist/commands/apply.d.ts +13 -0
  7. package/dist/commands/apply.js +28 -3
  8. package/dist/commands/browser.js +1 -1
  9. package/dist/commands/cloud.js +21 -11
  10. package/dist/commands/doctor.js +8 -4
  11. package/dist/commands/events.d.ts +11 -10
  12. package/dist/commands/events.js +30 -21
  13. package/dist/commands/exec.d.ts +34 -0
  14. package/dist/commands/exec.js +337 -39
  15. package/dist/commands/feed.d.ts +13 -0
  16. package/dist/commands/feed.js +130 -29
  17. package/dist/commands/hq.d.ts +2 -0
  18. package/dist/commands/hq.js +58 -0
  19. package/dist/commands/lease.d.ts +19 -0
  20. package/dist/commands/lease.js +138 -11
  21. package/dist/commands/login.d.ts +2 -0
  22. package/dist/commands/login.js +123 -0
  23. package/dist/commands/logs.js +1 -1
  24. package/dist/commands/mine.d.ts +27 -0
  25. package/dist/commands/mine.js +207 -0
  26. package/dist/commands/monitors.js +79 -49
  27. package/dist/commands/plugins.js +1 -0
  28. package/dist/commands/profiles.js +158 -0
  29. package/dist/commands/repo.js +2 -60
  30. package/dist/commands/resources.d.ts +5 -0
  31. package/dist/commands/resources.js +95 -0
  32. package/dist/commands/routines.d.ts +2 -0
  33. package/dist/commands/routines.js +139 -37
  34. package/dist/commands/secrets.js +234 -47
  35. package/dist/commands/send.d.ts +15 -0
  36. package/dist/commands/send.js +62 -0
  37. package/dist/commands/sessions-tail.d.ts +1 -0
  38. package/dist/commands/sessions-tail.js +20 -9
  39. package/dist/commands/sessions.js +18 -3
  40. package/dist/commands/setup-mine.d.ts +18 -0
  41. package/dist/commands/setup-mine.js +106 -0
  42. package/dist/commands/setup-share.js +2 -2
  43. package/dist/commands/setup.js +3 -1
  44. package/dist/commands/share.d.ts +8 -1
  45. package/dist/commands/share.js +122 -37
  46. package/dist/commands/ssh.d.ts +9 -0
  47. package/dist/commands/ssh.js +196 -26
  48. package/dist/commands/sync.js +1 -1
  49. package/dist/commands/teams.js +11 -2
  50. package/dist/index.js +79 -10
  51. package/dist/lib/activity.d.ts +124 -0
  52. package/dist/lib/activity.js +542 -0
  53. package/dist/lib/agents.js +16 -5
  54. package/dist/lib/artifact-actions.d.ts +1 -1
  55. package/dist/lib/artifact-actions.js +1 -1
  56. package/dist/lib/ask-classifier.d.ts +2 -1
  57. package/dist/lib/ask-classifier.js +3 -3
  58. package/dist/lib/auth-health.d.ts +32 -4
  59. package/dist/lib/auth-health.js +40 -1
  60. package/dist/lib/auto-pull.js +8 -1
  61. package/dist/lib/brand.d.ts +40 -0
  62. package/dist/lib/brand.js +122 -0
  63. package/dist/lib/browser/drivers/ssh.js +4 -7
  64. package/dist/lib/browser/service.js +6 -8
  65. package/dist/lib/channels/providers/index.d.ts +2 -0
  66. package/dist/lib/channels/providers/index.js +20 -0
  67. package/dist/lib/channels/providers/mailbox.d.ts +2 -0
  68. package/dist/lib/channels/providers/mailbox.js +26 -0
  69. package/dist/lib/channels/providers/openclaw-telegram.d.ts +2 -0
  70. package/dist/lib/channels/providers/openclaw-telegram.js +34 -0
  71. package/dist/lib/channels/providers/rush.d.ts +6 -0
  72. package/dist/lib/channels/providers/rush.js +55 -0
  73. package/dist/lib/channels/registry.d.ts +42 -0
  74. package/dist/lib/channels/registry.js +20 -0
  75. package/dist/lib/channels/resolve.d.ts +11 -0
  76. package/dist/lib/channels/resolve.js +12 -0
  77. package/dist/lib/cli-resources.d.ts +18 -0
  78. package/dist/lib/cli-resources.js +53 -4
  79. package/dist/lib/cloud/codex.js +6 -3
  80. package/dist/lib/cloud/factory.d.ts +1 -0
  81. package/dist/lib/cloud/factory.js +10 -4
  82. package/dist/lib/cloud/rush.d.ts +3 -1
  83. package/dist/lib/cloud/rush.js +6 -1
  84. package/dist/lib/cloud/types.d.ts +2 -0
  85. package/dist/lib/codex-home.d.ts +35 -0
  86. package/dist/lib/codex-home.js +136 -0
  87. package/dist/lib/crabbox/cli.d.ts +44 -0
  88. package/dist/lib/crabbox/cli.js +120 -20
  89. package/dist/lib/crabbox/lease.d.ts +52 -1
  90. package/dist/lib/crabbox/lease.js +117 -16
  91. package/dist/lib/crabbox/progress.d.ts +31 -0
  92. package/dist/lib/crabbox/progress.js +76 -0
  93. package/dist/lib/crabbox/runtimes.d.ts +4 -0
  94. package/dist/lib/crabbox/runtimes.js +33 -8
  95. package/dist/lib/crabbox/setup-copy.d.ts +87 -0
  96. package/dist/lib/crabbox/setup-copy.js +127 -0
  97. package/dist/lib/daemon.d.ts +5 -5
  98. package/dist/lib/daemon.js +9 -9
  99. package/dist/lib/drive-sync.js +6 -3
  100. package/dist/lib/event-stream.d.ts +36 -0
  101. package/dist/lib/event-stream.js +68 -0
  102. package/dist/lib/events.d.ts +1 -1
  103. package/dist/lib/exec.d.ts +11 -0
  104. package/dist/lib/exec.js +23 -2
  105. package/dist/lib/feed-policy.d.ts +1 -1
  106. package/dist/lib/feed-policy.js +14 -9
  107. package/dist/lib/feed-ranking.d.ts +32 -0
  108. package/dist/lib/feed-ranking.js +224 -0
  109. package/dist/lib/feed.d.ts +35 -2
  110. package/dist/lib/feed.js +66 -3
  111. package/dist/lib/fleet/auth-sync.d.ts +53 -0
  112. package/dist/lib/fleet/auth-sync.js +92 -0
  113. package/dist/lib/fleet/remote-login.d.ts +187 -0
  114. package/dist/lib/fleet/remote-login.js +556 -0
  115. package/dist/lib/format.d.ts +30 -3
  116. package/dist/lib/format.js +34 -5
  117. package/dist/lib/fs-atomic.d.ts +7 -2
  118. package/dist/lib/fs-atomic.js +8 -12
  119. package/dist/lib/git.d.ts +16 -0
  120. package/dist/lib/git.js +79 -2
  121. package/dist/lib/heal.js +11 -3
  122. package/dist/lib/hosts/progress.d.ts +28 -10
  123. package/dist/lib/hosts/progress.js +79 -22
  124. package/dist/lib/hosts/remote-cmd.js +4 -0
  125. package/dist/lib/hq/floor.d.ts +87 -0
  126. package/dist/lib/hq/floor.js +226 -0
  127. package/dist/lib/menubar/install-menubar.js +14 -20
  128. package/dist/lib/notify.d.ts +1 -0
  129. package/dist/lib/notify.js +3 -3
  130. package/dist/lib/open-url.d.ts +2 -0
  131. package/dist/lib/open-url.js +19 -0
  132. package/dist/lib/openclaw-keychain.d.ts +56 -0
  133. package/dist/lib/openclaw-keychain.js +236 -0
  134. package/dist/lib/overdue.js +10 -0
  135. package/dist/lib/permissions.d.ts +44 -1
  136. package/dist/lib/permissions.js +284 -7
  137. package/dist/lib/project-launch.d.ts +6 -12
  138. package/dist/lib/project-launch.js +13 -228
  139. package/dist/lib/project-resources.d.ts +7 -0
  140. package/dist/lib/project-resources.js +291 -0
  141. package/dist/lib/pty-client.d.ts +27 -0
  142. package/dist/lib/pty-client.js +136 -10
  143. package/dist/lib/refresh.js +14 -10
  144. package/dist/lib/resource-profiles.d.ts +26 -0
  145. package/dist/lib/resource-profiles.js +157 -0
  146. package/dist/lib/resources/permissions.js +7 -1
  147. package/dist/lib/resources/types.d.ts +1 -1
  148. package/dist/lib/resources.d.ts +1 -1
  149. package/dist/lib/resources.js +32 -3
  150. package/dist/lib/routines.d.ts +11 -0
  151. package/dist/lib/routines.js +56 -15
  152. package/dist/lib/runner.d.ts +1 -0
  153. package/dist/lib/runner.js +66 -5
  154. package/dist/lib/secrets/bundles.d.ts +16 -3
  155. package/dist/lib/secrets/bundles.js +206 -37
  156. package/dist/lib/secrets/icloud-import.d.ts +2 -2
  157. package/dist/lib/secrets/icloud-import.js +9 -6
  158. package/dist/lib/secrets/mcp.js +1 -1
  159. package/dist/lib/secrets/vault-age-helper.d.ts +1 -0
  160. package/dist/lib/secrets/vault-age-helper.js +34 -0
  161. package/dist/lib/secrets/vault.d.ts +49 -0
  162. package/dist/lib/secrets/vault.js +397 -0
  163. package/dist/lib/self-heal/checks/path.js +3 -1
  164. package/dist/lib/self-heal/checks/shadowing.js +10 -2
  165. package/dist/lib/self-heal/checks/shims.js +19 -11
  166. package/dist/lib/session/cloud.d.ts +2 -2
  167. package/dist/lib/session/cloud.js +2 -2
  168. package/dist/lib/session/db.d.ts +4 -0
  169. package/dist/lib/session/db.js +44 -7
  170. package/dist/lib/session/discover.d.ts +2 -0
  171. package/dist/lib/session/discover.js +114 -3
  172. package/dist/lib/session/stream-render.d.ts +3 -0
  173. package/dist/lib/session/stream-render.js +130 -0
  174. package/dist/lib/session/types.d.ts +6 -0
  175. package/dist/lib/share/analytics.d.ts +13 -0
  176. package/dist/lib/share/analytics.js +45 -0
  177. package/dist/lib/share/config.d.ts +19 -5
  178. package/dist/lib/share/config.js +44 -8
  179. package/dist/lib/share/provision.d.ts +58 -6
  180. package/dist/lib/share/provision.js +97 -22
  181. package/dist/lib/share/publish.d.ts +36 -13
  182. package/dist/lib/share/publish.js +55 -8
  183. package/dist/lib/share/worker-template.js +83 -17
  184. package/dist/lib/shims.d.ts +9 -0
  185. package/dist/lib/shims.js +91 -13
  186. package/dist/lib/ssh-exec.d.ts +14 -0
  187. package/dist/lib/ssh-exec.js +57 -0
  188. package/dist/lib/staleness/detectors/hooks.js +25 -1
  189. package/dist/lib/staleness/detectors/permissions.js +66 -0
  190. package/dist/lib/staleness/detectors/workflows.js +20 -0
  191. package/dist/lib/staleness/writers/hooks.js +58 -4
  192. package/dist/lib/staleness/writers/permissions.js +2 -2
  193. package/dist/lib/staleness/writers/skills.js +1 -1
  194. package/dist/lib/staleness/writers/sources.d.ts +10 -1
  195. package/dist/lib/staleness/writers/sources.js +68 -1
  196. package/dist/lib/star-nudge.d.ts +45 -0
  197. package/dist/lib/star-nudge.js +91 -0
  198. package/dist/lib/startup/command-registry.d.ts +6 -1
  199. package/dist/lib/startup/command-registry.js +17 -3
  200. package/dist/lib/state.d.ts +2 -0
  201. package/dist/lib/state.js +3 -0
  202. package/dist/lib/subagents-registry.d.ts +2 -0
  203. package/dist/lib/subagents-registry.js +3 -0
  204. package/dist/lib/teams/parsers.js +214 -6
  205. package/dist/lib/teams/supervisor.d.ts +7 -0
  206. package/dist/lib/teams/supervisor.js +2 -1
  207. package/dist/lib/template.d.ts +1 -1
  208. package/dist/lib/template.js +1 -1
  209. package/dist/lib/triggers/webhook.js +36 -3
  210. package/dist/lib/types.d.ts +73 -0
  211. package/dist/lib/version.d.ts +40 -0
  212. package/dist/lib/version.js +94 -16
  213. package/dist/lib/versions.d.ts +11 -0
  214. package/dist/lib/versions.js +208 -76
  215. package/dist/lib/workflows.d.ts +2 -0
  216. package/dist/lib/workflows.js +88 -0
  217. package/package.json +2 -1
  218. package/dist/commands/daemon.d.ts +0 -10
  219. package/dist/commands/daemon.js +0 -121
@@ -14,6 +14,9 @@ import { getPreset, listPresets, expandPreset } from '../lib/profiles-presets.js
14
14
  import { hasKeychainToken, keychainItemName, setKeychainToken, deleteKeychainToken, } from '../lib/secrets/profiles.js';
15
15
  import { isInteractiveTerminal } from './utils.js';
16
16
  import { getAgentsInvocation } from '../lib/daemon.js';
17
+ import { getActiveResourceProfileName, getResourceProfilePreset, listResourceProfileNames, setActiveResourceProfile, upsertResourceProfilePreset, validateResourceProfileName, } from '../lib/resource-profiles.js';
18
+ import { AGENTS } from '../lib/agents.js';
19
+ import { listInstalledVersions, syncResourcesToVersion } from '../lib/versions.js';
17
20
  /**
18
21
  * Pure helper: builds a Profile from collected wizard inputs. Extracted so the
19
22
  * shape of preset->profile mapping for the `create` wizard is unit-testable
@@ -69,8 +72,141 @@ function renderProfileRow(p) {
69
72
  const provider = p.provider || (p.auth?.keychainItem?.split('.')[1]) || '-';
70
73
  return `${chalk.cyan(p.name.padEnd(16))} ${host.padEnd(14)} ${provider.padEnd(12)} ${chalk.gray(model)}`;
71
74
  }
75
+ function splitList(value) {
76
+ if (value === undefined)
77
+ return undefined;
78
+ return value.split(',').map((part) => part.trim()).filter(Boolean);
79
+ }
80
+ function buildResourceProfileFromOptions(existing, opts) {
81
+ const next = { ...(existing ?? {}) };
82
+ if (opts.description !== undefined)
83
+ next.description = opts.description || undefined;
84
+ const keys = ['commands', 'skills', 'hooks', 'subagents', 'plugins', 'workflows', 'permissions', 'mcp'];
85
+ for (const key of keys) {
86
+ const parsed = splitList(opts[key]);
87
+ if (parsed !== undefined)
88
+ next[key] = parsed;
89
+ }
90
+ const secrets = splitList(opts.secrets);
91
+ if (secrets !== undefined)
92
+ next.secrets = secrets;
93
+ if (opts.rules !== undefined)
94
+ next.rules = opts.rules || undefined;
95
+ return next;
96
+ }
97
+ function printResourceProfile(name, preset, activeName) {
98
+ const activeMark = activeName === name ? '*' : ' ';
99
+ const description = preset.description ? ` ${chalk.gray(preset.description)}` : '';
100
+ console.log(`${activeMark} ${chalk.cyan(name)}${description}`);
101
+ }
102
+ function syncInstalledVersionsForActiveProfile(cwd) {
103
+ let synced = 0;
104
+ for (const agent of Object.keys(AGENTS)) {
105
+ for (const version of listInstalledVersions(agent)) {
106
+ syncResourcesToVersion(agent, version, undefined, { cwd, force: true });
107
+ synced++;
108
+ }
109
+ }
110
+ return synced;
111
+ }
112
+ function registerResourceProfileCommands(program) {
113
+ const cmd = program
114
+ .command('profile')
115
+ .description('Activate top-level resource profiles across commands, skills, hooks, rules, MCP, permissions, and secrets.');
116
+ cmd
117
+ .command('list')
118
+ .alias('ls')
119
+ .description('List top-level resource profiles')
120
+ .action(() => {
121
+ const names = listResourceProfileNames();
122
+ if (names.length === 0) {
123
+ console.log(chalk.gray('No resource profiles configured.'));
124
+ console.log(chalk.gray('Try: agents profile set work --skills user:code-review --secrets work'));
125
+ return;
126
+ }
127
+ const active = getActiveResourceProfileName();
128
+ for (const name of names) {
129
+ printResourceProfile(name, getResourceProfilePreset(name), active);
130
+ }
131
+ });
132
+ cmd
133
+ .command('status')
134
+ .description('Show the active top-level resource profile')
135
+ .action(() => {
136
+ const active = getActiveResourceProfileName();
137
+ if (!active) {
138
+ console.log(chalk.gray('No resource profile active.'));
139
+ return;
140
+ }
141
+ const preset = getResourceProfilePreset(active);
142
+ console.log(chalk.bold(active));
143
+ if (!preset) {
144
+ console.log(chalk.red('Configured active profile is missing from profiles.presets.'));
145
+ return;
146
+ }
147
+ if (preset.description)
148
+ console.log(chalk.gray(preset.description));
149
+ for (const [key, value] of Object.entries(preset)) {
150
+ if (key === 'description')
151
+ continue;
152
+ console.log(`${key}: ${Array.isArray(value) ? value.join(', ') : value}`);
153
+ }
154
+ });
155
+ cmd
156
+ .command('set <name>')
157
+ .alias('define')
158
+ .description('Create or update a top-level resource profile')
159
+ .option('--description <text>', 'Free-form description')
160
+ .option('--commands <patterns>', 'Comma-separated command selectors, e.g. system:commit,user:*')
161
+ .option('--skills <patterns>', 'Comma-separated skill selectors')
162
+ .option('--hooks <patterns>', 'Comma-separated hook selectors')
163
+ .option('--subagents <patterns>', 'Comma-separated subagent selectors')
164
+ .option('--plugins <patterns>', 'Comma-separated plugin selectors')
165
+ .option('--workflows <patterns>', 'Comma-separated workflow selectors')
166
+ .option('--permissions <patterns>', 'Comma-separated permission group selectors')
167
+ .option('--mcp <patterns>', 'Comma-separated MCP server selectors')
168
+ .option('--rules <preset>', 'Rules preset to compose while active')
169
+ .option('--secrets <names>', 'Comma-separated secrets bundles, or "*"')
170
+ .action((name, opts) => {
171
+ try {
172
+ validateResourceProfileName(name);
173
+ const preset = buildResourceProfileFromOptions(getResourceProfilePreset(name), opts);
174
+ upsertResourceProfilePreset(name, preset);
175
+ console.log(chalk.green(`Profile '${name}' saved.`));
176
+ }
177
+ catch (err) {
178
+ console.error(chalk.red(err.message));
179
+ process.exit(1);
180
+ }
181
+ });
182
+ cmd
183
+ .command('use <name>')
184
+ .description('Activate a top-level resource profile and reconcile installed versions')
185
+ .action((name) => {
186
+ try {
187
+ setActiveResourceProfile(name);
188
+ const synced = syncInstalledVersionsForActiveProfile(process.cwd());
189
+ console.log(chalk.green(`Profile '${name}' active.`));
190
+ console.log(chalk.gray(`Reconciled ${synced} installed version${synced === 1 ? '' : 's'}.`));
191
+ }
192
+ catch (err) {
193
+ console.error(chalk.red(err.message));
194
+ process.exit(1);
195
+ }
196
+ });
197
+ cmd
198
+ .command('clear')
199
+ .description('Clear the active top-level resource profile and reconcile installed versions')
200
+ .action(() => {
201
+ setActiveResourceProfile(null);
202
+ const synced = syncInstalledVersionsForActiveProfile(process.cwd());
203
+ console.log(chalk.green('Resource profile cleared.'));
204
+ console.log(chalk.gray(`Reconciled ${synced} installed version${synced === 1 ? '' : 's'}.`));
205
+ });
206
+ }
72
207
  /** Register the `agents profiles` command tree. */
73
208
  export function registerProfilesCommands(program) {
209
+ registerResourceProfileCommands(program);
74
210
  const cmd = program
75
211
  .command('profiles')
76
212
  .description('Named bundles of (host CLI, endpoint, model, auth) — run Kimi/DeepSeek/Qwen/etc through Claude Code without a proxy.')
@@ -142,6 +278,28 @@ Examples:
142
278
  # Fully remove the OpenRouter key from Keychain
143
279
  agents profiles logout openrouter
144
280
  `);
281
+ cmd
282
+ .command('use <name>')
283
+ .description('Alias for `agents profile use <name>`')
284
+ .action((name) => {
285
+ try {
286
+ setActiveResourceProfile(name);
287
+ const synced = syncInstalledVersionsForActiveProfile(process.cwd());
288
+ console.log(chalk.green(`Profile '${name}' active.`));
289
+ console.log(chalk.gray(`Reconciled ${synced} installed version${synced === 1 ? '' : 's'}.`));
290
+ }
291
+ catch (err) {
292
+ console.error(chalk.red(err.message));
293
+ process.exit(1);
294
+ }
295
+ });
296
+ cmd
297
+ .command('status')
298
+ .description('Alias for `agents profile status`')
299
+ .action(() => {
300
+ const active = getActiveResourceProfileName();
301
+ console.log(active ? active : chalk.gray('No resource profile active.'));
302
+ });
145
303
  cmd
146
304
  .command('list')
147
305
  .alias('ls')
@@ -6,7 +6,7 @@ import * as fs from 'fs';
6
6
  import * as path from 'path';
7
7
  import * as os from 'os';
8
8
  import simpleGit from 'simple-git';
9
- import { confirm, input } from '@inquirer/prompts';
9
+ import { input } from '@inquirer/prompts';
10
10
  import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
11
11
  import { setHelpSections } from '../lib/help.js';
12
12
  import { itemPicker } from '../lib/picker.js';
@@ -843,66 +843,8 @@ export function registerRepoCommands(program) {
843
843
  continue;
844
844
  }
845
845
  }
846
- if (t.alias === 'system') {
846
+ if (t.alias === 'system' && alias !== 'system') {
847
847
  // Skip system repo unless explicitly requested
848
- if (alias !== 'system')
849
- continue;
850
- // User explicitly asked for system repo — show status and offer to pull
851
- try {
852
- const git = simpleGit(t.dir);
853
- await git.fetch();
854
- const status = await git.status();
855
- const behind = status.behind ?? 0;
856
- if (behind === 0) {
857
- console.log(chalk.green('Up to date'));
858
- }
859
- else {
860
- // Count changed resources by type
861
- const diff = await git.diff(['--name-only', 'HEAD..@{upstream}']);
862
- const files = diff.split('\n').filter(Boolean);
863
- const counts = {};
864
- for (const f of files) {
865
- if (f.startsWith('skills/'))
866
- counts['skills'] = (counts['skills'] || 0) + 1;
867
- else if (f.startsWith('commands/'))
868
- counts['commands'] = (counts['commands'] || 0) + 1;
869
- else if (f.startsWith('hooks/'))
870
- counts['hooks'] = (counts['hooks'] || 0) + 1;
871
- else if (f.startsWith('rules/'))
872
- counts['rules'] = (counts['rules'] || 0) + 1;
873
- else
874
- counts['other'] = (counts['other'] || 0) + 1;
875
- }
876
- const parts = [];
877
- if (counts['skills'])
878
- parts.push(`${counts['skills']} skill${counts['skills'] > 1 ? 's' : ''}`);
879
- if (counts['commands'])
880
- parts.push(`${counts['commands']} command${counts['commands'] > 1 ? 's' : ''}`);
881
- if (counts['hooks'])
882
- parts.push(`${counts['hooks']} hook${counts['hooks'] > 1 ? 's' : ''}`);
883
- if (counts['rules'])
884
- parts.push(`${counts['rules']} rule${counts['rules'] > 1 ? 's' : ''}`);
885
- if (counts['other'])
886
- parts.push(`${counts['other']} other`);
887
- const summary = parts.length > 0 ? parts.join(', ') : `${behind} update${behind > 1 ? 's' : ''}`;
888
- console.log(chalk.yellow(`${summary} available`));
889
- if (isInteractiveTerminal()) {
890
- const doPull = await confirm({ message: 'Pull now?', default: true });
891
- if (doPull) {
892
- const result = await pullRepo(t.dir);
893
- if (result.success) {
894
- console.log(chalk.green('Updated'));
895
- }
896
- else {
897
- console.log(chalk.red(result.error || 'Pull failed'));
898
- }
899
- }
900
- }
901
- }
902
- }
903
- catch (err) {
904
- console.log(chalk.red(err.message));
905
- }
906
848
  continue;
907
849
  }
908
850
  const spinner = ora(`Pulling ${formatRepoTarget(t.alias, t.dir)}...`).start();
@@ -0,0 +1,5 @@
1
+ /**
2
+ * `agents resources` — show the merged DotAgents resource surface.
3
+ */
4
+ import type { Command } from 'commander';
5
+ export declare function registerResourcesCommand(program: Command): void;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * `agents resources` — show the merged DotAgents resource surface.
3
+ */
4
+ import * as path from 'path';
5
+ import chalk from 'chalk';
6
+ import { listResources } from '../lib/resources.js';
7
+ import { terminalWidth, truncateToWidth, stringWidth } from '../lib/session/width.js';
8
+ const DRILLABLE_KINDS = [
9
+ 'skills',
10
+ 'commands',
11
+ 'mcp',
12
+ 'hooks',
13
+ 'rules',
14
+ 'plugins',
15
+ 'workflows',
16
+ 'subagents',
17
+ ];
18
+ const KIND_LABELS = {
19
+ skills: 'Skills',
20
+ commands: 'Commands',
21
+ mcp: 'MCP',
22
+ hooks: 'Hooks',
23
+ rules: 'Rules',
24
+ plugins: 'Plugins',
25
+ workflows: 'Workflows',
26
+ subagents: 'Subagents',
27
+ };
28
+ export function registerResourcesCommand(program) {
29
+ program
30
+ .command('resources')
31
+ .description('Show the merged DotAgents resources resolved across project, user, system, and extras')
32
+ .option('--merged', 'Show the merged first-wins resource surface (default)')
33
+ .addHelpText('after', `
34
+ Examples:
35
+ agents resources
36
+ agents resources --merged
37
+ `)
38
+ .action((options) => {
39
+ void options;
40
+ renderMergedResources();
41
+ });
42
+ }
43
+ function renderMergedResources() {
44
+ const groups = DRILLABLE_KINDS.map((kind) => ({
45
+ kind,
46
+ rows: listResources(kind),
47
+ }));
48
+ const total = groups.reduce((sum, group) => sum + group.rows.length, 0);
49
+ if (total === 0) {
50
+ console.log(chalk.gray('No merged resources found.'));
51
+ return;
52
+ }
53
+ console.log(chalk.bold(`Resources (${total} merged)`));
54
+ for (const group of groups) {
55
+ console.log();
56
+ console.log(chalk.bold(`${KIND_LABELS[group.kind]} (${group.rows.length})`));
57
+ if (group.rows.length === 0) {
58
+ console.log(chalk.gray(' none'));
59
+ continue;
60
+ }
61
+ for (const line of renderResourceRows(group.rows))
62
+ console.log(line);
63
+ }
64
+ }
65
+ function renderResourceRows(rows) {
66
+ const nameW = Math.min(28, Math.max('Name'.length, ...rows.map((row) => stringWidth(row.name))));
67
+ const layerW = Math.min(16, Math.max('Layer'.length, ...rows.map((row) => stringWidth(row.source))));
68
+ const prefixW = 2 + nameW + 2 + layerW + 2;
69
+ const pathW = Math.max(12, terminalWidth() - prefixW);
70
+ const lines = [
71
+ ` ${chalk.bold(pad(row('Name', nameW), nameW))} ${chalk.bold(pad(row('Layer', layerW), layerW))} ${chalk.bold('Path')}`,
72
+ ` ${chalk.gray(`${'-'.repeat(nameW)} ${'-'.repeat(layerW)} ${'-'.repeat(Math.min(pathW, 40))}`)}`,
73
+ ];
74
+ for (const resource of rows) {
75
+ lines.push(` ${chalk.cyan(pad(truncateToWidth(resource.name, nameW), nameW))} ${pad(resource.source, layerW)} ${chalk.gray(truncateToWidth(formatPath(resource.path), pathW))}`);
76
+ }
77
+ return lines;
78
+ }
79
+ function row(value, width) {
80
+ return truncateToWidth(value, width);
81
+ }
82
+ function pad(value, width) {
83
+ return value + ' '.repeat(Math.max(0, width - stringWidth(value)));
84
+ }
85
+ function formatPath(value) {
86
+ const home = process.env.HOME;
87
+ if (home) {
88
+ const rel = path.relative(home, value);
89
+ if (rel === '')
90
+ return '~';
91
+ if (!rel.startsWith('..') && !path.isAbsolute(rel))
92
+ return `~/${rel}`;
93
+ }
94
+ return value;
95
+ }
@@ -6,11 +6,13 @@
6
6
  * Also exposes scheduler lifecycle controls (start/stop/status/logs).
7
7
  */
8
8
  import type { Command } from 'commander';
9
+ import type { RunMeta } from '../lib/routines.js';
9
10
  /**
10
11
  * Human-friendly wall-clock a run took (e.g. " · 3 min", " · 45 sec"), or ""
11
12
  * when it hasn't completed or timestamps are unparseable. Leading separator lets
12
13
  * callers drop it straight into a status line.
13
14
  */
14
15
  export declare function formatRunDuration(startedAt: string, completedAt: string | null): string;
16
+ export declare function buildRunsJson(runs: RunMeta[]): Record<string, unknown>[];
15
17
  /** Register the `agents routines` command tree. */
16
18
  export declare function registerRoutinesCommands(program: Command): void;