@phnx-labs/agents-cli 1.22.75 → 1.22.77
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/CHANGELOG.md +121 -0
- package/README.md +20 -8
- package/dist/bootstrap.js +7 -7
- package/dist/cli/command-registry.js +5 -0
- package/dist/commands/artifacts-setup.js +1 -1
- package/dist/commands/artifacts.js +1 -1
- package/dist/commands/auth.js +7 -1
- package/dist/commands/browser.js +104 -10
- package/dist/commands/commands.js +7 -6
- package/dist/commands/config.js +27 -4
- package/dist/commands/cost.js +6 -4
- package/dist/commands/doctor.d.ts +6 -5
- package/dist/commands/doctor.js +32 -274
- package/dist/commands/exec.d.ts +2 -0
- package/dist/commands/exec.js +9 -2
- package/dist/commands/harness.d.ts +1 -0
- package/dist/commands/harness.js +11 -3
- package/dist/commands/hooks.js +7 -6
- package/dist/commands/mcp.js +7 -6
- package/dist/commands/memory.js +7 -7
- package/dist/commands/monitors.js +3 -2
- package/dist/commands/open.d.ts +25 -12
- package/dist/commands/open.js +24 -10
- package/dist/commands/permissions.js +7 -6
- package/dist/commands/plugins.js +21 -17
- package/dist/commands/route.js +33 -16
- package/dist/commands/rules.js +7 -12
- package/dist/commands/sessions-share.js +1 -1
- package/dist/commands/setup-watchdog.js +2 -2
- package/dist/commands/setup.js +22 -1
- package/dist/commands/share.js +26 -10
- package/dist/commands/skills.js +7 -6
- package/dist/commands/subagents.js +7 -6
- package/dist/commands/sync.js +81 -10
- package/dist/commands/view.js +4 -1
- package/dist/commands/watchdog.d.ts +1 -1
- package/dist/commands/watchdog.js +10 -10
- package/dist/commands/webhook.d.ts +4 -0
- package/dist/commands/webhook.js +22 -4
- package/dist/commands/workflows.js +7 -6
- package/dist/lib/accounting/rotate.d.ts +3 -1
- package/dist/lib/accounting/rotate.js +8 -4
- package/dist/lib/auth-health.d.ts +2 -0
- package/dist/lib/auth-health.js +2 -0
- package/dist/lib/browser/chrome.d.ts +21 -0
- package/dist/lib/browser/chrome.js +60 -3
- package/dist/lib/browser/drivers/local.d.ts +21 -0
- package/dist/lib/browser/drivers/local.js +102 -9
- package/dist/lib/browser/profiles.d.ts +29 -1
- package/dist/lib/browser/profiles.js +50 -1
- package/dist/lib/browser/registry.js +10 -3
- package/dist/lib/browser/types.d.ts +18 -0
- package/dist/lib/config-keys.d.ts +7 -2
- package/dist/lib/config-keys.js +17 -2
- package/dist/lib/daemon/daemon.js +8 -0
- package/dist/lib/daemon/session-summarizer-service.d.ts +24 -0
- package/dist/lib/daemon/session-summarizer-service.js +39 -0
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +5 -0
- package/dist/lib/daemon-ticks.d.ts +2 -2
- package/dist/lib/daemon-ticks.js +2 -1
- package/dist/lib/deeplink/register.js +10 -9
- package/dist/lib/deeplink/url.d.ts +4 -4
- package/dist/lib/deeplink/url.js +4 -4
- package/dist/lib/device-config.js +25 -0
- package/dist/lib/devices/doctor-findings.d.ts +4 -4
- package/dist/lib/devices/doctor-findings.js +14 -8
- package/dist/lib/devices/registry.js +2 -0
- package/dist/lib/devices/stats-cache.d.ts +4 -0
- package/dist/lib/devices/stats-cache.js +19 -0
- package/dist/lib/drift-sync.d.ts +3 -1
- package/dist/lib/drift-sync.js +16 -5
- package/dist/lib/exec.d.ts +2 -0
- package/dist/lib/exec.js +16 -1
- package/dist/lib/fleet-shared-state.d.ts +8 -0
- package/dist/lib/git.js +6 -0
- package/dist/lib/heal.d.ts +4 -3
- package/dist/lib/heal.js +5 -4
- package/dist/lib/hosts/ready.d.ts +1 -1
- package/dist/lib/hosts/ready.js +16 -4
- package/dist/lib/hosts/reconnect.js +4 -2
- package/dist/lib/identity/client.d.ts +6 -0
- package/dist/lib/identity/index.d.ts +16 -0
- package/dist/lib/identity/index.js +25 -1
- package/dist/lib/installations/migrate.d.ts +10 -0
- package/dist/lib/installations/migrate.js +18 -0
- package/dist/lib/profiles.d.ts +2 -0
- package/dist/lib/profiles.js +28 -9
- package/dist/lib/project-resources.d.ts +23 -0
- package/dist/lib/project-resources.js +94 -0
- package/dist/lib/reconcile-and-repair.d.ts +109 -0
- package/dist/lib/reconcile-and-repair.js +267 -0
- package/dist/lib/routers.d.ts +12 -1
- package/dist/lib/routers.js +30 -1
- package/dist/lib/scheduling/routines.js +8 -2
- package/dist/lib/session/active.d.ts +13 -0
- package/dist/lib/session/db.d.ts +47 -7
- package/dist/lib/session/db.js +114 -12
- package/dist/lib/session/mirror.js +58 -0
- package/dist/lib/session/remote/watch.js +22 -2
- package/dist/lib/session/session-cache.d.ts +19 -0
- package/dist/lib/session/session-cache.js +46 -0
- package/dist/lib/session/types.d.ts +34 -0
- package/dist/lib/share/backend.d.ts +6 -4
- package/dist/lib/share/backend.js +10 -8
- package/dist/lib/share/config.d.ts +4 -3
- package/dist/lib/share/config.js +10 -1
- package/dist/lib/share/delete.d.ts +1 -1
- package/dist/lib/share/delete.js +1 -1
- package/dist/lib/share/html.d.ts +1 -1
- package/dist/lib/share/html.js +1 -1
- package/dist/lib/share/provision.d.ts +1 -1
- package/dist/lib/share/provision.js +2 -2
- package/dist/lib/share/publish.d.ts +23 -7
- package/dist/lib/share/publish.js +58 -12
- package/dist/lib/share/worker-template.js +221 -60
- package/dist/lib/startup/command-registry.js +2 -2
- package/dist/lib/state.d.ts +58 -1
- package/dist/lib/state.js +138 -16
- package/dist/lib/summarizer/config.d.ts +46 -0
- package/dist/lib/summarizer/config.js +83 -0
- package/dist/lib/summarizer/pass.d.ts +45 -0
- package/dist/lib/summarizer/pass.js +112 -0
- package/dist/lib/summarizer/summarize.d.ts +68 -0
- package/dist/lib/summarizer/summarize.js +120 -0
- package/dist/lib/teams/agents.d.ts +4 -3
- package/dist/lib/teams/agents.js +12 -4
- package/dist/lib/teams/scheduler.d.ts +4 -2
- package/dist/lib/teams/scheduler.js +6 -6
- package/dist/lib/tmux/session.d.ts +2 -0
- package/dist/lib/tmux/session.js +7 -1
- package/dist/lib/types.d.ts +20 -0
- package/dist/lib/verbs.d.ts +23 -0
- package/dist/lib/verbs.js +24 -0
- package/dist/lib/view-types.d.ts +4 -0
- package/dist/lib/watchdog/rotate.d.ts +1 -1
- package/dist/lib/watchdog/rotate.js +1 -1
- package/package.json +1 -1
|
@@ -15,11 +15,12 @@
|
|
|
15
15
|
* unified diff body for each divergent file. Mirrors the resolution that
|
|
16
16
|
* the shim drives at runtime: project > user > system > extras.
|
|
17
17
|
*
|
|
18
|
-
* Read-only
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `agents
|
|
22
|
-
*
|
|
18
|
+
* Read-only always: doctor diagnoses, it never mutates. To fix the gaps it
|
|
19
|
+
* finds — install missing resources, repair Claude-invalid plugin manifests,
|
|
20
|
+
* refresh stale plugins, reconcile drift, repair hook runtime shims — run
|
|
21
|
+
* `agents sync <agent>@all` (the one fixer, a superset of the old `doctor
|
|
22
|
+
* --fix`). Run `agents prune cleanup` to act on orphan readouts. `--fix` is a
|
|
23
|
+
* deprecated no-op that now errors with a pointer to `agents sync`.
|
|
23
24
|
*/
|
|
24
25
|
import type { Command } from 'commander';
|
|
25
26
|
import { type FleetInventory } from '../lib/devices/fleet-divergence.js';
|
package/dist/commands/doctor.js
CHANGED
|
@@ -4,7 +4,7 @@ import { addHostOption } from '../lib/hosts/option.js';
|
|
|
4
4
|
import { buildRemoteAgentsInvocation } from '../lib/hosts/remote-cmd.js';
|
|
5
5
|
import { loadDevices } from '../lib/devices/registry.js';
|
|
6
6
|
import { fanOutDevices, planFleetTargets, remoteFleetTargets } from '../lib/devices/fleet.js';
|
|
7
|
-
import { enterDoctorOverviewGate,
|
|
7
|
+
import { enterDoctorOverviewGate, writeDoctorOverviewCache } from '../lib/devices/doctor-overview-cache.js';
|
|
8
8
|
import { fleetDialTarget } from '../lib/devices/connect.js';
|
|
9
9
|
import { compareFleetInventories, FLEET_HOOK_RUNTIME_STATES } from '../lib/devices/fleet-divergence.js';
|
|
10
10
|
import { collectLocalFleetInventory } from '../lib/devices/fleet-inventory.js';
|
|
@@ -23,7 +23,7 @@ import { getVersionHomePath, listInstalledVersions, } from '../lib/installations
|
|
|
23
23
|
import { resolveAgentTargets, AgentSpecError } from '../lib/agent-spec/index.js';
|
|
24
24
|
import { loadManifest, isStale } from '../lib/staleness/index.js';
|
|
25
25
|
import { diffVersionResources, DOCTOR_ALL_KINDS, } from '../lib/doctor-diff.js';
|
|
26
|
-
import {
|
|
26
|
+
import { inspectDuplicateVersionHooks } from '../lib/hooks/install.js';
|
|
27
27
|
import { inspectReservedAuthBundle } from '../lib/secrets/bundles.js';
|
|
28
28
|
import { isVersionIsolated } from '../lib/installations/versions.js';
|
|
29
29
|
import { computeDrift, checkSyncStatus, countOrphans, computeSourceBehind } from '../lib/drift.js';
|
|
@@ -33,18 +33,13 @@ import { probeOwnerSink } from '../lib/channels/owner-sink.js';
|
|
|
33
33
|
import { unifiedDiff, colorizeUnifiedDiff } from '../lib/diff-text.js';
|
|
34
34
|
import { listCliStatus, listCliStatusAsync } from '../lib/cli-resources.js';
|
|
35
35
|
import { setHelpSections } from '../lib/help.js';
|
|
36
|
-
import { heal, healChangedAnything } from '../lib/heal.js';
|
|
37
36
|
import { getEffectiveExecutionPolicy } from '../lib/platform/winpath.js';
|
|
38
37
|
import { auditWindowsSshEnrollment, diagnoseWindowsSshFailure } from '../lib/devices/windows-ssh-enrollment.js';
|
|
39
38
|
import { scanUserRcFiles, masterPassphraseInEnv } from '../lib/secrets/rc-hygiene.js';
|
|
40
39
|
import { terminalWidth, truncateToWidth, stringWidth, padToWidth } from '../lib/session/width.js';
|
|
41
40
|
import { readRepoBehindMarkers } from '../lib/auto-pull.js';
|
|
42
41
|
import { detectAgentsBinaryShadows } from '../lib/binary-shadow.js';
|
|
43
|
-
import { remediateStaleAgentsCliInstalls, resolveRunningPackageRoot, } from '../lib/self-update.js';
|
|
44
42
|
import * as fs from 'fs';
|
|
45
|
-
import * as path from 'path';
|
|
46
|
-
import { fileURLToPath } from 'url';
|
|
47
|
-
const __doctorDirname = path.dirname(fileURLToPath(import.meta.url));
|
|
48
43
|
const AGENT_NAMES = Object.fromEntries(ALL_AGENT_IDS.map((id) => [id, AGENTS[id].name]));
|
|
49
44
|
// ─── overview mode (no target) ────────────────────────────────────────────────
|
|
50
45
|
function collapseWhitespace(s) {
|
|
@@ -521,7 +516,7 @@ function parseTargetArg(arg) {
|
|
|
521
516
|
const agent = resolveAgentName(agentPart);
|
|
522
517
|
if (!agent)
|
|
523
518
|
return { error: formatAgentError(agentPart) };
|
|
524
|
-
// No qualifier →
|
|
519
|
+
// No qualifier → diagnose every installed version of the agent.
|
|
525
520
|
if (!qualifier) {
|
|
526
521
|
const versions = listInstalledVersions(agent);
|
|
527
522
|
if (versions.length === 0)
|
|
@@ -659,11 +654,8 @@ function readExpectedForDiff(kind, row) {
|
|
|
659
654
|
return null;
|
|
660
655
|
return safeRead(row.sourcePath);
|
|
661
656
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
const HOOK_WIRING_FIX_AGENTS = ['claude', 'droid'];
|
|
665
|
-
/** Categories `--fix` reconciles (vs. `agents repo pull` for a behind source, or
|
|
666
|
-
* `agents prune cleanup` for an orphan). Drives the heal footer. */
|
|
657
|
+
/** Categories `agents sync` reconciles (vs. `agents repo pull` for a behind
|
|
658
|
+
* source, or `agents prune cleanup` for an orphan). Drives the heal footer. */
|
|
667
659
|
const AUTO_FIXABLE_CATEGORIES = new Set([
|
|
668
660
|
'hook-runtime-broken', 'unwired-hook', 'settings-missing', 'settings-unparseable', 'missing', 'divergent', 'stale', 'never-synced',
|
|
669
661
|
]);
|
|
@@ -693,8 +685,10 @@ function missingResourceSeverity(kind) {
|
|
|
693
685
|
export function computeVerdict(report) {
|
|
694
686
|
const issues = [];
|
|
695
687
|
const idLabel = `${report.agent}@${report.version}`;
|
|
696
|
-
|
|
697
|
-
|
|
688
|
+
// doctor diagnoses; `agents sync` fixes. Every auto-fixable finding points at
|
|
689
|
+
// the one fixer — a command sync can actually deliver (asserted in the tests).
|
|
690
|
+
const fixCmd = `agents sync ${idLabel} --yes`;
|
|
691
|
+
const syncCmd = fixCmd;
|
|
698
692
|
// ── critical: settings.json / unwired hooks (silent breakage) ──
|
|
699
693
|
const w = report.hookWiring;
|
|
700
694
|
for (const issue of w?.runtimeBroken ?? []) {
|
|
@@ -897,7 +891,7 @@ export function computeOverviewHealth(syncRows, orphanRows, repoBehindMarkers, d
|
|
|
897
891
|
issues.push({
|
|
898
892
|
severity: 'critical', category: 'hook-runtime-broken', subject: label,
|
|
899
893
|
impact: `${brokenRuntime} generated hook wrapper${brokenRuntime === 1 ? '' : 's'} unusable; affected hooks cannot run`,
|
|
900
|
-
fix: `agents
|
|
894
|
+
fix: `agents sync ${row.agent}@${row.version} --yes`,
|
|
901
895
|
text: `${label} ${brokenRuntime} hook runtime broken`, color: 'red',
|
|
902
896
|
});
|
|
903
897
|
}
|
|
@@ -931,7 +925,7 @@ export function computeOverviewHealth(syncRows, orphanRows, repoBehindMarkers, d
|
|
|
931
925
|
issues.push({
|
|
932
926
|
severity: 'warning', category: 'stale', subject: label,
|
|
933
927
|
impact: 'sources changed since last sync',
|
|
934
|
-
fix: `agents
|
|
928
|
+
fix: `agents sync ${row.agent}@${row.version} --yes`,
|
|
935
929
|
text: `${label} stale`, color: 'yellow',
|
|
936
930
|
});
|
|
937
931
|
}
|
|
@@ -1040,247 +1034,16 @@ function renderTargetText(report, options) {
|
|
|
1040
1034
|
}
|
|
1041
1035
|
console.log();
|
|
1042
1036
|
const verdict = computeVerdict(report);
|
|
1043
|
-
// A source layer behind origin is healed by `agents repo pull`, not
|
|
1037
|
+
// A source layer behind origin is healed by `agents repo pull`, not by sync —
|
|
1044
1038
|
// the per-issue fix already names the right command, so the heal footer only
|
|
1045
|
-
// shows when something is genuinely
|
|
1039
|
+
// shows when something is genuinely sync-fixable (never in the source-behind or
|
|
1046
1040
|
// orphan-only case, where it would mislead).
|
|
1047
1041
|
const hooksWired = report.hookWiring?.supported ? ' · hooks wired' : '';
|
|
1048
1042
|
renderHealthBlock(verdict, {
|
|
1049
1043
|
healthySummary: `${verdict.reconciled} resource${verdict.reconciled === 1 ? '' : 's'} reconciled${hooksWired} · sources current`,
|
|
1050
|
-
healFix: verdictIsAutoFixable(verdict) ? `agents
|
|
1044
|
+
healFix: verdictIsAutoFixable(verdict) ? `agents sync ${report.agent}@${report.version} --yes` : undefined,
|
|
1051
1045
|
});
|
|
1052
1046
|
}
|
|
1053
|
-
// ─── fix / heal mode ───────────────────────────────────────────────────────────
|
|
1054
|
-
function renderHealText(result) {
|
|
1055
|
-
for (const r of result.repairedManifests) {
|
|
1056
|
-
console.log(` ${chalk.green('repair')} plugin ${chalk.bold(r.plugin)} ${chalk.gray(`— dropped invalid ${r.droppedFields.join(', ')} field`)}`);
|
|
1057
|
-
}
|
|
1058
|
-
for (const r of result.refreshedPlugins) {
|
|
1059
|
-
console.log(` ${chalk.green('refresh')} plugin ${chalk.bold(r.plugin)} ${chalk.gray(`${r.from} → ${r.to}`)}`);
|
|
1060
|
-
}
|
|
1061
|
-
for (const s of result.skippedPlugins) {
|
|
1062
|
-
const why = s.reason === 'modified'
|
|
1063
|
-
? `locally modified — left as-is (run \`agents plugins update ${s.plugin}\` to force)`
|
|
1064
|
-
: `no baseline recorded — left as-is (run \`agents plugins update ${s.plugin}\` to adopt)`;
|
|
1065
|
-
console.log(` ${chalk.yellow('hold ')} plugin ${chalk.bold(s.plugin)} ${chalk.gray(`${s.from} → ${s.upstream} available; ${why}`)}`);
|
|
1066
|
-
}
|
|
1067
|
-
for (const v of result.versions) {
|
|
1068
|
-
const label = `${AGENT_NAMES[v.agent] || v.agent}@${v.version}`;
|
|
1069
|
-
if (v.healed.length === 0 && v.skipped.length === 0)
|
|
1070
|
-
continue;
|
|
1071
|
-
const byKind = new Map();
|
|
1072
|
-
for (const h of v.healed)
|
|
1073
|
-
byKind.set(h.kind, (byKind.get(h.kind) ?? 0) + 1);
|
|
1074
|
-
const parts = Array.from(byKind, ([k, n]) => `${n} ${k}`);
|
|
1075
|
-
if (v.healed.length > 0) {
|
|
1076
|
-
console.log(` ${chalk.green('fixed ')} ${label} ${chalk.gray(parts.join(', '))}`);
|
|
1077
|
-
}
|
|
1078
|
-
const drift = v.skipped.filter((s) => s.reason === 'drift');
|
|
1079
|
-
const unres = v.skipped.filter((s) => s.reason === 'unreconcilable');
|
|
1080
|
-
if (drift.length > 0) {
|
|
1081
|
-
console.log(` ${chalk.yellow('drift ')} ${label} ${chalk.gray(`${drift.length} hand-edited — left as-is (use \`--diff\` to inspect)`)}`);
|
|
1082
|
-
}
|
|
1083
|
-
if (unres.length > 0) {
|
|
1084
|
-
const names = unres.map((s) => `${s.kind}/${s.name}`).join(', ');
|
|
1085
|
-
console.log(` ${chalk.yellow('hold ')} ${label} ${chalk.gray(`${unres.length} couldn't reconcile (${names}) — source/home mismatch the writer can't satisfy`)}`);
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
console.log();
|
|
1089
|
-
const healed = result.versions.reduce((n, v) => n + v.healed.length, 0);
|
|
1090
|
-
const touchedVersions = result.versions.filter((v) => v.healed.length > 0).length;
|
|
1091
|
-
if (!healChangedAnything(result)) {
|
|
1092
|
-
console.log(chalk.green('✓ Everything in sync — nothing to heal.'));
|
|
1093
|
-
}
|
|
1094
|
-
else {
|
|
1095
|
-
const bits = [];
|
|
1096
|
-
if (healed > 0)
|
|
1097
|
-
bits.push(`${healed} resource${healed === 1 ? '' : 's'} across ${touchedVersions} version${touchedVersions === 1 ? '' : 's'}`);
|
|
1098
|
-
if (result.repairedManifests.length > 0)
|
|
1099
|
-
bits.push(`${result.repairedManifests.length} manifest${result.repairedManifests.length === 1 ? '' : 's'} repaired`);
|
|
1100
|
-
if (result.refreshedPlugins.length > 0)
|
|
1101
|
-
bits.push(`${result.refreshedPlugins.length} plugin${result.refreshedPlugins.length === 1 ? '' : 's'} refreshed`);
|
|
1102
|
-
console.log(chalk.green(`✓ Healed ${bits.join(', ')}.`));
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
/**
|
|
1106
|
-
* Re-wire hooks that reconcile as files but are absent from settings.json.
|
|
1107
|
-
*
|
|
1108
|
-
* heal() only re-syncs resources the diff flags missing/diff; a hook whose file
|
|
1109
|
-
* is byte-identical to source but never referenced in settings.json is neither,
|
|
1110
|
-
* so heal walks past it. registerHooksToSettings (the same call `agents sync`
|
|
1111
|
-
* makes at versions.ts) regenerates the wiring, so run it for any Claude-family
|
|
1112
|
-
* version this fix targets that has unwired hooks. Only claude/droid — the set
|
|
1113
|
-
* checkVersionHookWiring can verify.
|
|
1114
|
-
*/
|
|
1115
|
-
function rewireUnwiredHooks(parsed) {
|
|
1116
|
-
const out = [];
|
|
1117
|
-
const agents = parsed?.agent
|
|
1118
|
-
? (HOOK_WIRING_FIX_AGENTS.includes(parsed.agent) ? [parsed.agent] : [])
|
|
1119
|
-
: HOOK_WIRING_FIX_AGENTS;
|
|
1120
|
-
for (const agent of agents) {
|
|
1121
|
-
// A named version is explicit consent; a sweep excludes isolated copies,
|
|
1122
|
-
// mirroring heal().
|
|
1123
|
-
const versions = parsed?.agent && parsed.versionExplicit
|
|
1124
|
-
? parsed.versions
|
|
1125
|
-
: listInstalledVersions(agent).filter((v) => !isVersionIsolated(agent, v));
|
|
1126
|
-
for (const version of versions) {
|
|
1127
|
-
const before = checkVersionHookWiring(agent, version);
|
|
1128
|
-
if (!before.supported)
|
|
1129
|
-
continue;
|
|
1130
|
-
const need = before.unwired.length + (before.settingsMissing ? (before.expected ?? 0) : 0);
|
|
1131
|
-
if (need === 0)
|
|
1132
|
-
continue;
|
|
1133
|
-
try {
|
|
1134
|
-
const registration = registerHooksToSettings(agent, getVersionHomePath(agent, version));
|
|
1135
|
-
if (registration.errors.length > 0) {
|
|
1136
|
-
out.push({ agent, version, rewired: 0, remaining: need, failure: 'register-failed' });
|
|
1137
|
-
continue;
|
|
1138
|
-
}
|
|
1139
|
-
const after = checkVersionHookWiring(agent, version);
|
|
1140
|
-
const remaining = after.unwired.length + (after.settingsMissing ? (after.expected ?? 0) : 0);
|
|
1141
|
-
out.push({ agent, version, rewired: Math.max(0, need - remaining), remaining });
|
|
1142
|
-
}
|
|
1143
|
-
catch {
|
|
1144
|
-
// A shim write can fail before the native config writer gets to return
|
|
1145
|
-
// its own errors. Record the same stable class and keep doctor --fix
|
|
1146
|
-
// moving to the one bounded runtime repair pass below.
|
|
1147
|
-
out.push({ agent, version, rewired: 0, remaining: need, failure: 'register-failed' });
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
return out;
|
|
1152
|
-
}
|
|
1153
|
-
function renderHookRewireText(rewired) {
|
|
1154
|
-
for (const r of rewired) {
|
|
1155
|
-
const label = `${AGENT_NAMES[r.agent] || r.agent}@${r.version}`;
|
|
1156
|
-
if (r.failure) {
|
|
1157
|
-
console.log(` ${chalk.red('hold ')} ${label} ${chalk.gray('native hook wiring could not be updated')}`);
|
|
1158
|
-
}
|
|
1159
|
-
else if (r.remaining === 0) {
|
|
1160
|
-
console.log(` ${chalk.green('rewired')} ${label} ${chalk.gray(`${r.rewired} hook${r.rewired === 1 ? '' : 's'} wired into settings.json`)}`);
|
|
1161
|
-
}
|
|
1162
|
-
else {
|
|
1163
|
-
console.log(` ${chalk.yellow('hold ')} ${label} ${chalk.gray(`${r.remaining} hook${r.remaining === 1 ? '' : 's'} still unwired — run \`agents sync ${r.agent}@${r.version} --yes\``)}`);
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
function runtimeRepairFilter(parsed) {
|
|
1168
|
-
if (!parsed)
|
|
1169
|
-
return undefined;
|
|
1170
|
-
// A concrete target can be narrowed to that version. Broad selectors (@all,
|
|
1171
|
-
// @latest, agent-only) still make one bounded repair pass for that harness.
|
|
1172
|
-
return {
|
|
1173
|
-
agent: parsed.agent,
|
|
1174
|
-
...(parsed.versionExplicit && parsed.versions.length === 1 ? { version: parsed.versions[0] } : {}),
|
|
1175
|
-
};
|
|
1176
|
-
}
|
|
1177
|
-
function renderHookRuntimeRepairText(repair) {
|
|
1178
|
-
for (const fixed of repair.fixed) {
|
|
1179
|
-
console.log(` ${chalk.green('fixed ')} ${chalk.gray(fixed)}`);
|
|
1180
|
-
}
|
|
1181
|
-
for (const unresolved of repair.needsAttention) {
|
|
1182
|
-
console.log(` ${chalk.red('hold ')} ${chalk.gray(unresolved)}`);
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
/**
|
|
1186
|
-
* RUSH-2415: delete npx-cache / unsafe-legacy / pre-1.22.30 agents-cli copies
|
|
1187
|
-
* when a fixed peer already exists. Bare `doctor --fix` is the remediation
|
|
1188
|
-
* surface the multi-install warning points at; a targeted
|
|
1189
|
-
* `doctor <agent>@<version> --fix` only heals that version home and must not
|
|
1190
|
-
* touch other CLI installs on the box.
|
|
1191
|
-
*/
|
|
1192
|
-
function purgeStaleAgentsCliCopies(_opts) {
|
|
1193
|
-
let runningRoot;
|
|
1194
|
-
try {
|
|
1195
|
-
// dist/commands/doctor.js (or src/commands/doctor.ts under vitest) —
|
|
1196
|
-
// resolveRunningPackageRoot walks up until package.json names this package.
|
|
1197
|
-
runningRoot = resolveRunningPackageRoot(__doctorDirname);
|
|
1198
|
-
}
|
|
1199
|
-
catch {
|
|
1200
|
-
return null;
|
|
1201
|
-
}
|
|
1202
|
-
return remediateStaleAgentsCliInstalls({
|
|
1203
|
-
runningRoot,
|
|
1204
|
-
runningVersion: getCliVersion(),
|
|
1205
|
-
});
|
|
1206
|
-
}
|
|
1207
|
-
function renderStaleInstallPurgeText(purge) {
|
|
1208
|
-
if (purge.removed.length === 0 && purge.failed.length === 0 && purge.unresolved.length === 0)
|
|
1209
|
-
return;
|
|
1210
|
-
console.log(chalk.bold('\nStale agents-cli installs'));
|
|
1211
|
-
for (const r of purge.removed) {
|
|
1212
|
-
const why = r.reasons.join(', ');
|
|
1213
|
-
console.log(` ${chalk.green('purged')} ${chalk.gray(`${r.packageRoot} ${r.version} (${why})`)}`);
|
|
1214
|
-
}
|
|
1215
|
-
for (const f of purge.failed) {
|
|
1216
|
-
console.log(` ${chalk.red('hold ')} ${chalk.gray(`${f.packageRoot} ${f.version} — ${f.error}`)}`);
|
|
1217
|
-
}
|
|
1218
|
-
// RUSH-2705/2713: a duplicate --fix cannot auto-purge — either a healthy
|
|
1219
|
-
// >=1.22.30 peer, OR a pre-1.22.30 copy left alone only because no fixed peer
|
|
1220
|
-
// exists to fall back to (that one is NOT healthy). Either way, hand back the
|
|
1221
|
-
// command that removes it instead of ending on a bare "everything in sync".
|
|
1222
|
-
// Don't call it "healthy" — that would understate a genuinely vulnerable copy.
|
|
1223
|
-
for (const u of purge.unresolved) {
|
|
1224
|
-
console.log(` ${chalk.yellow('manual')} ${chalk.gray(`${u.packageRoot} ${u.version} — --fix will not delete this copy; remove it with:`)}`);
|
|
1225
|
-
console.log(` ${chalk.bold(u.manualRemoveCommand)}`);
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
async function runFix(parsed, opts) {
|
|
1229
|
-
// Heal targets the global install — project layer is irrelevant, so cwd is
|
|
1230
|
-
// left to heal's neutral default rather than process.cwd().
|
|
1231
|
-
if (!opts.json)
|
|
1232
|
-
console.log(chalk.bold('Healing…'));
|
|
1233
|
-
// `agents doctor <agent> --fix` is a SWEEP, same as the bare form — leave the
|
|
1234
|
-
// version list to heal() so it applies its isolated-copy filter. Passing the
|
|
1235
|
-
// enumerated list here would smuggle isolated versions past that filter.
|
|
1236
|
-
// A named version (`<agent>@<version>`) is explicit consent and is passed through.
|
|
1237
|
-
const result = await heal({
|
|
1238
|
-
mode: 'full',
|
|
1239
|
-
agent: parsed?.agent,
|
|
1240
|
-
versions: parsed?.versionExplicit ? parsed.versions : undefined,
|
|
1241
|
-
});
|
|
1242
|
-
// Re-wire hooks the diff-driven heal leaves behind (present file, not wired).
|
|
1243
|
-
const rewired = rewireUnwiredHooks(parsed);
|
|
1244
|
-
// One inspect→generate→verify pass, after normal resource and native-wiring
|
|
1245
|
-
// repair have settled. This routine never calls sync/register and never
|
|
1246
|
-
// retries; unresolved wrappers remain an explicit non-zero doctor outcome.
|
|
1247
|
-
const hookRuntimeRepair = repairManagedHookRuntimeArtifacts({ filter: runtimeRepairFilter(parsed) });
|
|
1248
|
-
// Bare doctor --fix also purges latent pre-fix / legacy agents-cli copies
|
|
1249
|
-
// that only warn today (RUSH-2415). A scoped agent@version fix leaves them
|
|
1250
|
-
// alone — the multi-install surface is machine-wide, not per-agent.
|
|
1251
|
-
const staleInstallPurge = parsed === null ? purgeStaleAgentsCliCopies(opts) : null;
|
|
1252
|
-
const rewireFailed = rewired.some((entry) => entry.failure !== undefined);
|
|
1253
|
-
if (healChangedAnything(result) ||
|
|
1254
|
-
rewired.some((entry) => entry.rewired > 0 || entry.remaining > 0 || entry.failure !== undefined) ||
|
|
1255
|
-
hookRuntimeRepair.attempts.length > 0 ||
|
|
1256
|
-
(staleInstallPurge !== null && (staleInstallPurge.removed.length > 0 || staleInstallPurge.failed.length > 0))) {
|
|
1257
|
-
invalidateDoctorOverviewCache();
|
|
1258
|
-
}
|
|
1259
|
-
if (opts.json) {
|
|
1260
|
-
console.log(JSON.stringify({
|
|
1261
|
-
...result,
|
|
1262
|
-
hookRewire: rewired,
|
|
1263
|
-
hookRuntimeRepair,
|
|
1264
|
-
...(staleInstallPurge ? { staleInstallPurge } : {}),
|
|
1265
|
-
}, null, 2));
|
|
1266
|
-
if (rewireFailed
|
|
1267
|
-
|| hookRuntimeRepair.needsAttention.length > 0
|
|
1268
|
-
|| (staleInstallPurge !== null && staleInstallPurge.failed.length > 0)) {
|
|
1269
|
-
process.exitCode = 1;
|
|
1270
|
-
}
|
|
1271
|
-
return;
|
|
1272
|
-
}
|
|
1273
|
-
renderHealText(result);
|
|
1274
|
-
renderHookRewireText(rewired);
|
|
1275
|
-
renderHookRuntimeRepairText(hookRuntimeRepair);
|
|
1276
|
-
if (staleInstallPurge)
|
|
1277
|
-
renderStaleInstallPurgeText(staleInstallPurge);
|
|
1278
|
-
if (rewireFailed
|
|
1279
|
-
|| hookRuntimeRepair.needsAttention.length > 0
|
|
1280
|
-
|| (staleInstallPurge !== null && staleInstallPurge.failed.length > 0)) {
|
|
1281
|
-
process.exitCode = 1;
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
1047
|
function checkLabel(row) {
|
|
1285
1048
|
return `${AGENT_NAMES[row.agent] || row.agent}@${row.version}`;
|
|
1286
1049
|
}
|
|
@@ -1360,7 +1123,7 @@ function runCheckGate(opts, cwd) {
|
|
|
1360
1123
|
}
|
|
1361
1124
|
const hints = [];
|
|
1362
1125
|
if (drift.staleCount > 0 || drift.neverSyncedCount > 0 || drift.unwiredHookVersions > 0 || drift.brokenHookRuntimeVersions > 0) {
|
|
1363
|
-
hints.push('`agents
|
|
1126
|
+
hints.push('`agents sync <agent>@all` (or `agents sync <agent>@<version>`)');
|
|
1364
1127
|
}
|
|
1365
1128
|
if (drift.sourceBehind.length > 0)
|
|
1366
1129
|
hints.push('`agents repo pull <alias>` for a source layer behind origin');
|
|
@@ -1447,7 +1210,7 @@ async function runDevicesCheck(opts, cwd) {
|
|
|
1447
1210
|
: [`${d.stale} stale`, `${d.neverSynced} never-synced`].filter((p) => !p.startsWith('0 ')).join(', ');
|
|
1448
1211
|
console.error(` ${chalk.yellow(d.device.padEnd(18))} ${detail || 'drift'}`);
|
|
1449
1212
|
}
|
|
1450
|
-
console.error(chalk.gray('\nReconcile each device with `agents
|
|
1213
|
+
console.error(chalk.gray('\nReconcile each device with `agents sync <agent>@all` or `agents repo pull user`.'));
|
|
1451
1214
|
}
|
|
1452
1215
|
process.exit(1);
|
|
1453
1216
|
}
|
|
@@ -1457,7 +1220,7 @@ export function registerDoctorCommand(program) {
|
|
|
1457
1220
|
.description('Diagnose CLI availability, sync status, and resource divergence (optionally for a specific agent[@version]).')
|
|
1458
1221
|
.option('--json', 'Output machine-readable JSON')
|
|
1459
1222
|
.option('--diff', 'In target mode, include unified diffs for divergent files')
|
|
1460
|
-
.option('--fix', '
|
|
1223
|
+
.option('--fix', '(deprecated) doctor is diagnose-only — this errors with a pointer to `agents sync`, the one fixer')
|
|
1461
1224
|
.option('--kind <kinds>', 'Restrict to comma-separated resource kinds (commands,skills,hooks,rules,mcp,permissions,subagents,plugins,workflows,memory)')
|
|
1462
1225
|
.option('--cwd <path>', 'Resolution cwd for project layer detection (default: process.cwd())')
|
|
1463
1226
|
.option('--adopt <agent>', "Take over the agent's native launcher that shadows the shim (symlink it to the version-managed shim; reversible with --release)")
|
|
@@ -1488,11 +1251,11 @@ export function registerDoctorCommand(program) {
|
|
|
1488
1251
|
# Inspect only rules and hooks, with full diffs
|
|
1489
1252
|
agents doctor claude@default --kind rules,hooks --diff
|
|
1490
1253
|
|
|
1491
|
-
#
|
|
1492
|
-
agents
|
|
1254
|
+
# Fix every gap across all installed versions (the one fixer)
|
|
1255
|
+
agents sync claude@all
|
|
1493
1256
|
|
|
1494
|
-
#
|
|
1495
|
-
agents
|
|
1257
|
+
# Fix just one version
|
|
1258
|
+
agents sync claude@2.1.207
|
|
1496
1259
|
|
|
1497
1260
|
# Fleet: agent readiness + cross-device divergence (missing plugins/skills,
|
|
1498
1261
|
# agent-version gaps, .agents/.system repo drift) vs this machine
|
|
@@ -1503,7 +1266,7 @@ export function registerDoctorCommand(program) {
|
|
|
1503
1266
|
agents doctor --check --quiet # just the verdict line
|
|
1504
1267
|
agents doctor --check --json # machine-readable, for scripting
|
|
1505
1268
|
agents doctor --check --devices # gate every registered device
|
|
1506
|
-
agents doctor --check || { echo "resources drifted — run 'agents
|
|
1269
|
+
agents doctor --check || { echo "resources drifted — run 'agents sync <agent>@all'"; exit 1; }
|
|
1507
1270
|
`,
|
|
1508
1271
|
});
|
|
1509
1272
|
doctorCmd.action(async (target, opts) => {
|
|
@@ -1587,20 +1350,15 @@ export function registerDoctorCommand(program) {
|
|
|
1587
1350
|
}
|
|
1588
1351
|
return;
|
|
1589
1352
|
}
|
|
1590
|
-
// --fix
|
|
1591
|
-
//
|
|
1353
|
+
// `doctor --fix` moved to `agents sync` — doctor is diagnose-only now.
|
|
1354
|
+
// Keep the flag for one release as a signpost: it never heals, it points at
|
|
1355
|
+
// the one fixer and exits non-zero so scripts and muscle memory get a clear
|
|
1356
|
+
// redirect instead of a silent no-op.
|
|
1592
1357
|
if (opts.fix) {
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
console.error(chalk.red(parsed.error));
|
|
1598
|
-
process.exit(1);
|
|
1599
|
-
}
|
|
1600
|
-
scope = parsed;
|
|
1601
|
-
}
|
|
1602
|
-
await runFix(scope, opts);
|
|
1603
|
-
return;
|
|
1358
|
+
const where = target ? `agents sync ${target}` : 'agents sync <agent>@all';
|
|
1359
|
+
console.error(chalk.yellow('`agents doctor --fix` has moved to `agents sync`.'));
|
|
1360
|
+
console.error(chalk.gray(` doctor now only diagnoses. To fix, run: ${where}`));
|
|
1361
|
+
process.exit(1);
|
|
1604
1362
|
}
|
|
1605
1363
|
if (!target) {
|
|
1606
1364
|
// Singleflight + short-TTL cache for the bare `doctor --json` overview.
|
|
@@ -1666,8 +1424,8 @@ export function registerDoctorCommand(program) {
|
|
|
1666
1424
|
// A MANAGED agent (installed versions) whose binary won't resolve is a
|
|
1667
1425
|
// real critical — an unmanaged-and-absent agent is not.
|
|
1668
1426
|
const cliMissing = ALL_AGENT_IDS.filter((a) => listInstalledVersions(a).length > 0 && clis[a] && !clis[a].installed);
|
|
1669
|
-
// An isolated copy is skipped by the agent-wide
|
|
1670
|
-
// findings must never fold into a collapsed cross-version row.
|
|
1427
|
+
// An isolated copy is skipped by the agent-wide `agents sync` sweep, so
|
|
1428
|
+
// its findings must never fold into a collapsed cross-version row.
|
|
1671
1429
|
const isolatedVersions = reports
|
|
1672
1430
|
.filter((r) => isVersionIsolated(r.agent, r.version))
|
|
1673
1431
|
.map((r) => `${r.agent}@${r.version}`);
|
package/dist/commands/exec.d.ts
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
import { type Command } from 'commander';
|
|
9
9
|
import type { ExecEffort } from '../lib/exec.js';
|
|
10
10
|
import { RUN_AUTO_KEYWORD } from '../lib/types.js';
|
|
11
|
+
/** Validate a caller-supplied session id before it reaches tmux, paths, indexes, or remote dispatch. */
|
|
12
|
+
export declare function parseExplicitSessionId(value: string): string;
|
|
11
13
|
export interface RunAccountPickerRequest {
|
|
12
14
|
requested: boolean;
|
|
13
15
|
normalizedAgentSpec: string;
|
package/dist/commands/exec.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* or headlessly. Supports profile resolution, version rotation, secrets
|
|
6
6
|
* injection, and multi-agent fallback chains for rate-limit resilience.
|
|
7
7
|
*/
|
|
8
|
-
import { Option } from 'commander';
|
|
8
|
+
import { InvalidArgumentError, Option } from 'commander';
|
|
9
9
|
import chalk from 'chalk';
|
|
10
10
|
import { isTierToken } from '../lib/model-tiers.js';
|
|
11
11
|
import { RUN_AUTO_KEYWORD } from '../lib/types.js';
|
|
@@ -28,6 +28,13 @@ import { isSessionTrackedAgent } from '../lib/session/types.js';
|
|
|
28
28
|
import { applyActiveRulesPresetAtRun } from '../lib/rules/run-sync.js';
|
|
29
29
|
import { handleBroadcast } from './run-broadcast.js';
|
|
30
30
|
import { bootMark } from '../lib/boot-profile.js';
|
|
31
|
+
/** Validate a caller-supplied session id before it reaches tmux, paths, indexes, or remote dispatch. */
|
|
32
|
+
export function parseExplicitSessionId(value) {
|
|
33
|
+
if (!/^[A-Za-z0-9._-]+$/.test(value)) {
|
|
34
|
+
throw new InvalidArgumentError('must contain only ASCII letters, digits, dots, underscores, or hyphens');
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
31
38
|
/** Distinguish a terminal account-picker marker from an explicit @version pin. */
|
|
32
39
|
export function parseRunAccountPickerRequest(agentSpec) {
|
|
33
40
|
const requested = agentSpec.endsWith('@');
|
|
@@ -514,7 +521,7 @@ export function registerRunCommand(program) {
|
|
|
514
521
|
.option('--results [run-id]', 'With --broadcast: show one saved matrix run, or list saved runs newest first')
|
|
515
522
|
.option('--concurrency <n>', 'With --broadcast: maximum cells running at once', '3')
|
|
516
523
|
.option('--resume [id]', 'Recover a previous conversation on its origin device. The exact healthy origin uses native resume; otherwise a healthy version of the same harness replays via /continue. Pair with a prompt to continue headlessly.')
|
|
517
|
-
.option('--session-id <id>', 'Force a NEW conversation to use this exact session UUID (Claude only). This CREATES a session — to resume an existing one, use --resume.')
|
|
524
|
+
.option('--session-id <id>', 'Force a NEW conversation to use this exact session UUID (Claude only). This CREATES a session — to resume an existing one, use --resume.', parseExplicitSessionId)
|
|
518
525
|
.option('--name <slug>', 'Name the run — seeds the session label so it shows up as `<name>` in `agents sessions` and resolves by it (and `agents hosts logs <name>` for --device runs) instead of an opaque id. An agent-generated title later refines the label; your name shows until then. Optional.')
|
|
519
526
|
.option('--notify', 'Post a desktop notification when a headless run finishes. Fired by this process on exit, so it survives whatever launched the run (the menu bar dispatching it, a terminal you closed).')
|
|
520
527
|
.option('--no-trace-sync', 'Skip the run-exit trace auto-sync for this run. Auto-sync fires by default only for local runs and only once you have run `agents traces sync` at least once (also silenced by AGENTS_NO_TRACE_SYNC=1).')
|
|
@@ -22,6 +22,7 @@ import { type HarnessDraft } from './harness-wizard.js';
|
|
|
22
22
|
export declare function renderHarnessDetail(name: string): void;
|
|
23
23
|
/** Options accepted by `agents harness fork`. */
|
|
24
24
|
export interface ForkOptions {
|
|
25
|
+
toHost?: string;
|
|
25
26
|
model?: string;
|
|
26
27
|
baseUrl?: string;
|
|
27
28
|
authProvider?: string;
|
package/dist/commands/harness.js
CHANGED
|
@@ -62,7 +62,11 @@ export function buildFork(source, name, opts) {
|
|
|
62
62
|
if (opts.authProvider || opts.fromSecrets)
|
|
63
63
|
throw new Error("Harnesses no longer own credentials. Add one with 'agents accounts add <name> --provider <provider> --auth <type>', then pass --account <name>.");
|
|
64
64
|
if (profileExists(source)) {
|
|
65
|
+
const targetHost = opts.toHost ? (resolveAgentName(opts.toHost) ?? undefined) : undefined;
|
|
66
|
+
if (opts.toHost && !targetHost)
|
|
67
|
+
throw new Error(`Unknown target host '${opts.toHost}'.`);
|
|
65
68
|
const profile = forkProfile(readProfile(source), name, {
|
|
69
|
+
host: targetHost,
|
|
66
70
|
model: opts.model,
|
|
67
71
|
baseUrl: opts.baseUrl,
|
|
68
72
|
provider: opts.authProvider,
|
|
@@ -78,14 +82,17 @@ export function buildFork(source, name, opts) {
|
|
|
78
82
|
}
|
|
79
83
|
return profile;
|
|
80
84
|
}
|
|
81
|
-
const
|
|
82
|
-
if (!
|
|
85
|
+
const sourceHost = resolveAgentName(source);
|
|
86
|
+
if (!sourceHost) {
|
|
83
87
|
throw new Error(`No harness or agent named '${source}'.\n` +
|
|
84
88
|
`Fork from a custom harness (agents harness list) or a native one: ${ALL_AGENT_IDS.join(', ')}.`);
|
|
85
89
|
}
|
|
86
90
|
if (!opts.model) {
|
|
87
|
-
throw new Error(`--model <id> is required when forking the native '${
|
|
91
|
+
throw new Error(`--model <id> is required when forking the native '${sourceHost}' harness (there is no model to inherit).`);
|
|
88
92
|
}
|
|
93
|
+
const host = opts.toHost ? resolveAgentName(opts.toHost) : sourceHost;
|
|
94
|
+
if (!host)
|
|
95
|
+
throw new Error(`Unknown target host '${opts.toHost}'.`);
|
|
89
96
|
const profile = profileFromHostModel(name, host, opts.model, {
|
|
90
97
|
version: opts.version,
|
|
91
98
|
baseUrl: opts.baseUrl,
|
|
@@ -461,6 +468,7 @@ Examples:
|
|
|
461
468
|
.command('fork [source] [name]')
|
|
462
469
|
.description('Fork a native harness (claude, opencode, ...) or an existing custom one into a new named harness. Omit args in a terminal for the interactive wizard.')
|
|
463
470
|
.option('--model <id>', 'Model to pin on the fork (required when forking a native harness)')
|
|
471
|
+
.option('--to-host <agent>', 'Translate the fork onto another native harness host (for example claude to codex)')
|
|
464
472
|
.option('--base-url <url>', 'Custom endpoint base URL (claude/codex hosts)')
|
|
465
473
|
.option('--account <name>', 'Default durable credential account')
|
|
466
474
|
.option('--auth-provider <provider>', 'Removed: use agents accounts add, then --account')
|
package/dist/commands/hooks.js
CHANGED
|
@@ -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';
|
|
@@ -40,8 +41,8 @@ When to use:
|
|
|
40
41
|
- Notifications: ping Slack when agents complete long tasks
|
|
41
42
|
- Team workflows: sync hooks via 'agents hooks add gh:team/hooks'
|
|
42
43
|
`);
|
|
43
|
-
hooksCmd
|
|
44
|
-
.command('list [agent]')
|
|
44
|
+
withAliases(hooksCmd
|
|
45
|
+
.command('list [agent]'), 'list')
|
|
45
46
|
.description('Show which hooks are installed and which events they respond to')
|
|
46
47
|
.option('-a, --agent <agent>', 'Filter to a specific agent (alternative to positional arg)')
|
|
47
48
|
.option('-s, --scope <scope>', 'user (global), project (repo), or all', 'all')
|
|
@@ -387,8 +388,8 @@ Examples:
|
|
|
387
388
|
process.exit(1);
|
|
388
389
|
}
|
|
389
390
|
});
|
|
390
|
-
hooksCmd
|
|
391
|
-
.command('remove [name]')
|
|
391
|
+
withAliases(hooksCmd
|
|
392
|
+
.command('remove [name]'), 'remove')
|
|
392
393
|
.description('Delete a hook from agents (interactive picker if no name given)')
|
|
393
394
|
.option('-a, --agents <list>', 'Limit removal to specific agents')
|
|
394
395
|
.addHelpText('after', `
|
|
@@ -527,8 +528,8 @@ Examples:
|
|
|
527
528
|
console.error(chalk.gray('Use: agents prune cleanup hooks (or `agents prune cleanup` for everything)'));
|
|
528
529
|
process.exit(1);
|
|
529
530
|
});
|
|
530
|
-
hooksCmd
|
|
531
|
-
.command('view [name]')
|
|
531
|
+
withAliases(hooksCmd
|
|
532
|
+
.command('view [name]'), 'view')
|
|
532
533
|
.description('Read the shell script content for a hook')
|
|
533
534
|
.addHelpText('after', `
|
|
534
535
|
Examples:
|
package/dist/commands/mcp.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withAliases } from '../lib/verbs.js';
|
|
1
2
|
import chalk from 'chalk';
|
|
2
3
|
import { truncate } from '../lib/format.js';
|
|
3
4
|
import ora from 'ora';
|
|
@@ -143,8 +144,8 @@ When to use:
|
|
|
143
144
|
- Version upgrade: 'agents mcp register' to sync servers to the new version
|
|
144
145
|
- Team setup: commit mcp config to .agents and run 'agents mcp register'
|
|
145
146
|
`);
|
|
146
|
-
mcpCmd
|
|
147
|
-
.command('list [agent]')
|
|
147
|
+
withAliases(mcpCmd
|
|
148
|
+
.command('list [agent]'), 'list')
|
|
148
149
|
.description('Show which MCP servers are registered and which agent versions they are synced to')
|
|
149
150
|
.option('-a, --agent <agent>', 'Filter to a specific agent (alternative to positional arg)')
|
|
150
151
|
.option('--json', 'Emit machine-readable JSON instead of the table/picker')
|
|
@@ -337,8 +338,8 @@ Examples:
|
|
|
337
338
|
console.log(chalk.green(`Added MCP server '${name}' to manifest`));
|
|
338
339
|
console.log(chalk.gray('Run: agents mcp register to apply'));
|
|
339
340
|
});
|
|
340
|
-
mcpCmd
|
|
341
|
-
.command('remove [name]')
|
|
341
|
+
withAliases(mcpCmd
|
|
342
|
+
.command('remove [name]'), 'remove')
|
|
342
343
|
.description('Unregister an MCP server from agents (interactive picker if no name given)')
|
|
343
344
|
.option('-a, --agents <list>', 'Limit removal to specific agents')
|
|
344
345
|
.addHelpText('after', `
|
|
@@ -487,8 +488,8 @@ Examples:
|
|
|
487
488
|
console.log(chalk.green(`\nRemoved ${removed} MCP server(s).`));
|
|
488
489
|
}
|
|
489
490
|
});
|
|
490
|
-
mcpCmd
|
|
491
|
-
.command('view [name]')
|
|
491
|
+
withAliases(mcpCmd
|
|
492
|
+
.command('view [name]'), 'view')
|
|
492
493
|
.description('Show MCP server configuration (command, scope, registered agents)')
|
|
493
494
|
.addHelpText('after', `
|
|
494
495
|
Examples:
|