@phnx-labs/agents-cli 1.20.4 → 1.20.6
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 +19 -0
- package/README.md +49 -18
- package/dist/commands/browser.js +31 -4
- package/dist/commands/cli.js +1 -1
- package/dist/commands/cloud.js +1 -1
- package/dist/commands/commands.js +2 -0
- package/dist/commands/computer.js +10 -2
- package/dist/commands/defaults.d.ts +7 -0
- package/dist/commands/defaults.js +89 -0
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/exec.js +73 -19
- package/dist/commands/hooks.js +6 -6
- package/dist/commands/inspect.d.ts +26 -0
- package/dist/commands/inspect.js +590 -0
- package/dist/commands/mcp.js +17 -16
- package/dist/commands/models.js +1 -1
- package/dist/commands/packages.js +6 -4
- package/dist/commands/permissions.js +13 -12
- package/dist/commands/plugins.d.ts +13 -0
- package/dist/commands/plugins.js +100 -11
- package/dist/commands/prune.js +3 -2
- package/dist/commands/pull.d.ts +12 -5
- package/dist/commands/pull.js +26 -422
- package/dist/commands/push.d.ts +14 -0
- package/dist/commands/push.js +30 -0
- package/dist/commands/repo.d.ts +1 -1
- package/dist/commands/repo.js +155 -112
- package/dist/commands/resource-view.d.ts +2 -0
- package/dist/commands/resource-view.js +12 -3
- package/dist/commands/routines.js +32 -7
- package/dist/commands/rules.js +4 -4
- package/dist/commands/secrets.js +46 -9
- package/dist/commands/sessions.js +1 -0
- package/dist/commands/setup.d.ts +3 -3
- package/dist/commands/setup.js +17 -17
- package/dist/commands/skills.js +6 -5
- package/dist/commands/subagents.js +5 -4
- package/dist/commands/sync.d.ts +18 -5
- package/dist/commands/sync.js +251 -65
- package/dist/commands/teams.js +109 -11
- package/dist/commands/tmux.d.ts +25 -0
- package/dist/commands/tmux.js +415 -0
- package/dist/commands/trash.d.ts +2 -2
- package/dist/commands/trash.js +1 -1
- package/dist/commands/versions.js +2 -2
- package/dist/commands/view.d.ts +12 -1
- package/dist/commands/view.js +128 -40
- package/dist/commands/workflows.js +4 -3
- package/dist/commands/worktree.d.ts +4 -5
- package/dist/commands/worktree.js +4 -4
- package/dist/index.js +106 -41
- package/dist/lib/agents.d.ts +23 -10
- package/dist/lib/agents.js +88 -25
- package/dist/lib/auto-pull-worker.d.ts +1 -1
- package/dist/lib/auto-pull-worker.js +2 -2
- package/dist/lib/auto-pull.d.ts +1 -1
- package/dist/lib/auto-pull.js +1 -1
- package/dist/lib/beta.d.ts +1 -1
- package/dist/lib/beta.js +1 -1
- package/dist/lib/browser/chrome.d.ts +10 -0
- package/dist/lib/browser/chrome.js +84 -3
- package/dist/lib/capabilities.js +2 -0
- package/dist/lib/commands.d.ts +28 -1
- package/dist/lib/commands.js +125 -20
- package/dist/lib/doctor-diff.js +2 -2
- package/dist/lib/exec.d.ts +14 -0
- package/dist/lib/exec.js +59 -5
- package/dist/lib/fuzzy.d.ts +12 -2
- package/dist/lib/fuzzy.js +29 -4
- package/dist/lib/git.js +8 -1
- package/dist/lib/hooks.d.ts +2 -2
- package/dist/lib/hooks.js +97 -10
- package/dist/lib/mcp.js +32 -2
- package/dist/lib/migrate.d.ts +51 -0
- package/dist/lib/migrate.js +233 -5
- package/dist/lib/models.js +62 -15
- package/dist/lib/permissions.d.ts +59 -2
- package/dist/lib/permissions.js +299 -7
- package/dist/lib/plugin-marketplace.d.ts +98 -40
- package/dist/lib/plugin-marketplace.js +196 -93
- package/dist/lib/plugins.d.ts +21 -4
- package/dist/lib/plugins.js +130 -49
- package/dist/lib/profiles-presets.js +12 -12
- package/dist/lib/project-launch.d.ts +70 -0
- package/dist/lib/project-launch.js +404 -0
- package/dist/lib/pty-client.js +1 -1
- package/dist/lib/pty-server.d.ts +1 -1
- package/dist/lib/pty-server.js +8 -5
- package/dist/lib/refresh.d.ts +26 -0
- package/dist/lib/refresh.js +315 -0
- package/dist/lib/resource-patterns.d.ts +1 -1
- package/dist/lib/resource-patterns.js +1 -1
- package/dist/lib/resources/commands.js +2 -2
- package/dist/lib/resources/hooks.d.ts +1 -1
- package/dist/lib/resources/hooks.js +1 -1
- package/dist/lib/resources/mcp.d.ts +1 -1
- package/dist/lib/resources/mcp.js +5 -6
- package/dist/lib/resources/permissions.js +5 -2
- package/dist/lib/resources/rules.js +3 -2
- package/dist/lib/resources/skills.js +3 -2
- package/dist/lib/resources/types.d.ts +1 -1
- package/dist/lib/resources.d.ts +2 -0
- package/dist/lib/resources.js +4 -3
- package/dist/lib/rotate.d.ts +1 -1
- package/dist/lib/rotate.js +7 -19
- package/dist/lib/routines.d.ts +16 -4
- package/dist/lib/routines.js +67 -17
- package/dist/lib/rules/compile.js +22 -10
- package/dist/lib/rules/rules.js +3 -3
- package/dist/lib/run-config.d.ts +9 -0
- package/dist/lib/run-config.js +35 -0
- package/dist/lib/run-defaults.d.ts +42 -0
- package/dist/lib/run-defaults.js +180 -0
- package/dist/lib/runner.js +16 -3
- package/dist/lib/scheduler.js +15 -1
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +9 -1
- package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
- package/dist/lib/secrets/install-helper.d.ts +11 -3
- package/dist/lib/secrets/install-helper.js +48 -6
- package/dist/lib/secrets/linux.d.ts +56 -9
- package/dist/lib/secrets/linux.js +327 -59
- package/dist/lib/session/db.js +15 -2
- package/dist/lib/session/discover.js +118 -3
- package/dist/lib/session/parse.js +3 -0
- package/dist/lib/session/types.d.ts +1 -1
- package/dist/lib/session/types.js +1 -1
- package/dist/lib/shims.d.ts +18 -9
- package/dist/lib/shims.js +133 -50
- package/dist/lib/skills.d.ts +1 -1
- package/dist/lib/skills.js +10 -9
- package/dist/lib/staleness/detectors/commands.d.ts +3 -0
- package/dist/lib/staleness/detectors/commands.js +46 -0
- package/dist/lib/staleness/detectors/hooks.d.ts +3 -0
- package/dist/lib/staleness/detectors/hooks.js +44 -0
- package/dist/lib/staleness/detectors/mcp.d.ts +3 -0
- package/dist/lib/staleness/detectors/mcp.js +31 -0
- package/dist/lib/staleness/detectors/permissions.d.ts +3 -0
- package/dist/lib/staleness/detectors/permissions.js +201 -0
- package/dist/lib/staleness/detectors/plugins.d.ts +8 -0
- package/dist/lib/staleness/detectors/plugins.js +23 -0
- package/dist/lib/staleness/detectors/rules.d.ts +3 -0
- package/dist/lib/staleness/detectors/rules.js +34 -0
- package/dist/lib/staleness/detectors/skills.d.ts +3 -0
- package/dist/lib/staleness/detectors/skills.js +71 -0
- package/dist/lib/staleness/detectors/subagents.d.ts +3 -0
- package/dist/lib/staleness/detectors/subagents.js +50 -0
- package/dist/lib/staleness/detectors/types.d.ts +22 -0
- package/dist/lib/staleness/detectors/types.js +1 -0
- package/dist/lib/staleness/detectors/workflows.d.ts +3 -0
- package/dist/lib/staleness/detectors/workflows.js +28 -0
- package/dist/lib/staleness/registry.d.ts +26 -0
- package/dist/lib/staleness/registry.js +123 -0
- package/dist/lib/staleness/writers/commands.d.ts +3 -0
- package/dist/lib/staleness/writers/commands.js +111 -0
- package/dist/lib/staleness/writers/hooks.d.ts +3 -0
- package/dist/lib/staleness/writers/hooks.js +47 -0
- package/dist/lib/staleness/writers/kinds.d.ts +10 -0
- package/dist/lib/staleness/writers/kinds.js +15 -0
- package/dist/lib/staleness/writers/lazy-map.d.ts +13 -0
- package/dist/lib/staleness/writers/lazy-map.js +19 -0
- package/dist/lib/staleness/writers/mcp.d.ts +10 -0
- package/dist/lib/staleness/writers/mcp.js +19 -0
- package/dist/lib/staleness/writers/permissions.d.ts +13 -0
- package/dist/lib/staleness/writers/permissions.js +26 -0
- package/dist/lib/staleness/writers/plugins.d.ts +7 -0
- package/dist/lib/staleness/writers/plugins.js +31 -0
- package/dist/lib/staleness/writers/rules.d.ts +7 -0
- package/dist/lib/staleness/writers/rules.js +55 -0
- package/dist/lib/staleness/writers/skills.d.ts +3 -0
- package/dist/lib/staleness/writers/skills.js +81 -0
- package/dist/lib/staleness/writers/sources.d.ts +16 -0
- package/dist/lib/staleness/writers/sources.js +72 -0
- package/dist/lib/staleness/writers/subagents.d.ts +3 -0
- package/dist/lib/staleness/writers/subagents.js +53 -0
- package/dist/lib/staleness/writers/types.d.ts +36 -0
- package/dist/lib/staleness/writers/types.js +1 -0
- package/dist/lib/staleness/writers/workflows.d.ts +7 -0
- package/dist/lib/staleness/writers/workflows.js +31 -0
- package/dist/lib/state.d.ts +34 -11
- package/dist/lib/state.js +58 -13
- package/dist/lib/subagents.d.ts +0 -2
- package/dist/lib/subagents.js +6 -6
- package/dist/lib/teams/agents.js +1 -1
- package/dist/lib/teams/api.d.ts +67 -0
- package/dist/lib/teams/api.js +78 -0
- package/dist/lib/teams/parsers.d.ts +1 -1
- package/dist/lib/tmux/binary.d.ts +67 -0
- package/dist/lib/tmux/binary.js +141 -0
- package/dist/lib/tmux/index.d.ts +8 -0
- package/dist/lib/tmux/index.js +8 -0
- package/dist/lib/tmux/paths.d.ts +17 -0
- package/dist/lib/tmux/paths.js +30 -0
- package/dist/lib/tmux/session.d.ts +122 -0
- package/dist/lib/tmux/session.js +305 -0
- package/dist/lib/types.d.ts +73 -13
- package/dist/lib/types.js +1 -1
- package/dist/lib/usage.js +1 -1
- package/dist/lib/versions.d.ts +4 -4
- package/dist/lib/versions.js +138 -496
- package/dist/lib/workflows.d.ts +2 -4
- package/dist/lib/workflows.js +3 -4
- package/package.json +6 -3
- package/scripts/postinstall.js +16 -63
- package/dist/commands/status.d.ts +0 -9
- package/dist/commands/status.js +0 -25
package/dist/commands/setup.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* First-run setup command.
|
|
3
3
|
*
|
|
4
4
|
* Registers the `agents setup` command which clones the system repo into
|
|
5
|
-
* ~/.agents
|
|
5
|
+
* ~/.agents/.system/ and installs agent CLIs with resource syncing.
|
|
6
6
|
*/
|
|
7
7
|
import chalk from 'chalk';
|
|
8
8
|
import ora from 'ora';
|
|
@@ -14,7 +14,7 @@ import { DEFAULT_SYSTEM_REPO, systemRepoSlug } from '../lib/types.js';
|
|
|
14
14
|
import { getAgentsDir, getVersionsDir, ensureAgentsDir } from '../lib/state.js';
|
|
15
15
|
import { isGitRepo, cloneIntoExisting, pullRepo } from '../lib/git.js';
|
|
16
16
|
import { isPromptCancelled, isInteractiveTerminal } from './utils.js';
|
|
17
|
-
import { AGENTS, getUnmanagedAgentInstalls, countSessionFiles, agentLabel } from '../lib/agents.js';
|
|
17
|
+
import { AGENTS, agentConfigDirName, getUnmanagedAgentInstalls, countSessionFiles, agentLabel } from '../lib/agents.js';
|
|
18
18
|
import { setGlobalDefault } from '../lib/versions.js';
|
|
19
19
|
import { ensureShimCurrent, switchHomeFileSymlinks, isShimsInPath, addShimsToPath, getPathSetupInstructions } from '../lib/shims.js';
|
|
20
20
|
import { setHelpSections } from '../lib/help.js';
|
|
@@ -28,7 +28,7 @@ async function importAgent(agentId, version) {
|
|
|
28
28
|
const configDir = agent.configDir;
|
|
29
29
|
const versionsDir = getVersionsDir();
|
|
30
30
|
const versionHome = path.join(versionsDir, agentId, version, 'home');
|
|
31
|
-
const versionConfigDir = path.join(versionHome,
|
|
31
|
+
const versionConfigDir = path.join(versionHome, agentConfigDirName(agentId));
|
|
32
32
|
// Skip if version dir already exists (collision)
|
|
33
33
|
if (fs.existsSync(versionConfigDir)) {
|
|
34
34
|
return { success: false, skipped: true, error: `${version} already installed` };
|
|
@@ -52,12 +52,12 @@ async function importAgent(agentId, version) {
|
|
|
52
52
|
return { success: false, error: err.message };
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
/** First-run setup. Clones ~/.agents
|
|
55
|
+
/** First-run setup. Clones ~/.agents/.system/ from the system repo if needed. */
|
|
56
56
|
export async function runSetup(program, options = {}) {
|
|
57
57
|
const agentsDir = getAgentsDir();
|
|
58
58
|
const alreadyConfigured = isGitRepo(agentsDir);
|
|
59
59
|
if (alreadyConfigured && !options.force) {
|
|
60
|
-
console.log(chalk.gray('~/.agents
|
|
60
|
+
console.log(chalk.gray('~/.agents/.system/ is already set up.'));
|
|
61
61
|
console.log(chalk.gray('\nTo sync updates: agents repo pull system'));
|
|
62
62
|
console.log(chalk.gray('To re-run setup: agents setup --force'));
|
|
63
63
|
return;
|
|
@@ -73,10 +73,10 @@ export async function runSetup(program, options = {}) {
|
|
|
73
73
|
if (options.systemRepo === false) {
|
|
74
74
|
ensureAgentsDir();
|
|
75
75
|
console.log(chalk.gray('Skipping system repo clone (--no-system-repo).'));
|
|
76
|
-
console.log(chalk.gray(`Populate ~/.agents
|
|
76
|
+
console.log(chalk.gray(`Populate ~/.agents/.system/ yourself before running other commands that depend on it.\n`));
|
|
77
77
|
}
|
|
78
78
|
else {
|
|
79
|
-
console.log(chalk.gray(`Cloning the system repo from ${systemRepoSlug(systemRepo)} into ~/.agents
|
|
79
|
+
console.log(chalk.gray(`Cloning the system repo from ${systemRepoSlug(systemRepo)} into ~/.agents/.system/.\n`));
|
|
80
80
|
ensureAgentsDir();
|
|
81
81
|
const spinner = ora('Cloning system repo...').start();
|
|
82
82
|
if (isGitRepo(agentsDir)) {
|
|
@@ -93,7 +93,7 @@ export async function runSetup(program, options = {}) {
|
|
|
93
93
|
// Check git is available
|
|
94
94
|
try {
|
|
95
95
|
const { execSync } = await import('child_process');
|
|
96
|
-
execSync('
|
|
96
|
+
execSync('git --version', { stdio: 'ignore' });
|
|
97
97
|
}
|
|
98
98
|
catch {
|
|
99
99
|
spinner.fail('git is not installed');
|
|
@@ -175,7 +175,7 @@ export async function runSetup(program, options = {}) {
|
|
|
175
175
|
}
|
|
176
176
|
/**
|
|
177
177
|
* Ensure the system repo exists before running a command that needs it.
|
|
178
|
-
* If ~/.agents
|
|
178
|
+
* If ~/.agents/.system/ is not a git repo AND we're in an interactive TTY,
|
|
179
179
|
* prompt the user to run setup now. In non-interactive mode, print a clear
|
|
180
180
|
* error and exit.
|
|
181
181
|
*/
|
|
@@ -203,23 +203,23 @@ export function registerSetupCommand(program) {
|
|
|
203
203
|
const setupCmd = program
|
|
204
204
|
.command('setup')
|
|
205
205
|
.description('First-time setup. Clones a config repo and installs agent CLIs.')
|
|
206
|
-
.option('-f, --force', 'Re-run setup even if ~/.agents
|
|
207
|
-
.option('--no-system-repo', 'Skip cloning the system repo (you must populate ~/.agents
|
|
206
|
+
.option('-f, --force', 'Re-run setup even if ~/.agents/.system/ already exists (use with caution)')
|
|
207
|
+
.option('--no-system-repo', 'Skip cloning the system repo (you must populate ~/.agents/.system/ yourself)');
|
|
208
208
|
setHelpSections(setupCmd, {
|
|
209
209
|
examples: `
|
|
210
|
-
# First-time setup (clones the system repo into ~/.agents
|
|
210
|
+
# First-time setup (clones the system repo into ~/.agents/.system/)
|
|
211
211
|
agents setup
|
|
212
212
|
|
|
213
|
-
# Re-run after corruption or to repair ~/.agents
|
|
213
|
+
# Re-run after corruption or to repair ~/.agents/.system/
|
|
214
214
|
agents setup --force
|
|
215
215
|
`,
|
|
216
216
|
notes: `
|
|
217
217
|
What it does:
|
|
218
|
-
1. Clones the system repo into ~/.agents
|
|
219
|
-
2.
|
|
220
|
-
3. Syncs commands, skills, hooks, and MCP servers to each version
|
|
218
|
+
1. Clones the system repo into ~/.agents/.system/
|
|
219
|
+
2. Imports any unmanaged agent installations it finds
|
|
221
220
|
|
|
222
|
-
|
|
221
|
+
To install CLIs from agents.yaml and sync resources into version homes:
|
|
222
|
+
agents repo refresh -y
|
|
223
223
|
`,
|
|
224
224
|
});
|
|
225
225
|
setupCmd.action(async (options) => {
|
package/dist/commands/skills.js
CHANGED
|
@@ -4,7 +4,8 @@ import * as fs from 'fs';
|
|
|
4
4
|
import * as os from 'os';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import { select, checkbox } from '@inquirer/prompts';
|
|
7
|
-
import { AGENTS,
|
|
7
|
+
import { AGENTS, resolveAgentName, formatAgentError, agentLabel, } from '../lib/agents.js';
|
|
8
|
+
import { capableAgents } from '../lib/capabilities.js';
|
|
8
9
|
import { cloneRepo } from '../lib/git.js';
|
|
9
10
|
import { discoverSkillsFromRepo, installSkillCentrally, listInstalledSkills, listInstalledSkillsWithScope, getSkillInfo, getSkillRules, getSkillsDir, countSkillFiles, tryParseSkillMetadata, diffVersionSkills, iterSkillsCapableVersions, removeSkillFromVersion, } from '../lib/skills.js';
|
|
10
11
|
import { getGlobalDefault, resolveVersionAlias, syncResourcesToVersion, promptAgentVersionSelection, getVersionHomePath, } from '../lib/versions.js';
|
|
@@ -54,7 +55,7 @@ When to use:
|
|
|
54
55
|
const resolved = resolveAgentName(parts[0]);
|
|
55
56
|
if (!resolved) {
|
|
56
57
|
spinner.stop();
|
|
57
|
-
console.log(chalk.red(formatAgentError(parts[0],
|
|
58
|
+
console.log(chalk.red(formatAgentError(parts[0], capableAgents('skills'))));
|
|
58
59
|
process.exit(1);
|
|
59
60
|
}
|
|
60
61
|
filterAgent = resolved;
|
|
@@ -251,7 +252,7 @@ Examples:
|
|
|
251
252
|
let selectedAgents;
|
|
252
253
|
let versionSelections;
|
|
253
254
|
if (options.agents) {
|
|
254
|
-
const result = await resolveAgentTargetsAutoInstalling(options.agents,
|
|
255
|
+
const result = await resolveAgentTargetsAutoInstalling(options.agents, capableAgents('skills'), { yes: options.yes });
|
|
255
256
|
if (!result) {
|
|
256
257
|
console.log(chalk.gray('Cancelled.'));
|
|
257
258
|
return;
|
|
@@ -260,7 +261,7 @@ Examples:
|
|
|
260
261
|
versionSelections = result.versionSelections;
|
|
261
262
|
}
|
|
262
263
|
else {
|
|
263
|
-
const result = await promptAgentVersionSelection(
|
|
264
|
+
const result = await promptAgentVersionSelection(capableAgents('skills'), {
|
|
264
265
|
skipPrompts: options.yes,
|
|
265
266
|
});
|
|
266
267
|
selectedAgents = result.selectedAgents;
|
|
@@ -441,7 +442,7 @@ Examples:
|
|
|
441
442
|
const cwd = process.cwd();
|
|
442
443
|
const allSkills = [];
|
|
443
444
|
const seenNames = new Set();
|
|
444
|
-
for (const agentId of
|
|
445
|
+
for (const agentId of capableAgents('skills')) {
|
|
445
446
|
const skills = listInstalledSkillsWithScope(agentId, cwd);
|
|
446
447
|
for (const skill of skills) {
|
|
447
448
|
if (!seenNames.has(skill.name)) {
|
|
@@ -10,8 +10,9 @@ import ora from 'ora';
|
|
|
10
10
|
import * as fs from 'fs';
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import { agentLabel } from '../lib/agents.js';
|
|
13
|
+
import { capableAgents } from '../lib/capabilities.js';
|
|
13
14
|
import { cloneRepo } from '../lib/git.js';
|
|
14
|
-
import { discoverSubagentsFromRepo, installSubagentCentrally, listInstalledSubagents, getInstalledSubagent, listSubagentsForAgent,
|
|
15
|
+
import { discoverSubagentsFromRepo, installSubagentCentrally, listInstalledSubagents, getInstalledSubagent, listSubagentsForAgent, iterSubagentsCapableVersions, removeSubagentFromVersion, } from '../lib/subagents.js';
|
|
15
16
|
import { listInstalledVersions, syncResourcesToVersion, getGlobalDefault, getVersionHomePath, promptAgentVersionSelection, } from '../lib/versions.js';
|
|
16
17
|
import { getSubagentsDir, recordVersionResources } from '../lib/state.js';
|
|
17
18
|
import { requireDestructiveArg, promptRemovalTargets, parseCommaSeparatedList, resolveAgentTargetsAutoInstalling, } from './utils.js';
|
|
@@ -182,7 +183,7 @@ Examples:
|
|
|
182
183
|
let selectedAgents;
|
|
183
184
|
let versionSelections;
|
|
184
185
|
if (agentsArg) {
|
|
185
|
-
const result = await resolveAgentTargetsAutoInstalling(agentsArg,
|
|
186
|
+
const result = await resolveAgentTargetsAutoInstalling(agentsArg, capableAgents('subagents'), { yes: options.yes });
|
|
186
187
|
if (!result) {
|
|
187
188
|
console.log(chalk.gray('Cancelled.'));
|
|
188
189
|
return;
|
|
@@ -191,7 +192,7 @@ Examples:
|
|
|
191
192
|
versionSelections = result.versionSelections;
|
|
192
193
|
}
|
|
193
194
|
else {
|
|
194
|
-
const result = await promptAgentVersionSelection(
|
|
195
|
+
const result = await promptAgentVersionSelection(capableAgents('subagents'), {
|
|
195
196
|
skipPrompts: options.yes,
|
|
196
197
|
});
|
|
197
198
|
selectedAgents = result.selectedAgents;
|
|
@@ -307,7 +308,7 @@ Examples:
|
|
|
307
308
|
/** Every (agent, version) that supports subagents and is installed. */
|
|
308
309
|
function iterSubagentCapableVersions() {
|
|
309
310
|
const out = [];
|
|
310
|
-
for (const agent of
|
|
311
|
+
for (const agent of capableAgents('subagents')) {
|
|
311
312
|
for (const version of listInstalledVersions(agent)) {
|
|
312
313
|
out.push({ agent, version, home: getVersionHomePath(agent, version) });
|
|
313
314
|
}
|
package/dist/commands/sync.d.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* `agents sync` — synchronize central resources into an installed agent version.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Forms:
|
|
5
|
+
* agents sync claude # uses default/sole installed version
|
|
6
|
+
* agents sync claude@2.1.142 # explicit version
|
|
7
|
+
* agents sync claude@latest # newest installed
|
|
8
|
+
* agents sync --agent claude --agent-version 2.1.142 # legacy form, still supported
|
|
9
|
+
*
|
|
10
|
+
* In a TTY the command previews available/new resources and lets the user
|
|
11
|
+
* select what to sync (same prompts shown after `agents add`). Pass
|
|
12
|
+
* --yes for non-interactive auto-sync, --force to re-sync when nothing
|
|
13
|
+
* has changed, --quiet for total silence.
|
|
14
|
+
*
|
|
15
|
+
* Hot path:
|
|
16
|
+
* --launch is the shim entry point. It skips version-home reconciliation
|
|
17
|
+
* and runs only the cheap project-scoped work (rules compile, workspace
|
|
18
|
+
* resource mirror, per-scope plugin marketplaces). Filesystem-only,
|
|
19
|
+
* sub-50ms steady state. Keep changes here surgical.
|
|
7
20
|
*/
|
|
8
21
|
import { Command } from 'commander';
|
|
9
|
-
/** Register the
|
|
22
|
+
/** Register the `agents sync` command. */
|
|
10
23
|
export declare function registerSyncCommand(program: Command): void;
|
package/dist/commands/sync.js
CHANGED
|
@@ -1,88 +1,274 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* `agents sync` — synchronize central resources into an installed agent version.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Forms:
|
|
5
|
+
* agents sync claude # uses default/sole installed version
|
|
6
|
+
* agents sync claude@2.1.142 # explicit version
|
|
7
|
+
* agents sync claude@latest # newest installed
|
|
8
|
+
* agents sync --agent claude --agent-version 2.1.142 # legacy form, still supported
|
|
9
|
+
*
|
|
10
|
+
* In a TTY the command previews available/new resources and lets the user
|
|
11
|
+
* select what to sync (same prompts shown after `agents add`). Pass
|
|
12
|
+
* --yes for non-interactive auto-sync, --force to re-sync when nothing
|
|
13
|
+
* has changed, --quiet for total silence.
|
|
14
|
+
*
|
|
15
|
+
* Hot path:
|
|
16
|
+
* --launch is the shim entry point. It skips version-home reconciliation
|
|
17
|
+
* and runs only the cheap project-scoped work (rules compile, workspace
|
|
18
|
+
* resource mirror, per-scope plugin marketplaces). Filesystem-only,
|
|
19
|
+
* sub-50ms steady state. Keep changes here surgical.
|
|
7
20
|
*/
|
|
8
21
|
import * as path from 'path';
|
|
9
22
|
import chalk from 'chalk';
|
|
10
|
-
import {
|
|
11
|
-
import { isVersionInstalled, syncResourcesToVersion } from '../lib/versions.js';
|
|
23
|
+
import { agentLabel, resolveAgentName } from '../lib/agents.js';
|
|
24
|
+
import { isVersionInstalled, syncResourcesToVersion, parseAgentSpec, resolveVersion, listInstalledVersions, getAvailableResources, getActuallySyncedResources, getProjectOnlyResources, getNewResources, hasNewResources, promptResourceSelection, promptNewResourceSelection, } from '../lib/versions.js';
|
|
12
25
|
import { compileRulesForProject } from '../lib/rules/compile.js';
|
|
13
|
-
|
|
26
|
+
import { runLaunchSync } from '../lib/project-launch.js';
|
|
27
|
+
import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
|
|
28
|
+
/** Register the `agents sync` command. */
|
|
14
29
|
export function registerSyncCommand(program) {
|
|
15
30
|
program
|
|
16
|
-
.command('sync'
|
|
17
|
-
.
|
|
18
|
-
.
|
|
19
|
-
.
|
|
31
|
+
.command('sync [agentSpec]')
|
|
32
|
+
.summary('Sync resources into an installed agent version')
|
|
33
|
+
.description('Sync resources (commands, skills, hooks, rules, MCPs, plugins, etc.) into an installed agent version. Previews what will change and lets you pick.\n\n[agentSpec] is the agent name with an optional @version, e.g. "claude" or "claude@2.1.142". Omit the version to sync into the active (or sole installed) one.')
|
|
34
|
+
.option('--agent <agent>', 'Agent identifier (legacy form; prefer the positional spec)')
|
|
35
|
+
.option('--agent-version <version>', 'Version to sync into (legacy form; prefer "agent@version")')
|
|
20
36
|
.option('--project-dir <path>', 'Path to project-level .agents/ directory containing project-scoped resources')
|
|
21
37
|
.option('--cwd <path>', 'Working directory for discovering project manifest and resources')
|
|
38
|
+
.option('--launch', 'Hot-path mode (shim only): skip version-home reconciliation, run project-scoped compile + workspace mirror + plugin marketplaces', false)
|
|
39
|
+
.option('-y, --yes', 'Skip the interactive preview and auto-sync all detected resources', false)
|
|
40
|
+
.option('--force', 'Re-sync even if no changes are detected since the last sync', false)
|
|
22
41
|
.option('--quiet', 'Suppress all output (exit code indicates success)', false)
|
|
23
|
-
.action((opts) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
.action(async (agentSpec, opts) => {
|
|
43
|
+
await runSync(agentSpec, opts);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async function runSync(agentSpec, opts) {
|
|
47
|
+
const quiet = !!opts.quiet;
|
|
48
|
+
const errLog = (msg) => { if (!quiet)
|
|
49
|
+
console.error(msg); };
|
|
50
|
+
const outLog = (msg) => { if (!quiet)
|
|
51
|
+
console.log(msg); };
|
|
52
|
+
// ---------- 1. Resolve agent + version ----------
|
|
53
|
+
let agentId;
|
|
54
|
+
let version;
|
|
55
|
+
if (agentSpec) {
|
|
56
|
+
const parsed = parseAgentSpec(agentSpec);
|
|
57
|
+
if (!parsed) {
|
|
58
|
+
errLog(chalk.red(`Invalid agent spec '${agentSpec}'.`));
|
|
59
|
+
errLog(chalk.gray('Examples: claude, claude@2.1.142, codex@latest'));
|
|
33
60
|
process.exitCode = 1;
|
|
34
61
|
return;
|
|
35
62
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
63
|
+
agentId = parsed.agent;
|
|
64
|
+
if (parsed.version !== 'latest')
|
|
65
|
+
version = parsed.version;
|
|
66
|
+
}
|
|
67
|
+
if (opts.agent) {
|
|
68
|
+
const resolved = resolveAgentName(opts.agent);
|
|
69
|
+
if (!resolved) {
|
|
70
|
+
errLog(chalk.red(`Unknown agent '${opts.agent}'.`));
|
|
40
71
|
process.exitCode = 1;
|
|
41
72
|
return;
|
|
42
73
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
74
|
+
agentId = resolved;
|
|
75
|
+
}
|
|
76
|
+
if (opts.agentVersion) {
|
|
77
|
+
version = opts.agentVersion;
|
|
78
|
+
}
|
|
79
|
+
if (!agentId) {
|
|
80
|
+
errLog(chalk.red('Usage: agents sync <agent>[@version]'));
|
|
81
|
+
errLog(chalk.gray(' agents sync claude'));
|
|
82
|
+
errLog(chalk.gray(' agents sync claude@2.1.142'));
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// ---------- 2. Resolve version (project pin → global default → sole installed) ----------
|
|
87
|
+
if (!version) {
|
|
88
|
+
version = resolveVersion(agentId, process.cwd()) || undefined;
|
|
89
|
+
if (!version) {
|
|
90
|
+
const installed = listInstalledVersions(agentId);
|
|
91
|
+
if (installed.length === 1) {
|
|
92
|
+
version = installed[0];
|
|
93
|
+
}
|
|
94
|
+
else if (installed.length === 0) {
|
|
95
|
+
errLog(chalk.red(`No ${agentLabel(agentId)} versions installed.`));
|
|
96
|
+
errLog(chalk.gray(`Install one: agents add ${agentId}@latest`));
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
errLog(chalk.red(`No default ${agentLabel(agentId)} version pinned. Specify one:`));
|
|
102
|
+
for (const v of installed) {
|
|
103
|
+
errLog(chalk.gray(` agents sync ${agentId}@${v}`));
|
|
104
|
+
}
|
|
105
|
+
process.exitCode = 1;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
54
108
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
synced.push('hooks');
|
|
62
|
-
if (result.memory.length > 0)
|
|
63
|
-
synced.push('memory');
|
|
64
|
-
if (result.permissions)
|
|
65
|
-
synced.push('permissions');
|
|
66
|
-
if (result.mcp.length > 0)
|
|
67
|
-
synced.push('mcp');
|
|
68
|
-
if (result.subagents.length > 0)
|
|
69
|
-
synced.push('subagents');
|
|
70
|
-
if (result.plugins.length > 0)
|
|
71
|
-
synced.push('plugins');
|
|
72
|
-
if (synced.length > 0) {
|
|
73
|
-
console.log(chalk.green(`Synced ${synced.join(', ')} to ${agentId}@${version}`));
|
|
109
|
+
}
|
|
110
|
+
if (!isVersionInstalled(agentId, version)) {
|
|
111
|
+
errLog(chalk.red(`${agentLabel(agentId)}@${version} is not installed.`));
|
|
112
|
+
const installed = listInstalledVersions(agentId);
|
|
113
|
+
if (installed.length > 0) {
|
|
114
|
+
errLog(chalk.gray(`Installed: ${installed.join(', ')}`));
|
|
74
115
|
}
|
|
75
|
-
|
|
76
|
-
|
|
116
|
+
errLog(chalk.gray(`Install it: agents add ${agentId}@${version}`));
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const projectDir = opts.projectDir;
|
|
121
|
+
const cwd = opts.cwd || process.cwd();
|
|
122
|
+
// ---------- 3. --launch mode bypasses everything below ----------
|
|
123
|
+
if (opts.launch) {
|
|
124
|
+
runLaunchMode(agentId, version, cwd, quiet);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// ---------- 4. Decide selection (interactive preview vs auto) ----------
|
|
128
|
+
const force = !!opts.force;
|
|
129
|
+
const yes = !!opts.yes;
|
|
130
|
+
const interactive = !quiet && !yes && isInteractiveTerminal();
|
|
131
|
+
let selection;
|
|
132
|
+
if (interactive) {
|
|
133
|
+
const available = getAvailableResources(cwd);
|
|
134
|
+
const actuallySynced = getActuallySyncedResources(agentId, version, { cwd });
|
|
135
|
+
const projectOnly = getProjectOnlyResources(cwd);
|
|
136
|
+
const newResources = getNewResources(available, actuallySynced, projectOnly);
|
|
137
|
+
const hasAnySynced = anyResources(actuallySynced);
|
|
138
|
+
try {
|
|
139
|
+
if (!hasAnySynced) {
|
|
140
|
+
outLog(chalk.cyan(`Syncing to ${agentLabel(agentId)}@${version}.`));
|
|
141
|
+
const userSelection = await promptResourceSelection(agentId);
|
|
142
|
+
if (!userSelection || Object.keys(userSelection).length === 0) {
|
|
143
|
+
outLog(chalk.gray('Nothing selected. No changes made.'));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
selection = userSelection;
|
|
147
|
+
}
|
|
148
|
+
else if (hasNewResources(newResources, agentId, version)) {
|
|
149
|
+
const userSelection = await promptNewResourceSelection(agentId, newResources, version);
|
|
150
|
+
if (!userSelection || Object.keys(userSelection).length === 0) {
|
|
151
|
+
outLog(chalk.gray('Nothing selected. No changes made.'));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
selection = userSelection;
|
|
155
|
+
}
|
|
156
|
+
else if (!force) {
|
|
157
|
+
outLog(chalk.gray(`${agentLabel(agentId)}@${version} is already in sync.`));
|
|
158
|
+
outLog(chalk.gray('Run with --force to re-sync, or --yes to bypass this check.'));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// else: --force on a fully-synced version → selection stays undefined,
|
|
162
|
+
// syncResourcesToVersion falls through to its pattern-based full sync.
|
|
77
163
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
164
|
+
catch (e) {
|
|
165
|
+
if (isPromptCancelled(e)) {
|
|
166
|
+
outLog(chalk.gray('Cancelled. No changes made.'));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
throw e;
|
|
83
170
|
}
|
|
84
|
-
|
|
85
|
-
|
|
171
|
+
}
|
|
172
|
+
// ---------- 5. Run sync ----------
|
|
173
|
+
const result = syncResourcesToVersion(agentId, version, selection, { projectDir, cwd, force });
|
|
174
|
+
// Compile project-scope rules into the workspace itself so each agent's
|
|
175
|
+
// native loader picks up cwd/<INSTRUCTIONS_FILE>. projectDir is the
|
|
176
|
+
// .agents/ directory; the workspace root is its parent.
|
|
177
|
+
let projectCompile = null;
|
|
178
|
+
if (projectDir) {
|
|
179
|
+
const projectRoot = path.dirname(projectDir);
|
|
180
|
+
projectCompile = compileRulesForProject(projectRoot);
|
|
181
|
+
}
|
|
182
|
+
if (quiet)
|
|
183
|
+
return;
|
|
184
|
+
// ---------- 6. Detailed output ----------
|
|
185
|
+
printSyncDetail(result, agentId, version, cwd);
|
|
186
|
+
if (projectCompile?.compiled) {
|
|
187
|
+
const linkInfo = projectCompile.symlinks.length > 0
|
|
188
|
+
? ` (+ ${projectCompile.symlinks.join(', ')})`
|
|
189
|
+
: '';
|
|
190
|
+
console.log(chalk.gray(`Compiled project rules → ${projectCompile.agentsPath}${linkInfo}`));
|
|
191
|
+
}
|
|
192
|
+
if (projectCompile && projectCompile.skippedClobber.length > 0) {
|
|
193
|
+
console.log(chalk.yellow(`Skipped (user-authored, not overwritten): ${projectCompile.skippedClobber.join(', ')}`));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function anyResources(r) {
|
|
197
|
+
return r.commands.length + r.skills.length + r.hooks.length + r.memory.length +
|
|
198
|
+
r.mcp.length + r.permissions.length + r.subagents.length +
|
|
199
|
+
r.plugins.length + r.workflows.length > 0;
|
|
200
|
+
}
|
|
201
|
+
/** Format the post-sync detail output: per-kind count + a name preview. */
|
|
202
|
+
function printSyncDetail(result, agent, version, cwd) {
|
|
203
|
+
// Booleans in SyncResult (commands, skills, hooks, permissions) carry no
|
|
204
|
+
// name list. Re-derive ground truth from the version home so the user
|
|
205
|
+
// sees what's actually present after the sync.
|
|
206
|
+
const synced = getActuallySyncedResources(agent, version, { cwd });
|
|
207
|
+
const lines = [];
|
|
208
|
+
if (result.commands)
|
|
209
|
+
lines.push({ kind: 'commands', items: synced.commands });
|
|
210
|
+
if (result.skills)
|
|
211
|
+
lines.push({ kind: 'skills', items: synced.skills });
|
|
212
|
+
if (result.hooks)
|
|
213
|
+
lines.push({ kind: 'hooks', items: synced.hooks });
|
|
214
|
+
if (result.memory.length > 0)
|
|
215
|
+
lines.push({ kind: 'memory', items: result.memory });
|
|
216
|
+
if (result.permissions)
|
|
217
|
+
lines.push({ kind: 'permissions', items: synced.permissions });
|
|
218
|
+
if (result.mcp.length > 0)
|
|
219
|
+
lines.push({ kind: 'mcp', items: result.mcp });
|
|
220
|
+
if (result.subagents.length > 0)
|
|
221
|
+
lines.push({ kind: 'subagents', items: result.subagents });
|
|
222
|
+
if (result.plugins.length > 0)
|
|
223
|
+
lines.push({ kind: 'plugins', items: result.plugins });
|
|
224
|
+
if (result.workflows.length > 0)
|
|
225
|
+
lines.push({ kind: 'workflows', items: result.workflows });
|
|
226
|
+
if (lines.length === 0) {
|
|
227
|
+
console.log(chalk.gray(`Already in sync — ${agentLabel(agent)}@${version}`));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
console.log(chalk.green(`Synced to ${agentLabel(agent)}@${version}:`));
|
|
231
|
+
const kindWidth = Math.max(...lines.map(l => l.kind.length));
|
|
232
|
+
const PREVIEW = 5;
|
|
233
|
+
for (const { kind, items } of lines) {
|
|
234
|
+
const padded = kind.padEnd(kindWidth);
|
|
235
|
+
const sorted = [...items].sort((a, b) => a.localeCompare(b));
|
|
236
|
+
const preview = sorted.slice(0, PREVIEW).join(', ');
|
|
237
|
+
const more = sorted.length > PREVIEW ? chalk.gray(`, +${sorted.length - PREVIEW} more`) : '';
|
|
238
|
+
const count = chalk.cyan(`(${sorted.length})`.padStart(5));
|
|
239
|
+
console.log(` ${chalk.bold(padded)} ${count} ${chalk.gray(preview)}${more}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function runLaunchMode(agent, version, cwd, quiet) {
|
|
243
|
+
let result;
|
|
244
|
+
try {
|
|
245
|
+
result = runLaunchSync({ agent, version, cwd });
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
if (!quiet) {
|
|
249
|
+
console.error(chalk.yellow(`agents: launch sync skipped (${err.message})`));
|
|
86
250
|
}
|
|
87
|
-
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (quiet)
|
|
254
|
+
return;
|
|
255
|
+
const bits = [];
|
|
256
|
+
if (result.rulesCompiled)
|
|
257
|
+
bits.push('rules');
|
|
258
|
+
if (result.workspaceLinks > 0)
|
|
259
|
+
bits.push(`${result.workspaceLinks} workspace link(s)`);
|
|
260
|
+
const mpCount = Object.keys(result.marketplaces).length;
|
|
261
|
+
if (mpCount > 0) {
|
|
262
|
+
const pluginCount = Object.values(result.marketplaces).reduce((acc, names) => acc + names.length, 0);
|
|
263
|
+
bits.push(`${pluginCount} plugin(s) across ${mpCount} marketplace(s)`);
|
|
264
|
+
}
|
|
265
|
+
if (bits.length === 0) {
|
|
266
|
+
console.log(chalk.gray('No project resources to compile'));
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
console.log(chalk.green(`Launch sync: ${bits.join(', ')}`));
|
|
270
|
+
}
|
|
271
|
+
if (result.workspaceSkipped.length > 0) {
|
|
272
|
+
console.log(chalk.yellow(`Skipped (user-owned, not overwritten): ${result.workspaceSkipped.join(', ')}`));
|
|
273
|
+
}
|
|
88
274
|
}
|