@phnx-labs/agents-cli 1.18.5 → 1.19.0
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 +13 -2
- package/README.md +22 -20
- package/dist/commands/browser.js +25 -2
- package/dist/commands/cloud.js +3 -3
- package/dist/commands/computer.d.ts +6 -0
- package/dist/commands/computer.js +477 -0
- package/dist/commands/doctor.js +19 -17
- package/dist/commands/exec.js +37 -59
- package/dist/commands/factory.js +12 -5
- package/dist/commands/import.js +6 -1
- package/dist/commands/mcp.js +9 -4
- package/dist/commands/packages.d.ts +3 -0
- package/dist/commands/packages.js +20 -12
- package/dist/commands/permissions.d.ts +2 -0
- package/dist/commands/permissions.js +20 -1
- package/dist/commands/plugins.d.ts +2 -0
- package/dist/commands/plugins.js +23 -4
- package/dist/commands/profiles.js +1 -1
- package/dist/commands/pty.js +126 -112
- package/dist/commands/pull.js +29 -25
- package/dist/commands/repo.js +24 -26
- package/dist/commands/routines.js +29 -26
- package/dist/commands/secrets.js +66 -73
- package/dist/commands/sessions-tail.js +21 -22
- package/dist/commands/sessions.js +36 -68
- package/dist/commands/setup.js +20 -24
- package/dist/commands/teams.js +30 -39
- package/dist/commands/versions.js +60 -68
- package/dist/commands/worktree.d.ts +20 -0
- package/dist/commands/worktree.js +242 -0
- package/dist/computer.d.ts +2 -0
- package/dist/computer.js +7 -0
- package/dist/index.js +70 -26
- package/dist/lib/agents.d.ts +4 -1
- package/dist/lib/agents.js +23 -5
- package/dist/lib/browser/cdp.d.ts +15 -1
- package/dist/lib/browser/cdp.js +77 -8
- package/dist/lib/browser/chrome.js +17 -24
- package/dist/lib/browser/drivers/ssh.d.ts +1 -0
- package/dist/lib/browser/drivers/ssh.js +20 -8
- package/dist/lib/browser/ipc.js +38 -5
- package/dist/lib/browser/profiles.js +34 -2
- package/dist/lib/browser/runtime-state.d.ts +1 -2
- package/dist/lib/browser/runtime-state.js +11 -3
- package/dist/lib/browser/service.d.ts +5 -0
- package/dist/lib/browser/service.js +32 -4
- package/dist/lib/browser/types.d.ts +1 -1
- package/dist/lib/browser/upload.d.ts +2 -0
- package/dist/lib/browser/upload.js +34 -0
- package/dist/lib/cloud/rush.d.ts +2 -1
- package/dist/lib/cloud/rush.js +28 -9
- package/dist/lib/computer-rpc.d.ts +24 -0
- package/dist/lib/computer-rpc.js +263 -0
- package/dist/lib/daemon.js +7 -7
- package/dist/lib/exec.d.ts +2 -1
- package/dist/lib/exec.js +3 -2
- package/dist/lib/fs-atomic.d.ts +18 -0
- package/dist/lib/fs-atomic.js +76 -0
- package/dist/lib/git.js +2 -4
- package/dist/lib/help.d.ts +15 -0
- package/dist/lib/help.js +41 -0
- package/dist/lib/hooks/match.d.ts +1 -0
- package/dist/lib/hooks/match.js +57 -12
- package/dist/lib/hooks.d.ts +1 -0
- package/dist/lib/hooks.js +27 -10
- package/dist/lib/import.d.ts +1 -0
- package/dist/lib/import.js +7 -0
- package/dist/lib/manifest.js +27 -1
- package/dist/lib/mcp.d.ts +14 -0
- package/dist/lib/mcp.js +79 -14
- package/dist/lib/migrate.js +3 -3
- package/dist/lib/models.js +3 -1
- package/dist/lib/permissions.d.ts +5 -0
- package/dist/lib/permissions.js +35 -0
- package/dist/lib/plugin-marketplace.d.ts +3 -1
- package/dist/lib/plugin-marketplace.js +36 -1
- package/dist/lib/plugins.d.ts +19 -1
- package/dist/lib/plugins.js +99 -8
- package/dist/lib/redact.d.ts +4 -0
- package/dist/lib/redact.js +18 -0
- package/dist/lib/registry.d.ts +2 -0
- package/dist/lib/registry.js +15 -0
- package/dist/lib/sandbox.js +15 -5
- package/dist/lib/secrets/bundles.d.ts +7 -12
- package/dist/lib/secrets/bundles.js +45 -29
- package/dist/lib/secrets/index.js +4 -4
- package/dist/lib/session/cloud.d.ts +2 -0
- package/dist/lib/session/cloud.js +34 -6
- package/dist/lib/session/parse.js +7 -2
- package/dist/lib/session/render.d.ts +4 -1
- package/dist/lib/session/render.js +81 -35
- package/dist/lib/shims.d.ts +5 -2
- package/dist/lib/shims.js +29 -7
- package/dist/lib/state.d.ts +5 -5
- package/dist/lib/state.js +43 -13
- package/dist/lib/teams/agents.d.ts +1 -1
- package/dist/lib/teams/agents.js +2 -2
- package/dist/lib/types.d.ts +4 -3
- package/dist/lib/types.js +0 -2
- package/dist/lib/versions.js +65 -40
- package/dist/lib/workflows.d.ts +7 -0
- package/dist/lib/workflows.js +42 -1
- package/npm-shrinkwrap.json +3256 -0
- package/package.json +32 -26
- package/scripts/postinstall.js +8 -2
package/dist/commands/secrets.js
CHANGED
|
@@ -10,7 +10,7 @@ import * as fs from 'fs';
|
|
|
10
10
|
import { bundleExists, deleteBundle, describeBundle, keychainItemsForBundle, keychainRef, listBundles, migrateLegacyBundles, parseDotenv, readBundle, renameBundle, rotateBundleSecret, validateBundleName, validateEnvKey, validateExpiresFutureDated, validateSecretType, writeBundle, } from '../lib/secrets/bundles.js';
|
|
11
11
|
import { deleteKeychainToken, getKeychainToken, hasKeychainToken, secretsKeychainItem, setKeychainToken, } from '../lib/secrets/index.js';
|
|
12
12
|
import { assertOpAvailable, createPasswordItem, deleteItemByTitle, extractSecrets, itemExistsByTitle, listItems, listVaults, } from '../lib/onepassword.js';
|
|
13
|
-
import { registerCommandGroups } from '../lib/help.js';
|
|
13
|
+
import { registerCommandGroups, setHelpSections } from '../lib/help.js';
|
|
14
14
|
import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
|
|
15
15
|
/** Prompt the user for a secret value with masked input. Requires an interactive TTY. */
|
|
16
16
|
async function promptForSecret(message) {
|
|
@@ -314,86 +314,45 @@ function countExpiringSoon(meta) {
|
|
|
314
314
|
export function registerSecretsCommands(program) {
|
|
315
315
|
const cmd = program
|
|
316
316
|
.command('secrets')
|
|
317
|
-
.description('Named bundles of env variables backed by macOS Keychain (iCloud-synced by default). Inject into agents via `agents run --secrets <name>`.')
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
bundle once, add secrets to it, then inject the whole bundle into any agent
|
|
323
|
-
run with --secrets <name>. Keychain-backed values never touch disk in
|
|
324
|
-
plaintext.
|
|
325
|
-
|
|
326
|
-
New bundles store values in the iCloud-synced keychain by default so they
|
|
327
|
-
appear automatically on your other Macs (same iCloud account, iCloud
|
|
328
|
-
Keychain enabled). Pass --no-icloud-sync at create time to keep values
|
|
329
|
-
device-local instead.
|
|
330
|
-
|
|
331
|
-
Examples:
|
|
332
|
-
# Create a bundle for production credentials (iCloud-synced by default)
|
|
333
|
-
agents secrets create prod --description "Production keys for the api stack"
|
|
334
|
-
|
|
335
|
-
# Create a bundle that never leaves this Mac
|
|
336
|
-
agents secrets create local-only --no-icloud-sync
|
|
337
|
-
|
|
338
|
-
# Rename a bundle (moves metadata + every keychain value)
|
|
339
|
-
agents secrets rename prod production
|
|
340
|
-
|
|
341
|
-
# Edit the description of an existing bundle
|
|
342
|
-
agents secrets describe prod "Production keys for the api stack"
|
|
343
|
-
agents secrets describe prod --clear
|
|
344
|
-
|
|
345
|
-
# Add a keychain-backed secret (prompts for the value)
|
|
346
|
-
agents secrets add prod STRIPE_API_KEY
|
|
347
|
-
|
|
348
|
-
# Add a literal (non-sensitive) value
|
|
349
|
-
agents secrets add prod LOG_LEVEL --value info
|
|
317
|
+
.description('Named bundles of env variables backed by macOS Keychain (iCloud-synced by default). Inject into agents via `agents run --secrets <name>`.');
|
|
318
|
+
setHelpSections(cmd, {
|
|
319
|
+
examples: `
|
|
320
|
+
# Create a bundle
|
|
321
|
+
agents secrets create prod --description "Production keys for the api stack"
|
|
350
322
|
|
|
351
|
-
|
|
352
|
-
|
|
323
|
+
# Add a keychain-backed secret (prompts for the value)
|
|
324
|
+
agents secrets add prod STRIPE_API_KEY
|
|
353
325
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
# Import an entire .env file straight into keychain
|
|
358
|
-
agents secrets import prod --from .env.prod
|
|
359
|
-
|
|
360
|
-
# Import secrets from a 1Password vault
|
|
361
|
-
agents secrets import prod --from-1password --vault "Rush Prod"
|
|
362
|
-
|
|
363
|
-
# Push a bundle back to 1Password (vault migration, backup)
|
|
364
|
-
agents secrets export prod --to-1password --vault "Rush Prod"
|
|
365
|
-
agents secrets export prod --to-1password --vault "Rush Prod" --force
|
|
366
|
-
|
|
367
|
-
# See what's in a bundle (values masked)
|
|
368
|
-
agents secrets view prod
|
|
326
|
+
# Add a non-sensitive literal
|
|
327
|
+
agents secrets add prod LOG_LEVEL --value info
|
|
369
328
|
|
|
370
|
-
|
|
371
|
-
|
|
329
|
+
# Inject the bundle into an agent run
|
|
330
|
+
agents run claude "deploy the worker" --secrets prod
|
|
372
331
|
|
|
373
|
-
|
|
374
|
-
|
|
332
|
+
# See what's in the bundle (values masked)
|
|
333
|
+
agents secrets view prod
|
|
375
334
|
|
|
376
|
-
|
|
377
|
-
|
|
335
|
+
# Eval the bundle into your current shell
|
|
336
|
+
eval "$(agents secrets export prod --plaintext)"
|
|
378
337
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
338
|
+
# Run a one-off command with secrets injected
|
|
339
|
+
agents secrets exec prod -- ./deploy.sh
|
|
340
|
+
`,
|
|
341
|
+
notes: `
|
|
342
|
+
Bundles are containers; secrets are the variables inside them. Keychain values
|
|
343
|
+
never touch disk in plaintext.
|
|
382
344
|
|
|
383
|
-
|
|
384
|
-
|
|
345
|
+
iCloud sync: new bundles use the iCloud-synced keychain by default so they
|
|
346
|
+
appear on other Macs (same iCloud account, iCloud Keychain enabled). Pass
|
|
347
|
+
--no-icloud-sync at create time to keep values device-local instead.
|
|
385
348
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
agents secrets generate 16
|
|
394
|
-
agents secrets generate 8 --pin
|
|
395
|
-
agents secrets generate 32 --hex
|
|
396
|
-
`);
|
|
349
|
+
See also:
|
|
350
|
+
agents secrets rotate <bundle> <key> rotate value, preserve metadata
|
|
351
|
+
agents secrets import <bundle> --from .env bulk import from .env
|
|
352
|
+
agents secrets import <bundle> --from-1password --vault <name>
|
|
353
|
+
agents secrets generate [length] generate a random password / PIN / hex
|
|
354
|
+
`,
|
|
355
|
+
});
|
|
397
356
|
registerCommandGroups(cmd, [
|
|
398
357
|
{ title: 'Bundle commands', names: ['list', 'view', 'create', 'rename', 'describe', 'delete'] },
|
|
399
358
|
{ title: 'Secret commands', names: ['add', 'rotate', 'remove', 'import', 'export'] },
|
|
@@ -796,6 +755,40 @@ Examples:
|
|
|
796
755
|
process.exit(1);
|
|
797
756
|
}
|
|
798
757
|
});
|
|
758
|
+
cmd
|
|
759
|
+
.command('migrate')
|
|
760
|
+
.description('Interactively migrate legacy YAML bundles into Keychain')
|
|
761
|
+
.action(async () => {
|
|
762
|
+
try {
|
|
763
|
+
if (!isInteractiveTerminal()) {
|
|
764
|
+
console.error(chalk.red('Refusing to migrate legacy secrets without an interactive confirmation prompt.'));
|
|
765
|
+
process.exit(1);
|
|
766
|
+
}
|
|
767
|
+
const { confirm } = await import('@inquirer/prompts');
|
|
768
|
+
const migrated = await migrateLegacyBundles(async (candidate) => {
|
|
769
|
+
console.log(chalk.bold(`Legacy bundle '${candidate.name}'`));
|
|
770
|
+
console.log(chalk.gray(candidate.file));
|
|
771
|
+
for (const key of candidate.keys) {
|
|
772
|
+
console.log(` ${key}`);
|
|
773
|
+
}
|
|
774
|
+
return await confirm({
|
|
775
|
+
message: `Migrate legacy bundle '${candidate.name}' into Keychain?`,
|
|
776
|
+
default: false,
|
|
777
|
+
});
|
|
778
|
+
});
|
|
779
|
+
if (migrated === 0) {
|
|
780
|
+
console.log(chalk.gray('No legacy bundles migrated.'));
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
console.log(chalk.green(`Migrated ${migrated} legacy bundle${migrated === 1 ? '' : 's'} into keychain.`));
|
|
784
|
+
}
|
|
785
|
+
catch (err) {
|
|
786
|
+
if (isPromptCancelled(err))
|
|
787
|
+
return;
|
|
788
|
+
console.error(chalk.red(err.message));
|
|
789
|
+
process.exit(1);
|
|
790
|
+
}
|
|
791
|
+
});
|
|
799
792
|
cmd
|
|
800
793
|
.command('import [bundle]')
|
|
801
794
|
.description('Import keys from a .env file or a 1Password vault into a bundle. By default every key is stored in keychain.')
|
|
@@ -10,6 +10,7 @@ import * as fsp from 'fs/promises';
|
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
import chalk from 'chalk';
|
|
12
12
|
import { discoverSessions, resolveSessionById } from '../lib/session/discover.js';
|
|
13
|
+
import { setHelpSections } from '../lib/help.js';
|
|
13
14
|
const TAIL_SUPPORTED = ['claude', 'codex'];
|
|
14
15
|
/**
|
|
15
16
|
* Tail a file: emit each newline-terminated line via onLine as it's written.
|
|
@@ -202,34 +203,32 @@ async function runTail(sessionId, options) {
|
|
|
202
203
|
}
|
|
203
204
|
/** Attach the `tail` subcommand to an existing `sessions` command. */
|
|
204
205
|
export function registerSessionsTailCommand(sessionsCmd) {
|
|
205
|
-
sessionsCmd
|
|
206
|
+
const tailCmd = sessionsCmd
|
|
206
207
|
.command('tail [sessionId]')
|
|
207
|
-
.description('
|
|
208
|
+
.description('Stream JSONL events from a session file as they are written, one event per line. Long-running: Ctrl+C to stop. Claude and Codex only.')
|
|
208
209
|
.option('--latest', 'Tail the most recent tailable session (claude or codex)')
|
|
209
210
|
.option('--from-start', 'Emit the full file first, then follow (default: start at EOF)')
|
|
210
|
-
.option('--json', 'Raw JSONL passthrough (default)')
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
.option('--json', 'Raw JSONL passthrough (default)');
|
|
212
|
+
setHelpSections(tailCmd, {
|
|
213
|
+
examples: `
|
|
214
|
+
# Follow the most recent active Claude or Codex session
|
|
215
|
+
agents sessions tail --latest
|
|
214
216
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
agents sessions tail --latest
|
|
217
|
+
# Follow a specific session by short or full ID
|
|
218
|
+
agents sessions tail a1b2c3d4
|
|
218
219
|
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
# Replay from the beginning, then follow
|
|
221
|
+
agents sessions tail a1b2c3d4 --from-start
|
|
221
222
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
`)
|
|
232
|
-
.action(async (sessionId, options) => {
|
|
223
|
+
# Pipe through jq to extract just user messages
|
|
224
|
+
agents sessions tail --latest | jq 'select(.type == "user")'
|
|
225
|
+
`,
|
|
226
|
+
notes: `
|
|
227
|
+
- Only Claude and Codex sessions are tailable — they append JSONL one event per line.
|
|
228
|
+
- Gemini, OpenCode, and OpenClaw use formats that rewrite the file or store state elsewhere.
|
|
229
|
+
`,
|
|
230
|
+
});
|
|
231
|
+
tailCmd.action(async (sessionId, options) => {
|
|
233
232
|
await runTail(sessionId, options);
|
|
234
233
|
});
|
|
235
234
|
}
|
|
@@ -25,6 +25,7 @@ import { colorAgent, resolveAgentName } from '../lib/agents.js';
|
|
|
25
25
|
import { resolveVersion, resolveVersionAliasLoose } from '../lib/versions.js';
|
|
26
26
|
import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
|
|
27
27
|
import { sessionPicker } from './sessions-picker.js';
|
|
28
|
+
import { setHelpSections } from '../lib/help.js';
|
|
28
29
|
import { registerSessionsTailCommand } from './sessions-tail.js';
|
|
29
30
|
const SESSION_AGENT_FILTER_HELP = `Filter by agent, e.g. claude, codex, claude@2.0.65`;
|
|
30
31
|
const CLAUDE_RESUME_MATCH_WINDOW_MS = 10 * 60_000;
|
|
@@ -297,7 +298,7 @@ async function sessionsAction(query, options) {
|
|
|
297
298
|
// When the user explicitly asks to render (via mode flag), resolve the
|
|
298
299
|
// query globally so sessions outside the default cwd/30d window are found.
|
|
299
300
|
if (wantsRender && searchQuery) {
|
|
300
|
-
await renderOneSession(searchQuery, mode, { agent: options.agent, project: options.project, filter: filterOpts });
|
|
301
|
+
await renderOneSession(searchQuery, mode, { agent: options.agent, project: options.project, filter: filterOpts, noRedact: options.noRedact });
|
|
301
302
|
return;
|
|
302
303
|
}
|
|
303
304
|
// Interactive picker loads a deep pool but shows only recent sessions
|
|
@@ -347,11 +348,11 @@ async function sessionsAction(query, options) {
|
|
|
347
348
|
if (searchQuery) {
|
|
348
349
|
const idMatches = resolveSessionById(sessions, searchQuery);
|
|
349
350
|
if (idMatches.length === 1) {
|
|
350
|
-
await renderSession(idMatches[0], mode, filterOpts);
|
|
351
|
+
await renderSession(idMatches[0], mode, filterOpts, options);
|
|
351
352
|
return;
|
|
352
353
|
}
|
|
353
354
|
if (idMatches.length === 0 && looksLikeSessionId(searchQuery)) {
|
|
354
|
-
await renderOneSession(searchQuery, mode, { agent: options.agent, project: options.project, filter: filterOpts });
|
|
355
|
+
await renderOneSession(searchQuery, mode, { agent: options.agent, project: options.project, filter: filterOpts, noRedact: options.noRedact });
|
|
355
356
|
return;
|
|
356
357
|
}
|
|
357
358
|
}
|
|
@@ -472,7 +473,7 @@ function resolveViewMode(options, filters) {
|
|
|
472
473
|
return 'markdown';
|
|
473
474
|
return 'summary';
|
|
474
475
|
}
|
|
475
|
-
async function renderSession(session, mode, filters) {
|
|
476
|
+
async function renderSession(session, mode, filters, options = {}) {
|
|
476
477
|
// OpenCode stores sessions in SQLite; filePath is "db_path#session_id"
|
|
477
478
|
const realPath = session.filePath.split('#')[0];
|
|
478
479
|
if (!fs.existsSync(realPath)) {
|
|
@@ -518,7 +519,7 @@ async function renderSession(session, mode, filters) {
|
|
|
518
519
|
chalk.gray(` ${formatRelativeTime(session.timestamp)}`) +
|
|
519
520
|
(session.account ? chalk.gray(` (${session.account})`) : ''));
|
|
520
521
|
console.log(chalk.gray('─'.repeat(60)));
|
|
521
|
-
process.stdout.write(renderMarkdown(renderConversationMarkdown(events)));
|
|
522
|
+
process.stdout.write(renderMarkdown(renderConversationMarkdown(events, { redact: options.noRedact !== true })));
|
|
522
523
|
return;
|
|
523
524
|
}
|
|
524
525
|
// json — no header, raw events only (pipeable)
|
|
@@ -731,7 +732,7 @@ async function runCloudSessions(query, options) {
|
|
|
731
732
|
const cachedSpinner = options.json ? null : ora('Fetching session...').start();
|
|
732
733
|
let cachedPath;
|
|
733
734
|
try {
|
|
734
|
-
cachedPath = await ensureCloudSessionCached(meta.id
|
|
735
|
+
cachedPath = await ensureCloudSessionCached(meta.id);
|
|
735
736
|
}
|
|
736
737
|
catch (err) {
|
|
737
738
|
cachedSpinner?.stop();
|
|
@@ -740,7 +741,7 @@ async function runCloudSessions(query, options) {
|
|
|
740
741
|
}
|
|
741
742
|
cachedSpinner?.stop();
|
|
742
743
|
// Ensure the SessionMeta points at the local cache path for renderSession.
|
|
743
|
-
await renderSession({ ...meta, filePath: cachedPath }, mode, filterOpts);
|
|
744
|
+
await renderSession({ ...meta, filePath: cachedPath }, mode, filterOpts, options);
|
|
744
745
|
}
|
|
745
746
|
function parseAgentFilter(agentName) {
|
|
746
747
|
if (!agentName)
|
|
@@ -986,7 +987,7 @@ async function renderOneSession(query, mode, scope) {
|
|
|
986
987
|
throw new Error('Session resolution failed');
|
|
987
988
|
}
|
|
988
989
|
spinner.stop();
|
|
989
|
-
await renderSession(session, mode, scope.filter);
|
|
990
|
+
await renderSession(session, mode, scope.filter, { noRedact: scope.noRedact });
|
|
990
991
|
}
|
|
991
992
|
catch (err) {
|
|
992
993
|
if (isPromptCancelled(err))
|
|
@@ -1011,6 +1012,7 @@ export function registerSessionsCommands(program) {
|
|
|
1011
1012
|
.option('--until <time>', 'Only sessions older than this (ISO timestamp)')
|
|
1012
1013
|
.option('-n, --limit <n>', 'Maximum number of sessions to return', '50')
|
|
1013
1014
|
.option('--markdown', 'Render the session as markdown (user, assistant, thinking, tool calls)')
|
|
1015
|
+
.option('--no-redact', 'Disable default secret redaction in markdown session output')
|
|
1014
1016
|
.option('--json', 'Output JSON (session list when browsing, event array when rendering one session)')
|
|
1015
1017
|
.option('--include <roles>', 'Only include these roles (comma-separated): user, assistant, thinking, tools')
|
|
1016
1018
|
.option('--exclude <roles>', 'Exclude these roles (comma-separated): user, assistant, thinking, tools')
|
|
@@ -1019,70 +1021,36 @@ export function registerSessionsCommands(program) {
|
|
|
1019
1021
|
.option('--artifacts', 'List all files written or edited during a session')
|
|
1020
1022
|
.option('--artifact <name>', 'Read a specific artifact by filename or path (outputs to stdout)')
|
|
1021
1023
|
.option('--active', 'Show only sessions running right now across terminals, teams, cloud, and headless agents')
|
|
1022
|
-
.option('--cloud', 'Source sessions from Rush Cloud (captured runs) instead of local disk')
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1024
|
+
.option('--cloud', 'Source sessions from Rush Cloud (captured runs) instead of local disk');
|
|
1025
|
+
setHelpSections(sessionsCmd, {
|
|
1026
|
+
examples: `
|
|
1027
|
+
# Search prior sessions in this project by topic, file path, or command
|
|
1028
|
+
agents sessions "add auth middleware"
|
|
1027
1029
|
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
+
# Read a session as markdown (user + assistant + thinking + tools)
|
|
1031
|
+
agents sessions a1b2c3d4 --markdown
|
|
1030
1032
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
+
# Just the user turns — useful for recalling intent
|
|
1034
|
+
agents sessions a1b2c3d4 --include user
|
|
1033
1035
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
+
# Show only what's running right now (terminals, teams, cloud, headless)
|
|
1037
|
+
agents sessions --active
|
|
1036
1038
|
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
+
# Search across every directory, not just this project
|
|
1040
|
+
agents sessions "topic" --all
|
|
1039
1041
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
# Only user messages (filter flags auto-select markdown)
|
|
1053
|
-
agents sessions a1b2c3d4 --include user
|
|
1054
|
-
|
|
1055
|
-
# Everything except thinking, as markdown
|
|
1056
|
-
agents sessions a1b2c3d4 --exclude thinking --markdown
|
|
1057
|
-
|
|
1058
|
-
# Last 3 turns as markdown
|
|
1059
|
-
agents sessions a1b2c3d4 --last 3
|
|
1060
|
-
|
|
1061
|
-
# First 10 turns, user messages only, as JSON
|
|
1062
|
-
agents sessions a1b2c3d4 --first 10 --include user --json
|
|
1063
|
-
|
|
1064
|
-
# Export all recent sessions as JSON for analysis
|
|
1065
|
-
agents sessions --since 30d --limit 200 --json > sessions.json
|
|
1066
|
-
|
|
1067
|
-
# Include team-spawned sessions in results
|
|
1068
|
-
agents sessions --teams
|
|
1069
|
-
|
|
1070
|
-
# Show only live sessions across terminals, teams, cloud, and headless agents
|
|
1071
|
-
agents sessions --active
|
|
1072
|
-
agents sessions --active --json
|
|
1073
|
-
|
|
1074
|
-
# List captured cloud-run sessions (claude/codex/rush) via Rush Cloud
|
|
1075
|
-
agents sessions --cloud
|
|
1076
|
-
agents sessions --cloud <execution_id>
|
|
1077
|
-
agents sessions --cloud <execution_id> --markdown
|
|
1078
|
-
agents sessions --cloud <execution_id> --include user,assistant --last 3
|
|
1079
|
-
|
|
1080
|
-
Notes:
|
|
1081
|
-
- --include and --exclude are mutually exclusive.
|
|
1082
|
-
- --first and --last are mutually exclusive.
|
|
1083
|
-
- A filter flag without --markdown/--json defaults to --markdown output.
|
|
1084
|
-
`)
|
|
1085
|
-
.action(async (query, options) => {
|
|
1042
|
+
# Export for analysis
|
|
1043
|
+
agents sessions --since 30d --limit 200 --json > sessions.json
|
|
1044
|
+
`,
|
|
1045
|
+
notes: `
|
|
1046
|
+
- --include and --exclude are mutually exclusive.
|
|
1047
|
+
- --first and --last are mutually exclusive.
|
|
1048
|
+
- A filter flag (--include/--exclude/--first/--last) without --markdown/--json defaults to --markdown output.
|
|
1049
|
+
- --cloud sources from Rush Cloud captured runs instead of local disk.
|
|
1050
|
+
- Without --teams, team-spawned sessions are hidden by default.
|
|
1051
|
+
`,
|
|
1052
|
+
});
|
|
1053
|
+
sessionsCmd.action(async (query, options) => {
|
|
1086
1054
|
await sessionsAction(query, options);
|
|
1087
1055
|
});
|
|
1088
1056
|
registerSessionsTailCommand(sessionsCmd);
|
|
@@ -1272,7 +1240,7 @@ function formatAbsoluteTime(isoTimestamp) {
|
|
|
1272
1240
|
return `${months[d.getMonth()]} ${d.getDate()} ${hh}:${mm}`;
|
|
1273
1241
|
}
|
|
1274
1242
|
function padRight(s, width) {
|
|
1275
|
-
return s.length >= width ? s
|
|
1243
|
+
return s.length >= width ? s : s + ' '.repeat(width - s.length);
|
|
1276
1244
|
}
|
|
1277
1245
|
function truncate(s, max) {
|
|
1278
1246
|
return s.length > max ? s.slice(0, max - 1) + '.' : s;
|
package/dist/commands/setup.js
CHANGED
|
@@ -17,6 +17,7 @@ import { isPromptCancelled, isInteractiveTerminal } from './utils.js';
|
|
|
17
17
|
import { AGENTS, 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
|
+
import { setHelpSections } from '../lib/help.js';
|
|
20
21
|
const HOME = os.homedir();
|
|
21
22
|
/**
|
|
22
23
|
* Import an existing unmanaged agent installation into agents-cli.
|
|
@@ -191,33 +192,28 @@ export async function ensureInitialized(program) {
|
|
|
191
192
|
}
|
|
192
193
|
/** Register the `agents setup` command. */
|
|
193
194
|
export function registerSetupCommand(program) {
|
|
194
|
-
program
|
|
195
|
+
const setupCmd = program
|
|
195
196
|
.command('setup')
|
|
196
|
-
.description('
|
|
197
|
-
.option('-f, --force', 'Re-run setup even if ~/.agents-system/ already exists (use with caution)')
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
197
|
+
.description('First-time setup. Clones a config repo and installs agent CLIs.')
|
|
198
|
+
.option('-f, --force', 'Re-run setup even if ~/.agents-system/ already exists (use with caution)');
|
|
199
|
+
setHelpSections(setupCmd, {
|
|
200
|
+
examples: `
|
|
201
|
+
# First-time setup (clones the system repo into ~/.agents-system/)
|
|
202
|
+
agents setup
|
|
202
203
|
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
# Re-run after corruption or to repair ~/.agents-system/
|
|
205
|
+
agents setup --force
|
|
206
|
+
`,
|
|
207
|
+
notes: `
|
|
208
|
+
What it does:
|
|
209
|
+
1. Clones the system repo into ~/.agents-system/
|
|
210
|
+
2. Installs agent CLIs based on agents.yaml in that repo
|
|
211
|
+
3. Syncs commands, skills, hooks, and MCP servers to each version
|
|
205
212
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
What it does:
|
|
212
|
-
1. Clones the system repo into ~/.agents-system/
|
|
213
|
-
2. Installs agent CLIs based on agents.yaml in that repo
|
|
214
|
-
3. Syncs commands, skills, hooks, and MCP servers to each version
|
|
215
|
-
|
|
216
|
-
Non-interactive alternative:
|
|
217
|
-
Skip 'setup' and run:
|
|
218
|
-
agents pull
|
|
219
|
-
`)
|
|
220
|
-
.action(async (options) => {
|
|
213
|
+
Non-interactive alternative: agents pull
|
|
214
|
+
`,
|
|
215
|
+
});
|
|
216
|
+
setupCmd.action(async (options) => {
|
|
221
217
|
try {
|
|
222
218
|
await runSetup(program, options);
|
|
223
219
|
}
|
package/dist/commands/teams.js
CHANGED
|
@@ -6,6 +6,7 @@ import { resolveProvider } from '../lib/cloud/registry.js';
|
|
|
6
6
|
import { runSupervisor } from '../lib/teams/supervisor.js';
|
|
7
7
|
import { handleSpawn, handleStatus, handleStop, handleTasks, } from '../lib/teams/api.js';
|
|
8
8
|
import { createTeam, ensureTeam, getTeam, loadTeams, removeTeam, teamExists, } from '../lib/teams/registry.js';
|
|
9
|
+
import { setHelpSections } from '../lib/help.js';
|
|
9
10
|
import { createWorktree, isGitRepo, hasUncommittedChanges, removeWorktree, } from '../lib/teams/worktree.js';
|
|
10
11
|
import { isVersionInstalled, resolveVersionAlias, resolveVersionAliasLoose } from '../lib/versions.js';
|
|
11
12
|
import { discoverSessions, parseTimeFilter, resolveSessionById } from '../lib/session/discover.js';
|
|
@@ -513,53 +514,43 @@ async function pickTeamOr(mgr, command) {
|
|
|
513
514
|
export function registerTeamsCommands(program) {
|
|
514
515
|
const teams = program
|
|
515
516
|
.command('teams')
|
|
516
|
-
.description('Organize AI coding agents into teams that
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
create
|
|
517
|
+
.description('Organize AI coding agents into teams that work in parallel on a shared task.');
|
|
518
|
+
setHelpSections(teams, {
|
|
519
|
+
examples: `
|
|
520
|
+
# Create a team for a coordinated task
|
|
521
|
+
agents teams create pricing-page
|
|
521
522
|
|
|
522
|
-
|
|
523
|
+
# Add a teammate — name them so you can refer to them later
|
|
524
|
+
agents teams add pricing-page claude "Rewrite /v2/pricing endpoint" --name backend
|
|
523
525
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
agents teams create pricing-page
|
|
526
|
+
# Parallel work — frontend stubs API while backend lands
|
|
527
|
+
agents teams add pricing-page codex "Build /pricing route with three-tier layout" --name frontend
|
|
527
528
|
|
|
528
|
-
|
|
529
|
-
|
|
529
|
+
# DAG dependency — QA waits for backend AND frontend to finish
|
|
530
|
+
agents teams add pricing-page claude "Run Playwright suite, fix flakes" --name qa --after backend,frontend
|
|
530
531
|
|
|
531
|
-
|
|
532
|
-
|
|
532
|
+
# Start everyone (respects --after dependencies) and watch live
|
|
533
|
+
agents teams start pricing-page --watch
|
|
533
534
|
|
|
534
|
-
|
|
535
|
-
|
|
535
|
+
# Delta-poll status without rereading everything
|
|
536
|
+
agents teams status pricing-page --since 2026-04-24T09:00:00-07:00
|
|
536
537
|
|
|
537
|
-
|
|
538
|
-
|
|
538
|
+
# Wind everyone down when shipped
|
|
539
|
+
agents teams disband pricing-page
|
|
540
|
+
`,
|
|
541
|
+
notes: `
|
|
542
|
+
A team is a named group of agents working in the background on a shared task.
|
|
543
|
+
Teammate sessions show in 'agents sessions --teams' tagged [team/name · mode].
|
|
539
544
|
|
|
540
|
-
|
|
541
|
-
|
|
545
|
+
Teammate syntax:
|
|
546
|
+
'claude' the default Claude version on this machine
|
|
547
|
+
'claude@2.1.112' a specific installed version (see 'agents view')
|
|
542
548
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
agents teams remove pricing-page frontend
|
|
549
|
-
|
|
550
|
-
# Ship done — wind everyone down
|
|
551
|
-
agents teams disband pricing-page
|
|
552
|
-
|
|
553
|
-
Short aliases:
|
|
554
|
-
teams c = create teams a = add teams s = status
|
|
555
|
-
teams rm = remove teams d = disband teams ls = list
|
|
556
|
-
|
|
557
|
-
Teammate syntax (same as the rest of agents-cli):
|
|
558
|
-
'claude' -> the default Claude version on this machine
|
|
559
|
-
'claude@2.1.112' -> a specific installed version (see 'agents view')
|
|
560
|
-
|
|
561
|
-
Name teammates with --name alice to refer to them as 'alice' instead of a UUID.
|
|
562
|
-
`);
|
|
549
|
+
Short aliases:
|
|
550
|
+
teams c = create teams a = add teams s = status
|
|
551
|
+
teams rm = remove teams d = disband teams ls = list
|
|
552
|
+
`,
|
|
553
|
+
});
|
|
563
554
|
// list
|
|
564
555
|
teams
|
|
565
556
|
.command('list [query]')
|