@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/repo.js
CHANGED
|
@@ -26,6 +26,30 @@ function resolveRepoPath(target) {
|
|
|
26
26
|
import { ensureAgentsDir, getExtraRepoDir, getSystemAgentsDir, getUserAgentsDir, readMeta, resolveExtraRepoDir, updateMeta, } from '../lib/state.js';
|
|
27
27
|
import { parseSource, pullRepo, commitAndPush, isGitRepo, isSystemRepoOrigin } from '../lib/git.js';
|
|
28
28
|
import { DEFAULT_SYSTEM_REPO } from '../lib/types.js';
|
|
29
|
+
import { ALL_AGENT_IDS, isAgentName, resolveAgentName } from '../lib/agents.js';
|
|
30
|
+
import { refresh } from '../lib/refresh.js';
|
|
31
|
+
import { capableAgents } from '../lib/capabilities.js';
|
|
32
|
+
import { getGlobalDefault, getVersionHomePath, listInstalledVersions } from '../lib/versions.js';
|
|
33
|
+
import { syncAllMarketplaces } from '../lib/plugin-marketplace.js';
|
|
34
|
+
/**
|
|
35
|
+
* After a repo add/remove/enable/disable, reconcile each plugins-capable
|
|
36
|
+
* agent's default version against the new marketplace set. Re-synthesizes
|
|
37
|
+
* catalogs and known_marketplaces.json entries. Source-copy of plugins is
|
|
38
|
+
* out of scope here — full sync still goes through `agents repo refresh`.
|
|
39
|
+
*/
|
|
40
|
+
function syncMarketplacesForDefaults() {
|
|
41
|
+
for (const agent of capableAgents('plugins')) {
|
|
42
|
+
const def = getGlobalDefault(agent);
|
|
43
|
+
if (!def)
|
|
44
|
+
continue;
|
|
45
|
+
if (!listInstalledVersions(agent).includes(def))
|
|
46
|
+
continue;
|
|
47
|
+
try {
|
|
48
|
+
syncAllMarketplaces(agent, getVersionHomePath(agent, def));
|
|
49
|
+
}
|
|
50
|
+
catch { /* best-effort */ }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
29
53
|
const ALIAS_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/;
|
|
30
54
|
/** Derive a default alias from a source URL (e.g. gh:foo/.agents-work -> agents-work). */
|
|
31
55
|
function deriveAlias(source) {
|
|
@@ -42,16 +66,97 @@ function deriveAlias(source) {
|
|
|
42
66
|
// becomes ~/.agents-<alias>/ on disk (e.g. ".agents-work" -> "work").
|
|
43
67
|
return base.replace(/^\.+/, '').replace(/^agents-/, '') || 'repo';
|
|
44
68
|
}
|
|
45
|
-
/**
|
|
46
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Categorized working-tree summary: `M:2 A:1 D:1 ?:3` — letters match the git
|
|
71
|
+
* porcelain shorthand (Modified / Added / Deleted / Renamed / Unmerged /
|
|
72
|
+
* Untracked). Zero counts are omitted so the column stays compact.
|
|
73
|
+
*/
|
|
74
|
+
function formatDirtyCounts(status) {
|
|
75
|
+
const parts = [];
|
|
76
|
+
if (status.modified.length)
|
|
77
|
+
parts.push(chalk.yellow(`M:${status.modified.length}`));
|
|
78
|
+
if (status.created.length)
|
|
79
|
+
parts.push(chalk.green(`A:${status.created.length}`));
|
|
80
|
+
if (status.deleted.length)
|
|
81
|
+
parts.push(chalk.red(`D:${status.deleted.length}`));
|
|
82
|
+
if (status.renamed.length)
|
|
83
|
+
parts.push(chalk.cyan(`R:${status.renamed.length}`));
|
|
84
|
+
if (status.conflicted.length)
|
|
85
|
+
parts.push(chalk.magenta(`U:${status.conflicted.length}`));
|
|
86
|
+
if (status.not_added.length)
|
|
87
|
+
parts.push(chalk.gray(`?:${status.not_added.length}`));
|
|
88
|
+
return parts.join(' ');
|
|
89
|
+
}
|
|
90
|
+
/** Visible character width of a string with embedded ANSI color codes. */
|
|
91
|
+
function visibleWidth(s) {
|
|
92
|
+
return s.replace(/\[[0-9;]*m/g, '').length;
|
|
93
|
+
}
|
|
94
|
+
/** Pad string with trailing spaces to a target visible column width. */
|
|
95
|
+
function padVisible(s, width) {
|
|
96
|
+
return s + ' '.repeat(Math.max(0, width - visibleWidth(s)));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Render one row of the unified repo table: alias / branch / ahead-behind /
|
|
100
|
+
* dirty counts / url+commit. Used by `agents repo list` and the hidden
|
|
101
|
+
* `agents repo status` alias.
|
|
102
|
+
*/
|
|
103
|
+
async function renderRepoRow(t) {
|
|
104
|
+
const aliasCol = chalk.cyan(t.alias.padEnd(12));
|
|
105
|
+
if (!fs.existsSync(t.dir)) {
|
|
106
|
+
return ` ${aliasCol} ${chalk.red('missing')} ${chalk.gray(t.dir)}`;
|
|
107
|
+
}
|
|
108
|
+
if (!isGitRepo(t.dir)) {
|
|
109
|
+
return ` ${aliasCol} ${chalk.gray('local (no git remote)')} ${chalk.gray(t.dir)}`;
|
|
110
|
+
}
|
|
47
111
|
try {
|
|
48
|
-
const git = simpleGit(
|
|
49
|
-
const
|
|
50
|
-
|
|
112
|
+
const git = simpleGit(t.dir);
|
|
113
|
+
const status = await git.status();
|
|
114
|
+
const branch = status.tracking || status.current || '(detached)';
|
|
115
|
+
const inSync = (status.ahead ?? 0) === 0 && (status.behind ?? 0) === 0;
|
|
116
|
+
const remoteRaw = inSync ? 'in sync' : `+${status.ahead ?? 0} -${status.behind ?? 0}`;
|
|
117
|
+
const remoteColored = inSync ? chalk.green(remoteRaw) : chalk.yellow(remoteRaw);
|
|
118
|
+
const remotePad = ' '.repeat(Math.max(0, 12 - remoteRaw.length));
|
|
119
|
+
const tree = status.isClean() ? chalk.green('clean') : formatDirtyCounts(status);
|
|
120
|
+
const remotes = await git.getRemotes(true);
|
|
121
|
+
const origin = remotes.find((r) => r.name === 'origin');
|
|
122
|
+
const url = origin?.refs?.fetch || '';
|
|
123
|
+
const commit = (await git.log({ maxCount: 1 })).latest?.hash.slice(0, 8) || '';
|
|
124
|
+
const tail = url
|
|
125
|
+
? chalk.gray(`${url}${commit ? ` (${commit})` : ''}`)
|
|
126
|
+
: commit
|
|
127
|
+
? chalk.gray(`(${commit})`)
|
|
128
|
+
: '';
|
|
129
|
+
return ` ${aliasCol} ${branch.padEnd(28)} ${remoteColored}${remotePad} ${padVisible(tree, 14)} ${tail}`;
|
|
51
130
|
}
|
|
52
|
-
catch {
|
|
53
|
-
return
|
|
131
|
+
catch (err) {
|
|
132
|
+
return ` ${aliasCol} ${chalk.red('error')} ${err.message}`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Shared action body for `agents repo list` and the hidden `agents repo status`
|
|
137
|
+
* alias. Prints a unified table: alias, branch, ahead/behind, dirty counts,
|
|
138
|
+
* remote URL and short commit hash.
|
|
139
|
+
*/
|
|
140
|
+
async function listRepos(alias) {
|
|
141
|
+
const targets = collectRepoTargets(alias);
|
|
142
|
+
if (!targets) {
|
|
143
|
+
process.exitCode = 1;
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (targets.length === 0) {
|
|
147
|
+
console.log(chalk.gray('No repos to show.'));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
console.log('');
|
|
151
|
+
console.log(` ${chalk.gray('REPO'.padEnd(12))} ${chalk.gray('BRANCH'.padEnd(28))} ${chalk.gray('REMOTE'.padEnd(12))} ${chalk.gray('LOCAL'.padEnd(14))} ${chalk.gray('URL')}`);
|
|
152
|
+
for (const t of targets) {
|
|
153
|
+
console.log(await renderRepoRow(t));
|
|
54
154
|
}
|
|
155
|
+
const userDir = getUserAgentsDir();
|
|
156
|
+
if (!isGitRepo(userDir) && fs.existsSync(userDir)) {
|
|
157
|
+
console.log(chalk.gray('\n user repo has no git remote — scaffold one with: agents repo init'));
|
|
158
|
+
}
|
|
159
|
+
console.log('');
|
|
55
160
|
}
|
|
56
161
|
/** Register the `agents repo` command tree. */
|
|
57
162
|
export function registerRepoCommands(program) {
|
|
@@ -201,6 +306,7 @@ export function registerRepoCommands(program) {
|
|
|
201
306
|
if (parsed.type === 'local') {
|
|
202
307
|
extras[alias] = { url: parsed.url, path: parsed.url, enabled: true };
|
|
203
308
|
updateMeta({ extraRepos: extras });
|
|
309
|
+
syncMarketplacesForDefaults();
|
|
204
310
|
console.log(chalk.green(`Registered local repo "${alias}" -> ${parsed.url}`));
|
|
205
311
|
return;
|
|
206
312
|
}
|
|
@@ -236,78 +342,16 @@ export function registerRepoCommands(program) {
|
|
|
236
342
|
}
|
|
237
343
|
extras[alias] = { url: parsed.url, path: targetDir, enabled: true };
|
|
238
344
|
updateMeta({ extraRepos: extras });
|
|
345
|
+
syncMarketplacesForDefaults();
|
|
239
346
|
console.log(chalk.gray(`\nRegistered as "${alias}". Skills and commands from this repo will be`));
|
|
240
347
|
console.log(chalk.gray(`picked up automatically the next time you launch any agent.`));
|
|
241
348
|
});
|
|
242
349
|
repoCmd
|
|
243
|
-
.command('list')
|
|
350
|
+
.command('list [alias]')
|
|
244
351
|
.alias('ls')
|
|
245
|
-
.description('Show all repos:
|
|
246
|
-
.action(async () => {
|
|
247
|
-
|
|
248
|
-
console.log('');
|
|
249
|
-
// System repo
|
|
250
|
-
const systemUrl = meta.source || DEFAULT_SYSTEM_REPO;
|
|
251
|
-
const systemDir = getSystemAgentsDir();
|
|
252
|
-
const systemOnDisk = fs.existsSync(systemDir);
|
|
253
|
-
const systemIsGit = systemOnDisk && isGitRepo(systemDir);
|
|
254
|
-
const systemCommit = systemIsGit ? await getShortCommit(systemDir) : null;
|
|
255
|
-
const systemStatus = !systemOnDisk
|
|
256
|
-
? chalk.red('missing')
|
|
257
|
-
: !systemIsGit
|
|
258
|
-
? chalk.yellow('not a git repo — run: agents setup')
|
|
259
|
-
: chalk.green('cloned');
|
|
260
|
-
const systemCommitLabel = systemCommit ? chalk.gray(`(${systemCommit})`) : '';
|
|
261
|
-
console.log(chalk.bold('System (~/.agents-system/)'));
|
|
262
|
-
console.log(` ${chalk.cyan('system'.padEnd(12))} ${systemUrl} ${systemStatus} ${systemCommitLabel}`);
|
|
263
|
-
// User repo
|
|
264
|
-
const userDir = getUserAgentsDir();
|
|
265
|
-
const userOnDisk = fs.existsSync(userDir);
|
|
266
|
-
const userIsGit = userOnDisk && isGitRepo(userDir);
|
|
267
|
-
const userCommit = userIsGit ? await getShortCommit(userDir) : null;
|
|
268
|
-
let userRemoteUrl = '';
|
|
269
|
-
if (userIsGit) {
|
|
270
|
-
try {
|
|
271
|
-
const git = simpleGit(userDir);
|
|
272
|
-
const remotes = await git.getRemotes(true);
|
|
273
|
-
const origin = remotes.find(r => r.name === 'origin');
|
|
274
|
-
userRemoteUrl = origin?.refs?.fetch || '';
|
|
275
|
-
}
|
|
276
|
-
catch { /* no remote */ }
|
|
277
|
-
}
|
|
278
|
-
const userStatus = !userOnDisk
|
|
279
|
-
? chalk.gray('not created')
|
|
280
|
-
: !userIsGit
|
|
281
|
-
? chalk.gray('local (no remote)')
|
|
282
|
-
: chalk.green('cloned');
|
|
283
|
-
const userCommitLabel = userCommit ? chalk.gray(`(${userCommit})`) : '';
|
|
284
|
-
console.log(chalk.bold('\nUser (~/.agents/)'));
|
|
285
|
-
console.log(` ${chalk.cyan('user'.padEnd(12))} ${userRemoteUrl || '~/.agents/'} ${userStatus} ${userCommitLabel}`);
|
|
286
|
-
if (!userIsGit) {
|
|
287
|
-
console.log(chalk.gray(` ${''.padEnd(12)} scaffold one with: agents repo init`));
|
|
288
|
-
}
|
|
289
|
-
// Extra repos
|
|
290
|
-
const extras = meta.extraRepos || {};
|
|
291
|
-
const aliases = Object.keys(extras);
|
|
292
|
-
console.log(chalk.bold('\nExtras:'));
|
|
293
|
-
if (aliases.length === 0) {
|
|
294
|
-
console.log(chalk.gray(' (none — add one with `agents repo add <source>`)\n'));
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
for (const alias of aliases) {
|
|
298
|
-
const config = extras[alias];
|
|
299
|
-
const dir = resolveExtraRepoDir(alias, config);
|
|
300
|
-
const onDisk = fs.existsSync(dir);
|
|
301
|
-
const commit = onDisk ? await getShortCommit(dir) : null;
|
|
302
|
-
const status = !config.enabled
|
|
303
|
-
? chalk.yellow('disabled')
|
|
304
|
-
: !onDisk
|
|
305
|
-
? chalk.red('missing')
|
|
306
|
-
: chalk.green('enabled');
|
|
307
|
-
const commitLabel = commit ? chalk.gray(`(${commit})`) : '';
|
|
308
|
-
console.log(` ${chalk.cyan(alias.padEnd(12))} ${config.url} ${status} ${commitLabel}`);
|
|
309
|
-
}
|
|
310
|
-
console.log('');
|
|
352
|
+
.description('Show all repos: branch, ahead/behind, dirty counts, URL, commit.')
|
|
353
|
+
.action(async (alias) => {
|
|
354
|
+
await listRepos(alias);
|
|
311
355
|
});
|
|
312
356
|
repoCmd
|
|
313
357
|
.command('remove <alias>')
|
|
@@ -335,6 +379,7 @@ export function registerRepoCommands(program) {
|
|
|
335
379
|
}
|
|
336
380
|
delete extras[alias];
|
|
337
381
|
updateMeta({ extraRepos: extras });
|
|
382
|
+
syncMarketplacesForDefaults();
|
|
338
383
|
console.log(chalk.green(`Removed "${alias}"`));
|
|
339
384
|
});
|
|
340
385
|
repoCmd
|
|
@@ -351,7 +396,7 @@ export function registerRepoCommands(program) {
|
|
|
351
396
|
});
|
|
352
397
|
repoCmd
|
|
353
398
|
.command('pull [alias]')
|
|
354
|
-
.description('Pull updates. Aliases: "system" (~/.agents
|
|
399
|
+
.description('Pull updates. Aliases: "system" (~/.agents/.system/), "user" (~/.agents/), or any registered extra. No arg pulls all.')
|
|
355
400
|
.action(async (alias) => {
|
|
356
401
|
const targets = collectRepoTargets(alias);
|
|
357
402
|
if (!targets) {
|
|
@@ -483,46 +528,43 @@ export function registerRepoCommands(program) {
|
|
|
483
528
|
}
|
|
484
529
|
});
|
|
485
530
|
repoCmd
|
|
486
|
-
.command('
|
|
487
|
-
.description('
|
|
488
|
-
.
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
console.log(` ${chalk.cyan(t.alias.padEnd(12))} ${chalk.red('missing')} ${chalk.gray(t.dir)}`);
|
|
499
|
-
continue;
|
|
500
|
-
}
|
|
501
|
-
if (!isGitRepo(t.dir)) {
|
|
502
|
-
console.log(` ${chalk.cyan(t.alias.padEnd(12))} ${chalk.gray('not a git repo')} ${chalk.gray(t.dir)}`);
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
try {
|
|
506
|
-
const git = simpleGit(t.dir);
|
|
507
|
-
const status = await git.status();
|
|
508
|
-
const branch = status.tracking || status.current || '(detached)';
|
|
509
|
-
const remoteRaw = (status.ahead ?? 0) === 0 && (status.behind ?? 0) === 0
|
|
510
|
-
? 'in sync'
|
|
511
|
-
: `+${status.ahead ?? 0} -${status.behind ?? 0}`;
|
|
512
|
-
const remoteColored = (status.ahead ?? 0) === 0 && (status.behind ?? 0) === 0
|
|
513
|
-
? chalk.green(remoteRaw)
|
|
514
|
-
: chalk.yellow(remoteRaw);
|
|
515
|
-
const tree = status.isClean()
|
|
516
|
-
? chalk.green('clean')
|
|
517
|
-
: chalk.yellow(`${status.files.length} uncommitted`);
|
|
518
|
-
const remotePad = ' '.repeat(Math.max(0, 12 - remoteRaw.length));
|
|
519
|
-
console.log(` ${chalk.cyan(t.alias.padEnd(12))} ${branch.padEnd(28)} ${remoteColored}${remotePad} ${tree}`);
|
|
531
|
+
.command('refresh [agent]')
|
|
532
|
+
.description('Re-materialize resources into installed agent version homes. No git, no network.')
|
|
533
|
+
.option('-y, --yes', 'Auto-sync everything without prompting')
|
|
534
|
+
.option('--skip-clis', 'Skip CLI version install/upgrade from agents.yaml')
|
|
535
|
+
.action(async (arg, options) => {
|
|
536
|
+
let agentFilter;
|
|
537
|
+
if (arg) {
|
|
538
|
+
if (!isAgentName(arg)) {
|
|
539
|
+
console.log(chalk.red(`Unknown agent "${arg}".`));
|
|
540
|
+
console.log(chalk.gray(`Available: ${ALL_AGENT_IDS.join(', ')}`));
|
|
541
|
+
process.exitCode = 1;
|
|
542
|
+
return;
|
|
520
543
|
}
|
|
521
|
-
|
|
522
|
-
|
|
544
|
+
agentFilter = resolveAgentName(arg);
|
|
545
|
+
}
|
|
546
|
+
try {
|
|
547
|
+
await refresh({
|
|
548
|
+
agentFilter,
|
|
549
|
+
skipPrompts: options.yes,
|
|
550
|
+
skipClis: options.skipClis,
|
|
551
|
+
});
|
|
552
|
+
console.log(chalk.green('\nRefresh complete'));
|
|
553
|
+
}
|
|
554
|
+
catch (err) {
|
|
555
|
+
if (isPromptCancelled(err)) {
|
|
556
|
+
console.log(chalk.yellow('\nCancelled'));
|
|
557
|
+
return;
|
|
523
558
|
}
|
|
559
|
+
console.error(chalk.red(err.message));
|
|
560
|
+
process.exit(1);
|
|
524
561
|
}
|
|
525
|
-
|
|
562
|
+
});
|
|
563
|
+
repoCmd
|
|
564
|
+
.command('status [alias]', { hidden: true })
|
|
565
|
+
.description('Alias of `list` (kept for muscle memory).')
|
|
566
|
+
.action(async (alias) => {
|
|
567
|
+
await listRepos(alias);
|
|
526
568
|
});
|
|
527
569
|
}
|
|
528
570
|
/**
|
|
@@ -564,5 +606,6 @@ async function toggle(alias, enabled) {
|
|
|
564
606
|
}
|
|
565
607
|
extras[alias] = { ...extras[alias], enabled };
|
|
566
608
|
updateMeta({ extraRepos: extras });
|
|
609
|
+
syncMarketplacesForDefaults();
|
|
567
610
|
console.log(chalk.green(`${enabled ? 'Enabled' : 'Disabled'} "${alias}"`));
|
|
568
611
|
}
|
|
@@ -18,6 +18,7 @@ export interface ResourceRow {
|
|
|
18
18
|
name: string;
|
|
19
19
|
description?: string;
|
|
20
20
|
extra?: string;
|
|
21
|
+
extra2?: string;
|
|
21
22
|
targets: SyncTarget[];
|
|
22
23
|
buildDetail: () => string;
|
|
23
24
|
}
|
|
@@ -25,6 +26,7 @@ export interface ResourceViewOptions {
|
|
|
25
26
|
resourcePlural: string;
|
|
26
27
|
resourceSingular: string;
|
|
27
28
|
extraLabel?: string;
|
|
29
|
+
extra2Label?: string;
|
|
28
30
|
rows: ResourceRow[];
|
|
29
31
|
emptyMessage: string;
|
|
30
32
|
centralPath?: string;
|
|
@@ -68,10 +68,13 @@ function formatPickerRow(row, opts) {
|
|
|
68
68
|
const extra = opts.extraLabel
|
|
69
69
|
? chalk.gray(padRight(row.extra ?? '-', 10))
|
|
70
70
|
: '';
|
|
71
|
+
const extra2 = opts.extra2Label
|
|
72
|
+
? chalk.gray(padRight(row.extra2 ?? '-', 16))
|
|
73
|
+
: '';
|
|
71
74
|
const descRaw = row.description ? truncate(row.description, 40) : '';
|
|
72
75
|
const desc = padRight(chalk.gray(descRaw), 42);
|
|
73
76
|
const sync = formatSyncSummary(row.targets, opts);
|
|
74
|
-
return `${name} ${extra}${desc} ${sync}`;
|
|
77
|
+
return `${name} ${extra}${extra2}${desc} ${sync}`;
|
|
75
78
|
}
|
|
76
79
|
/** Render resources as a plain-text table (used when output is piped). */
|
|
77
80
|
function printResourceTable(opts) {
|
|
@@ -83,10 +86,13 @@ function printResourceTable(opts) {
|
|
|
83
86
|
const extra = opts.extraLabel
|
|
84
87
|
? padRight(row.extra ?? '-', 10)
|
|
85
88
|
: '';
|
|
89
|
+
const extra2 = opts.extra2Label
|
|
90
|
+
? padRight(row.extra2 ?? '-', 16)
|
|
91
|
+
: '';
|
|
86
92
|
const descRaw = row.description ? truncate(row.description, 40) : '-';
|
|
87
93
|
const desc = padRight(chalk.gray(descRaw), 42);
|
|
88
94
|
const sync = formatSyncSummary(row.targets, opts);
|
|
89
|
-
console.log(`${name} ${extra}${desc} ${sync}`);
|
|
95
|
+
console.log(`${name} ${extra}${extra2}${desc} ${sync}`);
|
|
90
96
|
}
|
|
91
97
|
console.log();
|
|
92
98
|
const summary = [
|
|
@@ -103,9 +109,12 @@ function buildTableHeader(opts) {
|
|
|
103
109
|
const extra = opts.extraLabel
|
|
104
110
|
? chalk.bold(padRight(opts.extraLabel, 10))
|
|
105
111
|
: '';
|
|
112
|
+
const extra2 = opts.extra2Label
|
|
113
|
+
? chalk.bold(padRight(opts.extra2Label, 16))
|
|
114
|
+
: '';
|
|
106
115
|
const desc = padRight(chalk.bold('Description'), 42);
|
|
107
116
|
const sync = chalk.bold('Synced');
|
|
108
|
-
return `${name} ${extra}${desc} ${sync}`;
|
|
117
|
+
return `${name} ${extra}${extra2}${desc} ${sync}`;
|
|
109
118
|
}
|
|
110
119
|
/** Compact sync summary: "everywhere", "14 of 16 installs", or "not installed". */
|
|
111
120
|
function formatSyncSummary(targets, opts) {
|
|
@@ -43,9 +43,19 @@ function isPromptCancelled(err) {
|
|
|
43
43
|
err.name === 'ExitPromptError' ||
|
|
44
44
|
err.code === 'ERR_USE_AFTER_CLOSE'));
|
|
45
45
|
}
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Interactive job picker. Returns the selected job name or null on cancel/empty.
|
|
48
|
+
*
|
|
49
|
+
* `cwd` is opt-in: pass `process.cwd()` only for inspect-class commands
|
|
50
|
+
* (`view`) whose backing operation tolerates project-layer entries. Mutation
|
|
51
|
+
* (`remove`/`edit`/`pause`/`resume`) and execution (`run`) callers omit it,
|
|
52
|
+
* which limits the picker — and therefore the user — to user-layer routines
|
|
53
|
+
* only. Without that guard, a cloned public repo's `.agents/routines/<name>.yml`
|
|
54
|
+
* would surface in `agents routines run`'s picker and execute with an
|
|
55
|
+
* attacker-supplied prompt under the user's Claude session.
|
|
56
|
+
*/
|
|
57
|
+
async function pickJob(message, filter, alternatives = [], cwd) {
|
|
58
|
+
let jobs = listAllJobs(cwd);
|
|
49
59
|
if (filter) {
|
|
50
60
|
jobs = jobs.filter(filter);
|
|
51
61
|
}
|
|
@@ -114,7 +124,7 @@ export function registerRoutinesCommands(program) {
|
|
|
114
124
|
.command('list')
|
|
115
125
|
.description('See all scheduled jobs, when they run next, and their last execution status')
|
|
116
126
|
.action(() => {
|
|
117
|
-
const jobs = listAllJobs();
|
|
127
|
+
const jobs = listAllJobs(process.cwd());
|
|
118
128
|
if (jobs.length === 0) {
|
|
119
129
|
console.log(chalk.gray('No jobs configured'));
|
|
120
130
|
console.log(chalk.gray(' Add a job: agents routines add <path-to-job.yml>'));
|
|
@@ -149,7 +159,14 @@ export function registerRoutinesCommands(program) {
|
|
|
149
159
|
for (const job of jobs) {
|
|
150
160
|
const nextRun = scheduler.getNextRun(job.name);
|
|
151
161
|
const nextStr = humanizeNextRun(nextRun ?? null, now, job.timezone);
|
|
152
|
-
|
|
162
|
+
let schedStr = humanizeCron(job.schedule, job.timezone);
|
|
163
|
+
if (job.endAt) {
|
|
164
|
+
const end = new Date(job.endAt);
|
|
165
|
+
const endLabel = Number.isFinite(end.getTime())
|
|
166
|
+
? end.toLocaleDateString()
|
|
167
|
+
: job.endAt;
|
|
168
|
+
schedStr = `${schedStr} (until ${endLabel})`;
|
|
169
|
+
}
|
|
153
170
|
const latestRun = getLatestRun(job.name);
|
|
154
171
|
const lastStatus = latestRun?.status || '-';
|
|
155
172
|
const repoInfo = formatRepoLink(job.repo);
|
|
@@ -189,6 +206,7 @@ export function registerRoutinesCommands(program) {
|
|
|
189
206
|
.option('-t, --timeout <timeout>', 'Kill the agent if it runs longer than this (e.g., 10m, 2h, 3d, 1w; max 1w)', '10m')
|
|
190
207
|
.option('--timezone <tz>', 'Interpret schedule in this timezone (e.g., America/Los_Angeles)')
|
|
191
208
|
.option('--at <time>', 'One-shot mode: run once at this time (e.g., "14:30" or "2026-02-24 09:00"), then disable')
|
|
209
|
+
.option('--end-at <iso>', 'Stop firing on or after this ISO 8601 timestamp (e.g., "2026-12-31T23:59:00Z"); routine auto-disables.')
|
|
192
210
|
.option('--disabled', 'Create the routine but keep it paused (enable later with resume)')
|
|
193
211
|
.action(async (nameOrPath, options) => {
|
|
194
212
|
// Check if inline mode (has flags) or file mode
|
|
@@ -242,6 +260,7 @@ export function registerRoutinesCommands(program) {
|
|
|
242
260
|
prompt: options.prompt,
|
|
243
261
|
timezone: options.timezone,
|
|
244
262
|
...(runOnce ? { runOnce: true } : {}),
|
|
263
|
+
...(options.endAt ? { endAt: options.endAt } : {}),
|
|
245
264
|
};
|
|
246
265
|
const errors = validateJob(config);
|
|
247
266
|
if (errors.length > 0) {
|
|
@@ -329,11 +348,11 @@ export function registerRoutinesCommands(program) {
|
|
|
329
348
|
.description('Show the full YAML configuration for a routine')
|
|
330
349
|
.action(async (name) => {
|
|
331
350
|
if (!name) {
|
|
332
|
-
name = await pickJob('Select job to view', undefined, ['agents routines view <name>']) ?? undefined;
|
|
351
|
+
name = await pickJob('Select job to view', undefined, ['agents routines view <name>'], process.cwd()) ?? undefined;
|
|
333
352
|
if (!name)
|
|
334
353
|
return;
|
|
335
354
|
}
|
|
336
|
-
const job = readJob(name);
|
|
355
|
+
const job = readJob(name, process.cwd());
|
|
337
356
|
if (!job) {
|
|
338
357
|
console.log(chalk.red(`Job '${name}' not found`));
|
|
339
358
|
process.exit(1);
|
|
@@ -430,6 +449,12 @@ export function registerRoutinesCommands(program) {
|
|
|
430
449
|
if (!name)
|
|
431
450
|
return;
|
|
432
451
|
}
|
|
452
|
+
// Execution is intentionally user-only: a routine spawns a full agent
|
|
453
|
+
// session with a YAML-supplied prompt, so a cloned public repo's
|
|
454
|
+
// `.agents/routines/<name>.yml` would be a prompt-injection vector if
|
|
455
|
+
// `run` honored the project layer. `list` / `view` stay project-aware
|
|
456
|
+
// for inspection; `run`, `remove`, `edit`, `pause`, `resume` stay on
|
|
457
|
+
// the trusted user layer.
|
|
433
458
|
const job = readJob(name);
|
|
434
459
|
if (!job) {
|
|
435
460
|
console.log(chalk.red(`Job '${name}' not found`));
|
package/dist/commands/rules.js
CHANGED
|
@@ -4,7 +4,7 @@ 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, ALL_AGENT_IDS, resolveAgentName, formatAgentError, agentLabel, } from '../lib/agents.js';
|
|
7
|
+
import { AGENTS, agentConfigDirName, ALL_AGENT_IDS, resolveAgentName, formatAgentError, agentLabel, } from '../lib/agents.js';
|
|
8
8
|
import { cloneRepo } from '../lib/git.js';
|
|
9
9
|
import { discoverInstructionsFromRepo, discoverRuleFilesFromRepo, installInstructionsCentrally, uninstallInstructions, listInstalledInstructionsWithScope, instructionsExists, getInstructionsContent, listCentralRules, } from '../lib/rules/rules.js';
|
|
10
10
|
import { listInstalledVersions, getGlobalDefault, resolveVersionAlias, syncResourcesToVersion, promptAgentVersionSelection, getVersionHomePath, } from '../lib/versions.js';
|
|
@@ -426,7 +426,7 @@ Examples:
|
|
|
426
426
|
return;
|
|
427
427
|
}
|
|
428
428
|
const home = getVersionHomePath(agentId, requestedVersion);
|
|
429
|
-
const filePath = path.join(home,
|
|
429
|
+
const filePath = path.join(home, agentConfigDirName(agentId), AGENTS[agentId].instructionsFile);
|
|
430
430
|
if (!fs.existsSync(filePath)) {
|
|
431
431
|
console.log(chalk.yellow(`No user rules found for ${agentLabel(agentId)}@${requestedVersion}`));
|
|
432
432
|
return;
|
|
@@ -486,7 +486,7 @@ Examples:
|
|
|
486
486
|
}
|
|
487
487
|
const home = getVersionHomePath(agentId, requestedVersion);
|
|
488
488
|
const agent = AGENTS[agentId];
|
|
489
|
-
const filePath = path.join(home,
|
|
489
|
+
const filePath = path.join(home, agentConfigDirName(agentId), agent.instructionsFile);
|
|
490
490
|
if (fs.existsSync(filePath)) {
|
|
491
491
|
fs.unlinkSync(filePath);
|
|
492
492
|
console.log(chalk.green(`Removed ${agent.instructionsFile} from ${agentLabel(agent.id)}@${requestedVersion}`));
|
|
@@ -556,7 +556,7 @@ Examples:
|
|
|
556
556
|
}
|
|
557
557
|
const presets = Array.from(presetSet).sort();
|
|
558
558
|
if (presets.length === 0) {
|
|
559
|
-
console.log(chalk.red('No presets found. Define presets in ~/.agents
|
|
559
|
+
console.log(chalk.red('No presets found. Define presets in ~/.agents/.system/rules/rules.yaml or ~/.agents/rules/rules.yaml.'));
|
|
560
560
|
process.exit(1);
|
|
561
561
|
}
|
|
562
562
|
let chosen = options.preset;
|
package/dist/commands/secrets.js
CHANGED
|
@@ -1052,15 +1052,15 @@ Examples:
|
|
|
1052
1052
|
password += charClass[charIndex];
|
|
1053
1053
|
}
|
|
1054
1054
|
if (opts.copy) {
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1055
|
+
try {
|
|
1056
|
+
await copyToClipboard(password);
|
|
1057
|
+
console.log(chalk.green(`Password copied to clipboard (${length} chars)`));
|
|
1058
|
+
}
|
|
1059
|
+
catch (err) {
|
|
1060
|
+
console.error(chalk.red(`Clipboard copy failed: ${err.message}`));
|
|
1061
|
+
console.error(chalk.gray('Re-run without --copy to print the password instead.'));
|
|
1062
|
+
process.exitCode = 1;
|
|
1063
|
+
}
|
|
1064
1064
|
}
|
|
1065
1065
|
else {
|
|
1066
1066
|
console.log(password);
|
|
@@ -1069,3 +1069,40 @@ Examples:
|
|
|
1069
1069
|
registerSecretsSyncCommands(cmd);
|
|
1070
1070
|
registerSecretsMigrateAclCommand(cmd);
|
|
1071
1071
|
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Copy text to the system clipboard, cross-platform.
|
|
1074
|
+
* macOS: `pbcopy`. Windows: `clip`. Linux: tries `wl-copy` (Wayland), then
|
|
1075
|
+
* `xclip`, then `xsel` (X11). Throws with an install hint if none are present.
|
|
1076
|
+
*/
|
|
1077
|
+
async function copyToClipboard(text) {
|
|
1078
|
+
const { spawn } = await import('child_process');
|
|
1079
|
+
const candidates = process.platform === 'darwin'
|
|
1080
|
+
? [['pbcopy', []]]
|
|
1081
|
+
: process.platform === 'win32'
|
|
1082
|
+
? [['clip', []]]
|
|
1083
|
+
: [
|
|
1084
|
+
['wl-copy', []],
|
|
1085
|
+
['xclip', ['-selection', 'clipboard']],
|
|
1086
|
+
['xsel', ['--clipboard', '--input']],
|
|
1087
|
+
];
|
|
1088
|
+
let lastErr = null;
|
|
1089
|
+
for (const [cmd, args] of candidates) {
|
|
1090
|
+
try {
|
|
1091
|
+
await new Promise((resolve, reject) => {
|
|
1092
|
+
const proc = spawn(cmd, args, { stdio: ['pipe', 'ignore', 'ignore'] });
|
|
1093
|
+
proc.on('error', reject);
|
|
1094
|
+
proc.on('close', (code) => (code === 0 ? resolve() : reject(new Error(`${cmd} exited ${code}`))));
|
|
1095
|
+
proc.stdin.write(text);
|
|
1096
|
+
proc.stdin.end();
|
|
1097
|
+
});
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
catch (err) {
|
|
1101
|
+
lastErr = err;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
const hint = process.platform === 'linux'
|
|
1105
|
+
? ' Install one: wl-clipboard (Wayland) or xclip / xsel (X11).'
|
|
1106
|
+
: '';
|
|
1107
|
+
throw new Error(`no clipboard tool available (${lastErr?.message ?? 'none found'}).${hint}`);
|
|
1108
|
+
}
|
package/dist/commands/setup.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
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 type { Command } from 'commander';
|
|
8
|
-
/** First-run setup. Clones ~/.agents
|
|
8
|
+
/** First-run setup. Clones ~/.agents/.system/ from the system repo if needed. */
|
|
9
9
|
export declare function runSetup(program: Command, options?: {
|
|
10
10
|
force?: boolean;
|
|
11
11
|
suppressFooter?: boolean;
|
|
@@ -13,7 +13,7 @@ export declare function runSetup(program: Command, options?: {
|
|
|
13
13
|
}): Promise<void>;
|
|
14
14
|
/**
|
|
15
15
|
* Ensure the system repo exists before running a command that needs it.
|
|
16
|
-
* If ~/.agents
|
|
16
|
+
* If ~/.agents/.system/ is not a git repo AND we're in an interactive TTY,
|
|
17
17
|
* prompt the user to run setup now. In non-interactive mode, print a clear
|
|
18
18
|
* error and exit.
|
|
19
19
|
*/
|