@phnx-labs/agents-cli 1.22.75 → 1.22.76

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 (132) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/README.md +20 -8
  3. package/dist/bootstrap.js +7 -7
  4. package/dist/cli/command-registry.js +5 -0
  5. package/dist/commands/artifacts-setup.js +1 -1
  6. package/dist/commands/artifacts.js +1 -1
  7. package/dist/commands/auth.js +7 -1
  8. package/dist/commands/browser.js +104 -10
  9. package/dist/commands/commands.js +7 -6
  10. package/dist/commands/config.js +27 -4
  11. package/dist/commands/cost.js +6 -4
  12. package/dist/commands/doctor.d.ts +6 -5
  13. package/dist/commands/doctor.js +32 -274
  14. package/dist/commands/exec.d.ts +2 -0
  15. package/dist/commands/exec.js +9 -2
  16. package/dist/commands/harness.d.ts +1 -0
  17. package/dist/commands/harness.js +11 -3
  18. package/dist/commands/hooks.js +7 -6
  19. package/dist/commands/mcp.js +7 -6
  20. package/dist/commands/memory.js +7 -7
  21. package/dist/commands/monitors.js +3 -2
  22. package/dist/commands/open.d.ts +25 -12
  23. package/dist/commands/open.js +24 -10
  24. package/dist/commands/permissions.js +7 -6
  25. package/dist/commands/plugins.js +21 -17
  26. package/dist/commands/route.js +33 -16
  27. package/dist/commands/rules.js +7 -12
  28. package/dist/commands/sessions-share.js +1 -1
  29. package/dist/commands/setup-watchdog.js +2 -2
  30. package/dist/commands/setup.js +22 -1
  31. package/dist/commands/share.js +26 -10
  32. package/dist/commands/skills.js +7 -6
  33. package/dist/commands/subagents.js +7 -6
  34. package/dist/commands/sync.js +81 -10
  35. package/dist/commands/view.js +4 -1
  36. package/dist/commands/watchdog.d.ts +1 -1
  37. package/dist/commands/watchdog.js +10 -10
  38. package/dist/commands/webhook.d.ts +4 -0
  39. package/dist/commands/webhook.js +22 -4
  40. package/dist/commands/workflows.js +7 -6
  41. package/dist/lib/accounting/rotate.d.ts +3 -1
  42. package/dist/lib/accounting/rotate.js +8 -4
  43. package/dist/lib/auth-health.d.ts +2 -0
  44. package/dist/lib/auth-health.js +2 -0
  45. package/dist/lib/browser/chrome.d.ts +21 -0
  46. package/dist/lib/browser/chrome.js +60 -3
  47. package/dist/lib/browser/drivers/local.d.ts +21 -0
  48. package/dist/lib/browser/drivers/local.js +102 -9
  49. package/dist/lib/browser/profiles.d.ts +29 -1
  50. package/dist/lib/browser/profiles.js +50 -1
  51. package/dist/lib/browser/types.d.ts +18 -0
  52. package/dist/lib/config-keys.d.ts +7 -2
  53. package/dist/lib/config-keys.js +17 -2
  54. package/dist/lib/daemon/daemon.js +8 -0
  55. package/dist/lib/daemon/session-summarizer-service.d.ts +24 -0
  56. package/dist/lib/daemon/session-summarizer-service.js +39 -0
  57. package/dist/lib/daemon-services.d.ts +1 -1
  58. package/dist/lib/daemon-services.js +5 -0
  59. package/dist/lib/daemon-ticks.d.ts +2 -2
  60. package/dist/lib/daemon-ticks.js +2 -1
  61. package/dist/lib/deeplink/register.js +10 -9
  62. package/dist/lib/deeplink/url.d.ts +4 -4
  63. package/dist/lib/deeplink/url.js +4 -4
  64. package/dist/lib/device-config.js +25 -0
  65. package/dist/lib/devices/doctor-findings.d.ts +4 -4
  66. package/dist/lib/devices/doctor-findings.js +14 -8
  67. package/dist/lib/devices/registry.js +2 -0
  68. package/dist/lib/devices/stats-cache.d.ts +4 -0
  69. package/dist/lib/devices/stats-cache.js +19 -0
  70. package/dist/lib/drift-sync.d.ts +3 -1
  71. package/dist/lib/drift-sync.js +16 -5
  72. package/dist/lib/exec.d.ts +2 -0
  73. package/dist/lib/exec.js +16 -1
  74. package/dist/lib/fleet-shared-state.d.ts +8 -0
  75. package/dist/lib/heal.d.ts +4 -3
  76. package/dist/lib/heal.js +5 -4
  77. package/dist/lib/hosts/ready.d.ts +1 -1
  78. package/dist/lib/hosts/ready.js +16 -4
  79. package/dist/lib/hosts/reconnect.js +4 -2
  80. package/dist/lib/identity/client.d.ts +6 -0
  81. package/dist/lib/identity/index.d.ts +16 -0
  82. package/dist/lib/identity/index.js +25 -1
  83. package/dist/lib/profiles.d.ts +2 -0
  84. package/dist/lib/profiles.js +28 -9
  85. package/dist/lib/reconcile-and-repair.d.ts +109 -0
  86. package/dist/lib/reconcile-and-repair.js +267 -0
  87. package/dist/lib/routers.d.ts +12 -1
  88. package/dist/lib/routers.js +30 -1
  89. package/dist/lib/scheduling/routines.js +8 -2
  90. package/dist/lib/session/active.d.ts +13 -0
  91. package/dist/lib/session/db.d.ts +47 -7
  92. package/dist/lib/session/db.js +114 -12
  93. package/dist/lib/session/mirror.js +58 -0
  94. package/dist/lib/session/remote/watch.js +22 -2
  95. package/dist/lib/session/session-cache.d.ts +19 -0
  96. package/dist/lib/session/session-cache.js +46 -0
  97. package/dist/lib/session/types.d.ts +34 -0
  98. package/dist/lib/share/backend.d.ts +6 -4
  99. package/dist/lib/share/backend.js +10 -8
  100. package/dist/lib/share/config.d.ts +4 -3
  101. package/dist/lib/share/config.js +10 -1
  102. package/dist/lib/share/delete.d.ts +1 -1
  103. package/dist/lib/share/delete.js +1 -1
  104. package/dist/lib/share/html.d.ts +1 -1
  105. package/dist/lib/share/html.js +1 -1
  106. package/dist/lib/share/provision.d.ts +1 -1
  107. package/dist/lib/share/provision.js +2 -2
  108. package/dist/lib/share/publish.d.ts +23 -7
  109. package/dist/lib/share/publish.js +58 -12
  110. package/dist/lib/share/worker-template.js +221 -60
  111. package/dist/lib/startup/command-registry.js +2 -2
  112. package/dist/lib/state.d.ts +15 -0
  113. package/dist/lib/state.js +29 -7
  114. package/dist/lib/summarizer/config.d.ts +46 -0
  115. package/dist/lib/summarizer/config.js +83 -0
  116. package/dist/lib/summarizer/pass.d.ts +45 -0
  117. package/dist/lib/summarizer/pass.js +112 -0
  118. package/dist/lib/summarizer/summarize.d.ts +68 -0
  119. package/dist/lib/summarizer/summarize.js +120 -0
  120. package/dist/lib/teams/agents.d.ts +4 -3
  121. package/dist/lib/teams/agents.js +12 -4
  122. package/dist/lib/teams/scheduler.d.ts +4 -2
  123. package/dist/lib/teams/scheduler.js +6 -6
  124. package/dist/lib/tmux/session.d.ts +2 -0
  125. package/dist/lib/tmux/session.js +7 -1
  126. package/dist/lib/types.d.ts +20 -0
  127. package/dist/lib/verbs.d.ts +23 -0
  128. package/dist/lib/verbs.js +24 -0
  129. package/dist/lib/view-types.d.ts +4 -0
  130. package/dist/lib/watchdog/rotate.d.ts +1 -1
  131. package/dist/lib/watchdog/rotate.js +1 -1
  132. package/package.json +1 -1
@@ -4,6 +4,7 @@
4
4
  * Mirrors the skills surface at list / add / remove / view / sync scale.
5
5
  * Canonical storage: ~/.agents/memory/ (project > user > system layering).
6
6
  */
7
+ import { withAliases } from '../lib/verbs.js';
7
8
  import chalk from 'chalk';
8
9
  import * as fs from 'fs';
9
10
  import { listMemoryFacts, addMemoryFact, removeMemoryFact, readMemoryFact, ensureUserMemoryDir, getUserMemoryDir, syncMemoryToVersionHome, } from '../lib/memory.js';
@@ -42,8 +43,8 @@ export function registerMemoryCommands(program) {
42
43
  Format: MEMORY.md index + one <slug>.md file per fact.
43
44
  `,
44
45
  });
45
- memoryCmd
46
- .command('list')
46
+ withAliases(memoryCmd
47
+ .command('list'), 'list')
47
48
  .description('List memory facts from project, user, and system layers')
48
49
  .option('--json', 'Emit machine-readable JSON')
49
50
  .action((options) => {
@@ -86,9 +87,8 @@ export function registerMemoryCommands(program) {
86
87
  console.log(chalk.gray(' Run: agents memory sync (or agents sync) to fan out'));
87
88
  }
88
89
  });
89
- memoryCmd
90
- .command('remove <name>')
91
- .alias('rm')
90
+ withAliases(memoryCmd
91
+ .command('remove <name>'), 'remove')
92
92
  .description('Remove a user-layer memory fact')
93
93
  .action((name) => {
94
94
  if (removeMemoryFact(name)) {
@@ -99,8 +99,8 @@ export function registerMemoryCommands(program) {
99
99
  process.exit(1);
100
100
  }
101
101
  });
102
- memoryCmd
103
- .command('view <name>')
102
+ withAliases(memoryCmd
103
+ .command('view <name>'), 'view')
104
104
  .description('Print a memory fact (winning layer)')
105
105
  .action((name) => {
106
106
  const fact = readMemoryFact(name, process.cwd());
@@ -8,6 +8,7 @@
8
8
  * source instead of a clock.
9
9
  */
10
10
  import chalk from 'chalk';
11
+ import { withAliases } from '../lib/verbs.js';
11
12
  import * as fs from 'fs';
12
13
  import * as path from 'path';
13
14
  import * as yaml from 'yaml';
@@ -1184,8 +1185,8 @@ export function registerMonitorsCommands(program) {
1184
1185
  console.log(chalk.gray(' Re-pin with: agents monitors device ' + name + ' --set <device>'));
1185
1186
  });
1186
1187
  // ─── remove ────────────────────────────────────────────────────────────────────
1187
- monitorsCmd
1188
- .command('remove [name]')
1188
+ withAliases(monitorsCmd
1189
+ .command('remove [name]'), 'remove')
1189
1190
  .description('Delete a monitor. Stops watching; past fire history remains on disk.')
1190
1191
  .action(async (name) => {
1191
1192
  if (!name) {
@@ -1,18 +1,31 @@
1
1
  /**
2
- * `agents open` — resolve an `agents://` deep link, and manage the OS handler
3
- * that routes such links here.
2
+ * `agents _callback` — the machine-only OS callback for `agents://` deep links.
4
3
  *
5
- * agents open agents://session/<id> resume that session in a terminal
6
- * agents open register register the agents:// scheme with the OS
7
- * agents open unregister remove the handler
8
- * agents open status report whether the handler is registered
4
+ * agents _callback agents://session/<id> resume that session in a terminal
9
5
  *
10
- * A rendered artifact (plan/report) embeds `agents://session/<id>` in its
11
- * provenance line; clicking it hands the URL to the OS, which invokes
12
- * `agents open <url>`. This command parses it (lib/deeplink/url.ts) and hands the
13
- * session id to the existing resume dispatcher, which resolves the owning host
14
- * and opens the terminal with the cursor in the input bar. The id is passed as
15
- * argv, never interpolated into a shell.
6
+ * This is NOT a user command: humans resume with `agents sessions resume`, and
7
+ * manage the OS URL-scheme handler with `agents setup url-scheme`. The bare-URL
8
+ * verb exists only because a rendered artifact (plan/report) embeds
9
+ * `agents://session/<id>` in its provenance line; clicking it hands the URL to
10
+ * the OS, which invokes the registered handler — `agents _callback <url>`. This
11
+ * command parses it (lib/deeplink/url.ts) and hands the session id to the
12
+ * existing resume dispatcher, which resolves the owning host and opens the
13
+ * terminal with the cursor in the input bar. The id is passed as argv, never
14
+ * interpolated into a shell.
15
+ *
16
+ * The command is hidden. `open` is kept as a HIDDEN alias so machines whose OS
17
+ * handler was written by an older CLI (which emitted `agents open <url>`) keep
18
+ * resolving until `agents setup url-scheme register` re-writes the handler to the
19
+ * `_callback` verb. Dropping `open` would break every previously-registered link.
16
20
  */
17
21
  import type { Command } from 'commander';
18
22
  export declare function registerOpenCommand(program: Command): void;
23
+ /**
24
+ * Attach `register` / `unregister` / `status` subcommands that manage the
25
+ * `agents://` OS URL-scheme handler onto `parent`. One implementation, mounted
26
+ * both under the hidden `_callback` command (back-compat) and under the visible
27
+ * `agents setup url-scheme` group.
28
+ */
29
+ export declare function addUrlSchemeSubcommands(parent: Command, opts?: {
30
+ hidden?: boolean;
31
+ }): void;
@@ -2,18 +2,32 @@ import chalk from 'chalk';
2
2
  import { parseAgentsUrl } from '../lib/deeplink/url.js';
3
3
  import { registerAgentsUrlScheme, unregisterAgentsUrlScheme, agentsUrlSchemeStatus, } from '../lib/deeplink/register.js';
4
4
  export function registerOpenCommand(program) {
5
- const open = program
6
- .command('open [url]')
7
- .description('Resume a session from an agents:// deep link, or register/unregister/status the OS URL-scheme handler.')
5
+ const callback = program
6
+ .command('_callback [url]', { hidden: true })
7
+ .alias('open')
8
+ .description('OS callback that resumes a session from an agents:// deep link (machine-only; humans use `agents sessions resume`).')
8
9
  .action(async (url) => {
9
10
  if (!url) {
10
- open.help();
11
+ callback.help();
11
12
  return;
12
13
  }
13
14
  await handleUrl(url);
14
15
  });
15
- open
16
- .command('register')
16
+ // Back-compat: `agents open register|unregister|status` still work as HIDDEN
17
+ // subcommands (muscle memory + docs). The canonical, visible home is
18
+ // `agents setup url-scheme <verb>`, which reuses the SAME builder below.
19
+ addUrlSchemeSubcommands(callback, { hidden: true });
20
+ }
21
+ /**
22
+ * Attach `register` / `unregister` / `status` subcommands that manage the
23
+ * `agents://` OS URL-scheme handler onto `parent`. One implementation, mounted
24
+ * both under the hidden `_callback` command (back-compat) and under the visible
25
+ * `agents setup url-scheme` group.
26
+ */
27
+ export function addUrlSchemeSubcommands(parent, opts = {}) {
28
+ const hidden = opts.hidden ?? false;
29
+ parent
30
+ .command('register', { hidden })
17
31
  .description('Register the agents:// URL scheme with the OS so artifact links resume sessions (idempotent).')
18
32
  .action(() => {
19
33
  const status = registerAgentsUrlScheme();
@@ -25,15 +39,15 @@ export function registerOpenCommand(program) {
25
39
  process.exitCode = 1;
26
40
  }
27
41
  });
28
- open
29
- .command('unregister')
42
+ parent
43
+ .command('unregister', { hidden })
30
44
  .description('Remove the agents:// URL scheme handler.')
31
45
  .action(() => {
32
46
  const status = unregisterAgentsUrlScheme();
33
47
  console.log(chalk.gray(status.detail));
34
48
  });
35
- open
36
- .command('status')
49
+ parent
50
+ .command('status', { hidden })
37
51
  .description('Report whether the agents:// URL scheme handler is registered.')
38
52
  .action(() => {
39
53
  const status = agentsUrlSchemeStatus();
@@ -1,3 +1,4 @@
1
+ import { withAliases } from '../lib/verbs.js';
1
2
  import chalk from 'chalk';
2
3
  import ora from 'ora';
3
4
  import { terminalWidth, truncateToWidth, stringWidth } from '../lib/session/width.js';
@@ -44,8 +45,8 @@ When to use:
44
45
  - Team sync: share permission sets via 'agents permissions add gh:team/perms'
45
46
  - Version isolation: apply stricter permissions to experimental versions
46
47
  `);
47
- permissionsCmd
48
- .command('list [agent]')
48
+ withAliases(permissionsCmd
49
+ .command('list [agent]'), 'list')
49
50
  .description('Show permission sets in storage or active permissions for an agent version')
50
51
  .option('-s, --scope <scope>', 'user (global) or project (repo-specific)', 'user')
51
52
  .action(async (agentArg, options) => {
@@ -642,8 +643,8 @@ Examples:
642
643
  console.error(chalk.red(`Error: ${err.message}`));
643
644
  }
644
645
  });
645
- permissionsCmd
646
- .command('remove [name]')
646
+ withAliases(permissionsCmd
647
+ .command('remove [name]'), 'remove')
647
648
  .description('Delete a permission set from ~/.agents/permissions/ (interactive picker if no name given)')
648
649
  .addHelpText('after', `
649
650
  Examples:
@@ -704,8 +705,8 @@ Examples:
704
705
  }
705
706
  }
706
707
  });
707
- permissionsCmd
708
- .command('view [name]')
708
+ withAliases(permissionsCmd
709
+ .command('view [name]'), 'view')
709
710
  .description('Read the allow and deny rules for a stored permission set')
710
711
  .addHelpText('after', `
711
712
  Examples:
@@ -7,6 +7,7 @@
7
7
  */
8
8
  import * as fs from 'fs';
9
9
  import * as path from 'path';
10
+ import { withAliases } from '../lib/verbs.js';
10
11
  import chalk from 'chalk';
11
12
  import { homeDir } from '../lib/platform/index.js';
12
13
  import { input } from '@inquirer/prompts';
@@ -86,8 +87,8 @@ When to use:
86
87
  // flag to the parent for `plugins list --json`, dropping it from the subcommand.)
87
88
  pluginsCmd.action(runList);
88
89
  // agents plugins list
89
- pluginsCmd
90
- .command('list')
90
+ withAliases(pluginsCmd
91
+ .command('list'), 'list')
91
92
  .description('Show plugins in a table with sync status across agent versions')
92
93
  .option('--json', 'Emit machine-readable JSON')
93
94
  .action(runList);
@@ -127,10 +128,10 @@ When to use:
127
128
  .description(`Redirects to 'agents repo ${verb}' — marketplaces follow repos`)
128
129
  .action(marketplaceRedirect(verb));
129
130
  }
130
- // agents plugins info [name]
131
- pluginsCmd
132
- .command('info [name]')
133
- .alias('view')
131
+ // agents plugins view [name]
132
+ withAliases(pluginsCmd
133
+ .command('view [name]'), 'view')
134
+ .alias('info')
134
135
  .description('Show plugin metadata, resources, and installation status across agent versions')
135
136
  .addHelpText('after', `
136
137
  Examples:
@@ -150,8 +151,8 @@ Examples:
150
151
  return;
151
152
  }
152
153
  if (!isInteractiveTerminal()) {
153
- requireInteractiveSelection('Picking a plugin for `agents plugins info`', [
154
- 'agents plugins info <name>',
154
+ requireInteractiveSelection('Picking a plugin for `agents plugins view`', [
155
+ 'agents plugins view <name>',
155
156
  'agents plugins # to see installed plugins',
156
157
  ]);
157
158
  }
@@ -375,8 +376,8 @@ Examples:
375
376
  }
376
377
  });
377
378
  // agents plugins remove [name]
378
- pluginsCmd
379
- .command('remove [name]')
379
+ withAliases(pluginsCmd
380
+ .command('remove [name]'), 'remove')
380
381
  .description('Unsync a plugin from all agent versions and optionally delete its source directory')
381
382
  .option('--keep-source', 'Keep the directory at ~/.agents/plugins/<name> (only unsync from agents)')
382
383
  .addHelpText('after', `
@@ -493,22 +494,25 @@ Examples:
493
494
  console.log(chalk.gray(`Kept source at ${formatPath(pluginRoot)}`));
494
495
  }
495
496
  });
496
- // agents plugins install <spec>
497
+ // agents plugins add <spec>
497
498
  pluginsCmd
498
- .command('install <spec>')
499
- .alias('add')
499
+ .command('add <spec>')
500
+ .alias('install')
500
501
  .description('Install a plugin from a git URL or local path (format: name@source or source)')
501
502
  .option('--allow-exec-surfaces', 'Allow installing plugins that ship executable surfaces')
502
503
  .addHelpText('after', `
503
504
  Examples:
504
505
  # Install from a git URL
505
- agents plugins install my-plugin@https://github.com/user/my-plugin.git
506
+ agents plugins add my-plugin@https://github.com/user/my-plugin.git
506
507
 
507
508
  # Install from a local path
508
- agents plugins install /path/to/plugin
509
+ agents plugins add /path/to/plugin
509
510
 
510
511
  # Named install from a local path
511
- agents plugins install rush-toolkit@~/Projects/rush-toolkit
512
+ agents plugins add rush-toolkit@~/Projects/rush-toolkit
513
+
514
+ # 'install' is kept as an alias
515
+ agents plugins install /path/to/plugin
512
516
  `)
513
517
  .action(async (spec, options) => {
514
518
  console.log(chalk.gray(`Installing plugin from: ${spec}`));
@@ -545,7 +549,7 @@ Examples:
545
549
  const missingDeps = checkPluginDependencies(plugin.manifest);
546
550
  if (missingDeps.length > 0) {
547
551
  console.log(chalk.yellow(`Warning: missing dependencies: ${missingDeps.join(', ')}`));
548
- console.log(chalk.gray('Install them with: agents plugins install <name>@<source>'));
552
+ console.log(chalk.gray('Install them with: agents plugins add <name>@<source>'));
549
553
  }
550
554
  // Prompt for userConfig fields
551
555
  if (plugin.manifest.userConfig && plugin.manifest.userConfig.length > 0 && isInteractiveTerminal()) {
@@ -9,7 +9,8 @@
9
9
  * invoking a router to route a task is a separate ticket.
10
10
  */
11
11
  import chalk from 'chalk';
12
- import { listRouters, readRouter, writeRouter, deleteRouter, routerExists, routerSource, routersDir, validateRouter, } from '../lib/routers.js';
12
+ import { withAliases } from '../lib/verbs.js';
13
+ import { listRouters, readRouter, writeRouter, deleteRouter, renameRouter, routerExists, routerSource, routersDir, validateRouter, } from '../lib/routers.js';
13
14
  import { MODEL_TIERS, isTierToken } from '../lib/model-tiers.js';
14
15
  import { die } from '../lib/format.js';
15
16
  import { setHelpSections } from '../lib/help.js';
@@ -89,11 +90,12 @@ function printRouterDetail(router) {
89
90
  export function registerRouteCommands(program) {
90
91
  const routeCmd = program
91
92
  .command('route')
93
+ .alias('routes')
92
94
  .description('Named routers -- reusable, task-typed allowlists of harnesses x models/tiers x linked accounts.');
93
95
  setHelpSections(routeCmd, {
94
96
  examples: `
95
97
  # Create a router scoped to two harnesses, capped at a tier
96
- agents route create research --harness gemini,kimi --tier cheap,default
98
+ agents route add research --harness gemini,kimi --tier cheap,default
97
99
 
98
100
  # Narrow one harness's model set
99
101
  agents route allow research kimi kimi-k2
@@ -102,8 +104,9 @@ export function registerRouteCommands(program) {
102
104
  agents route link-account research gemini personal
103
105
  agents route link-account research kimi work
104
106
 
105
- # Inspect it
106
- agents route show research
107
+ # Inspect, rename, remove it
108
+ agents route view research
109
+ agents route rename research deep-research
107
110
  agents route list --json
108
111
  `,
109
112
  notes: `
@@ -112,12 +115,16 @@ export function registerRouteCommands(program) {
112
115
  outside its declared harness/model/tier allowlist or linked accounts.
113
116
 
114
117
  Routers are a layered resource (project > user > system, like commands,
115
- skills, and profiles) but 'agents route create'/'allow'/'link-account'
118
+ skills, and profiles) but 'agents route add'/'allow'/'link-account'
116
119
  always write to the user layer (~/.agents/routers/<name>.yml).
120
+
121
+ The older verb names still work as aliases: 'create' for 'add',
122
+ 'show' for 'view'.
117
123
  `,
118
124
  });
119
125
  routeCmd
120
- .command('create <name>')
126
+ .command('add <name>')
127
+ .alias('create')
121
128
  .description('Create a named router with an initial harness + tier allowlist.')
122
129
  .option('--harness <list>', 'Comma-separated harness ids to allow, e.g. gemini,kimi')
123
130
  .option('--tier <list>', 'Comma-separated tier tokens applied to every listed harness, e.g. cheap,default')
@@ -127,7 +134,7 @@ export function registerRouteCommands(program) {
127
134
  die(`Router '${name}' already exists. Use 'agents route allow ${name} <harness> <model|tier>...' to edit it.`);
128
135
  }
129
136
  if (!opts.harness) {
130
- die("Missing --harness. Example: agents route create research --harness gemini,kimi --tier cheap,default");
137
+ die("Missing --harness. Example: agents route add research --harness gemini,kimi --tier cheap,default");
131
138
  }
132
139
  const harnesses = opts.harness.split(',').map((h) => h.trim()).filter(Boolean);
133
140
  const tiers = (opts.tier ?? '').split(',').map((t) => t.trim()).filter(Boolean);
@@ -145,8 +152,8 @@ export function registerRouteCommands(program) {
145
152
  writeRouter(router);
146
153
  console.log(chalk.green(`+ created router "${name}"`) + chalk.gray(` (${path.join(routersDir(), `${name}.yml`)})`));
147
154
  });
148
- routeCmd
149
- .command('list')
155
+ withAliases(routeCmd
156
+ .command('list'), 'list')
150
157
  .description('List every configured router.')
151
158
  .option('--json', 'Emit machine-readable JSON')
152
159
  .action((opts) => {
@@ -163,15 +170,14 @@ export function registerRouteCommands(program) {
163
170
  }
164
171
  if (routers.length === 0) {
165
172
  console.log(chalk.gray('No routers configured.'));
166
- console.log(chalk.gray('Try: agents route create research --harness gemini,kimi --tier cheap,default'));
173
+ console.log(chalk.gray('Try: agents route add research --harness gemini,kimi --tier cheap,default'));
167
174
  return;
168
175
  }
169
176
  for (const router of routers)
170
177
  console.log(renderRouterRow(router));
171
178
  });
172
- routeCmd
173
- .command('show <name>')
174
- .alias('view')
179
+ withAliases(routeCmd
180
+ .command('view <name>'), 'view')
175
181
  .description("Show a router's harness/model/account allowlist, weights, and hijack flag.")
176
182
  .option('--json', 'Emit machine-readable JSON')
177
183
  .action((name, opts) => {
@@ -242,9 +248,20 @@ export function registerRouteCommands(program) {
242
248
  writeRouter(router);
243
249
  console.log(chalk.green(`Router '${name}': unlinked ${harness} account '${account}'`));
244
250
  });
245
- routeCmd
246
- .command('remove <name>')
247
- .alias('rm')
251
+ withAliases(routeCmd
252
+ .command('rename <old-name> <new-name>'), 'rename')
253
+ .description('Rename a router, preserving every field (allowlists, weights, accounts, hijack). Errors on a name collision.')
254
+ .action((oldName, newName) => {
255
+ try {
256
+ renameRouter(oldName, newName);
257
+ console.log(chalk.green(`Router '${oldName}' renamed to '${newName}'.`));
258
+ }
259
+ catch (err) {
260
+ die(err.message);
261
+ }
262
+ });
263
+ withAliases(routeCmd
264
+ .command('remove <name>'), 'remove')
248
265
  .description('Remove a router.')
249
266
  .action((name) => {
250
267
  const source = routerSource(name);
@@ -1,3 +1,4 @@
1
+ import { withAliases } from '../lib/verbs.js';
1
2
  import chalk from 'chalk';
2
3
  import ora from 'ora';
3
4
  import * as fs from 'fs';
@@ -57,8 +58,8 @@ Project rules & @-imports:
57
58
  For rules that need to work across all agents, inline the content rather than using
58
59
  @-imports — the second group will load '@path/to/file.md' as a literal string.
59
60
  `);
60
- rulesCmd
61
- .command('list [agent]')
61
+ withAliases(rulesCmd
62
+ .command('list [agent]'), 'list')
62
63
  .description('Show which rule files are installed. Pass agent@version to see a specific version.')
63
64
  .option('-a, --agent <agent>', 'Filter to a specific agent (alternative to positional arg)')
64
65
  .action(async (agentArg, options) => {
@@ -364,8 +365,8 @@ Examples:
364
365
  process.exit(1);
365
366
  }
366
367
  });
367
- rulesCmd
368
- .command('view [agent]')
368
+ withAliases(rulesCmd
369
+ .command('view [agent]'), 'view')
369
370
  .description('Read the full content of a rule file with markdown rendering')
370
371
  .option('-s, --scope <scope>', 'user (global) or project (repo-specific)', 'user')
371
372
  .addHelpText('after', `
@@ -446,8 +447,8 @@ Examples:
446
447
  const filePath = instr?.path || '';
447
448
  await displayContent(content, `${agentLabel(agentId)} Rules (${scope})`, filePath);
448
449
  });
449
- rulesCmd
450
- .command('remove [agent]')
450
+ withAliases(rulesCmd
451
+ .command('remove [agent]'), 'remove')
451
452
  .description('Delete user-level rule files for an agent or version')
452
453
  .addHelpText('after', `
453
454
  Examples:
@@ -605,10 +606,4 @@ Examples:
605
606
  process.exit(1);
606
607
  }
607
608
  });
608
- rulesCmd
609
- .command('show [agent]', { hidden: true })
610
- .action(async (agentArg) => {
611
- console.log(chalk.yellow('Deprecated: Use "agents rules view" instead of "agents rules show"\n'));
612
- await rulesCmd.commands.find((c) => c.name() === 'view')?.parseAsync(['view', ...(agentArg ? [agentArg] : [])], { from: 'user' });
613
- });
614
609
  }
@@ -68,7 +68,7 @@ export function registerSessionsShareCommand(sessionsCmd) {
68
68
  examples: `# Share a session — prints an unlisted, redacted link
69
69
  agents sessions share a1b2c3d4
70
70
 
71
- # Put it in your public gallery at share.agents-cli.sh/<you>
71
+ # Put it in your public gallery at share.getrush.ai/<you>
72
72
  agents sessions share a1b2c3d4 --public --label "How the retry bug got fixed"
73
73
 
74
74
  # Keep the model's reasoning in collapsible sections
@@ -10,7 +10,7 @@ export async function runWatchdogSetupWizard() {
10
10
  const devices = [...new Set([...Object.keys(registry), machineId()].map(normalizeHost))].sort();
11
11
  const enabled = new Set(devices.filter((device) => getConfigValue('watchdog.enabled', { device }).value === true));
12
12
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
13
- requireInteractiveSelection('watchdog devices', ['agents watchdog on', 'agents watchdog on --device <device>']);
13
+ requireInteractiveSelection('watchdog devices', ['agents watchdog enable', 'agents watchdog enable --device <device>']);
14
14
  }
15
15
  try {
16
16
  const { checkbox } = await import('@inquirer/prompts');
@@ -25,7 +25,7 @@ export async function runWatchdogSetupWizard() {
25
25
  setConfigValue('watchdog.enabled', on);
26
26
  continue;
27
27
  }
28
- const launch = getCliLaunch(['watchdog', on ? 'on' : 'off', '--device', device]);
28
+ const launch = getCliLaunch(['watchdog', on ? 'enable' : 'disable', '--device', device]);
29
29
  const result = spawnSync(launch.command, launch.args, { stdio: 'inherit', env: process.env });
30
30
  if ((result.status ?? 1) !== 0)
31
31
  throw new Error(`Could not configure watchdog on ${device}`);
@@ -29,6 +29,7 @@ import { registerSetupWatchdogCommand, runWatchdogSetupWizard } from './setup-wa
29
29
  import { hasMintedSetupToken } from '../lib/auth-mint.js';
30
30
  import { registerAliasCommand } from './alias.js';
31
31
  import { registerBetaCommands } from './beta.js';
32
+ import { addUrlSchemeSubcommands } from './open.js';
32
33
  import { runPreferencesStep } from './setup-preferences.js';
33
34
  import { getConfiguredDefaultProfileName, getProfile, getAutoDetectedProfile, isProfileLaunchableHere } from '../lib/browser/profiles.js';
34
35
  import { listInstalledBrowsers } from '../lib/browser/chrome.js';
@@ -228,7 +229,7 @@ export async function runSetup(program, options = {}) {
228
229
  console.log(chalk.gray('Registered the agents:// URL scheme (artifact session deep links).'));
229
230
  }
230
231
  catch {
231
- // non-fatal — the user can run `agents open register` later.
232
+ // non-fatal — the user can run `agents setup url-scheme register` later.
232
233
  }
233
234
  if (options.suppressFooter)
234
235
  return;
@@ -382,6 +383,26 @@ export function registerSetupCommand(program) {
382
383
  registerSetupWatchdogCommand(setupCmd);
383
384
  registerAliasCommand(setupCmd);
384
385
  registerBetaCommands(setupCmd);
386
+ // `agents setup url-scheme register|unregister|status` — the canonical, visible
387
+ // home for the agents:// OS handler that routes artifact deep links to the
388
+ // machine-only `agents _callback` verb. Reuses the same builder the hidden
389
+ // `agents open` back-compat subcommands mount.
390
+ const urlScheme = setupCmd
391
+ .command('url-scheme')
392
+ .description('Register/unregister/status the agents:// OS URL-scheme handler for artifact session deep links.');
393
+ addUrlSchemeSubcommands(urlScheme, { hidden: false });
394
+ setHelpSections(urlScheme, {
395
+ examples: `
396
+ # Register the handler so agents:// links in rendered artifacts resume sessions
397
+ agents setup url-scheme register
398
+
399
+ # Check whether the handler is registered on this machine
400
+ agents setup url-scheme status
401
+
402
+ # Remove the handler
403
+ agents setup url-scheme unregister
404
+ `,
405
+ });
385
406
  setupCmd.command('status')
386
407
  .description('Show setup readiness for core, browser, computer, secrets, accounts, fleet, share, watchdog, and preferences.')
387
408
  .option('--json', 'print machine-readable JSON')