@nemus-cli/nemus 0.9.0 → 0.11.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 +32 -0
- package/README.md +23 -5
- package/bin/workspace.js +12 -0
- package/dist/commands/analyze-deps.js +5 -12
- package/dist/commands/archive.js +13 -18
- package/dist/commands/branch/create.js +5 -12
- package/dist/commands/branch/switch.js +14 -25
- package/dist/commands/cache/manager.js +13 -24
- package/dist/commands/cleanup.js +14 -26
- package/dist/commands/configure-claude.js +4 -8
- package/dist/commands/configure.js +38 -32
- package/dist/commands/dashboard/session-picker.js +19 -26
- package/dist/commands/dashboard/workspace-picker.js +19 -26
- package/dist/commands/delete.js +15 -30
- package/dist/commands/ghq-status.js +7 -12
- package/dist/commands/go.js +18 -27
- package/dist/commands/history.js +6 -13
- package/dist/commands/list.js +20 -29
- package/dist/commands/prune.js +196 -0
- package/dist/commands/remove-repo.js +21 -29
- package/dist/commands/save-context.js +5 -10
- package/dist/commands/sessions.js +19 -25
- package/dist/commands/suite/create.js +27 -53
- package/dist/commands/suite/delete.js +13 -25
- package/dist/commands/suite/export.js +20 -36
- package/dist/commands/suite/import.js +9 -20
- package/dist/commands/suite/use.js +9 -17
- package/dist/program.js +2 -0
- package/dist/utils/prompt.js +26 -0
- package/dist/utils/prompts.js +86 -118
- package/dist/utils/prune.js +70 -0
- package/package.json +3 -6
- package/scripts/release-notes.mjs +54 -0
- package/skills/config.md +17 -0
- package/skills/nemus/SKILL.md +7 -2
- package/skills/nemus/references/completion.md +22 -0
- package/skills/nemus/references/config.md +32 -0
- package/skills/nemus/references/prune.md +44 -0
- package/skills/nemus/references/reflect.md +43 -0
- package/skills/nemus/references/save-context.md +25 -0
- package/skills/prune-workspaces.md +23 -0
- package/skills/reflect.md +21 -0
- package/src/commands/analyze-deps.ts +5 -9
- package/src/commands/archive.ts +5 -7
- package/src/commands/branch/create.ts +5 -9
- package/src/commands/branch/switch.ts +14 -22
- package/src/commands/cache/manager.ts +13 -21
- package/src/commands/cleanup.ts +14 -23
- package/src/commands/configure-claude.ts +4 -5
- package/src/commands/configure.ts +35 -29
- package/src/commands/dashboard/session-picker.ts +6 -11
- package/src/commands/dashboard/workspace-picker.ts +6 -11
- package/src/commands/delete.test.ts +36 -42
- package/src/commands/delete.ts +15 -27
- package/src/commands/ghq-status.ts +5 -7
- package/src/commands/go.ts +18 -25
- package/src/commands/history.ts +6 -10
- package/src/commands/list.test.ts +19 -26
- package/src/commands/list.ts +24 -31
- package/src/commands/prune.ts +183 -0
- package/src/commands/remove-repo.ts +11 -17
- package/src/commands/save-context.ts +3 -5
- package/src/commands/sessions.ts +6 -10
- package/src/commands/suite/create.ts +28 -50
- package/src/commands/suite/delete.ts +14 -23
- package/src/commands/suite/export.ts +20 -33
- package/src/commands/suite/import.ts +9 -17
- package/src/commands/suite/use.ts +9 -14
- package/src/program.ts +2 -0
- package/src/utils/prompt.ts +16 -0
- package/src/utils/prompts.test.ts +70 -41
- package/src/utils/prompts.ts +98 -128
- package/src/utils/prune.test.ts +121 -0
- package/src/utils/prune.ts +109 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: prune-workspaces
|
|
3
|
+
description: Bulk-delete workspaces with no recent activity, safe by default (protects uncommitted/unpushed work)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Preview first — never delete without showing the user the plan:
|
|
7
|
+
```bash
|
|
8
|
+
nemus prune --days 30 --dry-run
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Then prune after confirming with the user:
|
|
12
|
+
```bash
|
|
13
|
+
nemus prune --days 30 # prompts (default: No)
|
|
14
|
+
nemus prune --days 30 --yes # non-interactive — only when the user is sure
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- **Stale** = no agent session (or, failing that, no `createdAt`) in the last N
|
|
18
|
+
days (`--days`, default 30). Undatable workspaces are never selected.
|
|
19
|
+
- **Safe by default:** workspaces with uncommitted or unpushed changes are
|
|
20
|
+
**protected** and listed with the reason — not deleted. `--include-dirty`
|
|
21
|
+
overrides this (only with explicit user consent to lose that work).
|
|
22
|
+
- `--json` and `--dry-run` never delete.
|
|
23
|
+
- Deletion is permanent — repos must be re-cloned. Always confirm first.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reflect
|
|
3
|
+
description: Retrospective on recent agent sessions — get concrete tips to improve skills, context, and prompts
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Analyze recent workspaces' agent sessions and get setup improvement tips (read-only; changes no repos):
|
|
7
|
+
```bash
|
|
8
|
+
nemus reflect # most recent workspaces (default 10)
|
|
9
|
+
nemus reflect --workspace <name> # a single workspace
|
|
10
|
+
nemus reflect --markdown > reflection.md # shareable report
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Review saved reports (saved under `~/.nemus/reflect/` unless `--no-save`):
|
|
14
|
+
```bash
|
|
15
|
+
nemus reflect history # list past reports
|
|
16
|
+
nemus reflect show [id] # show one (defaults to latest)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- Uses *your own* configured agent (claude/pi/opencode) as the judge — no API key of Nemus's.
|
|
20
|
+
- `--json` / `--markdown` for machine or shareable output; `--group-by kind|priority`.
|
|
21
|
+
- Safe: it reads transcripts and prints advice, nothing is modified.
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { logError, logInfo, logStep, logSuccess } from '../utils/logger';
|
|
12
12
|
import { outputJson, outputJsonError } from '../utils/output';
|
|
13
13
|
import { colorize } from '../utils/colors';
|
|
14
|
-
import
|
|
14
|
+
import { confirm } from '../utils/prompt';
|
|
15
15
|
import { resolveWorkspace } from '../utils/command-helpers';
|
|
16
16
|
|
|
17
17
|
const displayDependencyAnalysis = (analyses: Map<string, any>) => {
|
|
@@ -122,14 +122,10 @@ async function handleAnalyzeDeps(workspaceArg?: string, opts: { json?: boolean }
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
if (process.stdout.isTTY) {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
message: 'Save dependency analysis to workspace metadata?',
|
|
130
|
-
default: true,
|
|
131
|
-
},
|
|
132
|
-
]);
|
|
125
|
+
const saveToMetadata = await confirm({
|
|
126
|
+
message: 'Save dependency analysis to workspace metadata?',
|
|
127
|
+
default: true,
|
|
128
|
+
});
|
|
133
129
|
|
|
134
130
|
if (saveToMetadata) {
|
|
135
131
|
const updatedMetadata = updateWorkspaceMetadata(metadata, analyses);
|
package/src/commands/archive.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { listWorkspaces, archiveWorkspace, unarchiveWorkspace } from '../utils/w
|
|
|
3
3
|
import { promptMultiWorkspaceSelection } from '../utils/prompts';
|
|
4
4
|
import { logInfo, logSuccess, logError } from '../utils/logger';
|
|
5
5
|
import { colorize } from '../utils/colors';
|
|
6
|
-
import
|
|
6
|
+
import { confirm } from '../utils/prompt';
|
|
7
7
|
import { getGlobalOpts, parseList } from '../utils/command-helpers';
|
|
8
8
|
|
|
9
9
|
export function registerArchiveCommand(parent: Command) {
|
|
@@ -50,13 +50,12 @@ async function handleArchive(opts: {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if (!opts.yes) {
|
|
53
|
-
const
|
|
54
|
-
type: 'confirm', name: 'confirmed',
|
|
53
|
+
const confirmed = await confirm({
|
|
55
54
|
message: selectedNames.length === 1
|
|
56
55
|
? `Unarchive workspace ${selectedNames[0]}?`
|
|
57
56
|
: `Unarchive these ${selectedNames.length} workspaces?`,
|
|
58
57
|
default: true,
|
|
59
|
-
}
|
|
58
|
+
});
|
|
60
59
|
if (!confirmed) return;
|
|
61
60
|
}
|
|
62
61
|
|
|
@@ -86,13 +85,12 @@ async function handleArchive(opts: {
|
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
if (!opts.yes) {
|
|
89
|
-
const
|
|
90
|
-
type: 'confirm', name: 'confirmed',
|
|
88
|
+
const confirmed = await confirm({
|
|
91
89
|
message: selectedNames.length === 1
|
|
92
90
|
? `Archive workspace ${selectedNames[0]}? It will be auto-deleted in 30 days.`
|
|
93
91
|
: `Archive these ${selectedNames.length} workspaces? They will be auto-deleted in 30 days.`,
|
|
94
92
|
default: true,
|
|
95
|
-
}
|
|
93
|
+
});
|
|
96
94
|
if (!confirmed) return;
|
|
97
95
|
}
|
|
98
96
|
|
|
@@ -6,7 +6,7 @@ import { createBranch } from '../../utils/branch-operations';
|
|
|
6
6
|
import { logError, logInfo, logStep, logSuccess, logWarning } from '../../utils/logger';
|
|
7
7
|
import { colorize } from '../../utils/colors';
|
|
8
8
|
import { WORKSPACES_DIR } from '../../utils/config';
|
|
9
|
-
import
|
|
9
|
+
import { input } from '../../utils/prompt';
|
|
10
10
|
|
|
11
11
|
export interface BranchCreateOpts {
|
|
12
12
|
workspace?: string;
|
|
@@ -40,14 +40,10 @@ export const main = async (opts?: BranchCreateOpts) => {
|
|
|
40
40
|
logError('Usage: w branch create --workspace <name> --branch <branch>');
|
|
41
41
|
process.exit(1);
|
|
42
42
|
}
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
message: 'New branch name:',
|
|
48
|
-
validate: (input: string) => input.trim() ? true : 'Branch name cannot be empty',
|
|
49
|
-
},
|
|
50
|
-
]);
|
|
43
|
+
const branch = await input({
|
|
44
|
+
message: 'New branch name:',
|
|
45
|
+
validate: (input: string) => input.trim() ? true : 'Branch name cannot be empty',
|
|
46
|
+
});
|
|
51
47
|
branchName = branch;
|
|
52
48
|
}
|
|
53
49
|
|
|
@@ -7,7 +7,7 @@ import { promptWorkspaceSelection } from '../../utils/prompts';
|
|
|
7
7
|
import { logInfo, logSuccess, logError, logWarning } from '../../utils/logger';
|
|
8
8
|
import { colorize } from '../../utils/colors';
|
|
9
9
|
import { switchBranch, BranchSwitchResult } from '../../utils/branch-operations';
|
|
10
|
-
import
|
|
10
|
+
import { confirm, input } from '../../utils/prompt';
|
|
11
11
|
|
|
12
12
|
export interface BranchSwitchOpts {
|
|
13
13
|
workspace?: string;
|
|
@@ -61,20 +61,16 @@ export async function main(opts?: BranchSwitchOpts) {
|
|
|
61
61
|
logError('Usage: w branch switch --workspace <name> --branch <branch>');
|
|
62
62
|
process.exit(1);
|
|
63
63
|
}
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return 'Branch name cannot be empty';
|
|
73
|
-
}
|
|
74
|
-
return true;
|
|
75
|
-
},
|
|
64
|
+
const branch = await input({
|
|
65
|
+
message: 'Target branch name:',
|
|
66
|
+
default: 'main',
|
|
67
|
+
validate: (input: string) => {
|
|
68
|
+
if (!input || input.trim().length === 0) {
|
|
69
|
+
return 'Branch name cannot be empty';
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
76
72
|
},
|
|
77
|
-
|
|
73
|
+
});
|
|
78
74
|
targetBranch = branch;
|
|
79
75
|
}
|
|
80
76
|
|
|
@@ -82,14 +78,10 @@ export async function main(opts?: BranchSwitchOpts) {
|
|
|
82
78
|
|
|
83
79
|
// Skip confirmation when --yes flag is provided
|
|
84
80
|
if (!yes && process.stdout.isTTY) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
message: 'Proceed with bulk branch switch?',
|
|
90
|
-
default: true,
|
|
91
|
-
},
|
|
92
|
-
]);
|
|
81
|
+
const confirmed = await confirm({
|
|
82
|
+
message: 'Proceed with bulk branch switch?',
|
|
83
|
+
default: true,
|
|
84
|
+
});
|
|
93
85
|
|
|
94
86
|
if (!confirmed) {
|
|
95
87
|
logInfo('Branch switch cancelled');
|
|
@@ -4,7 +4,7 @@ import { clearCache, getCacheStats } from '../../utils/cache';
|
|
|
4
4
|
import { fetchOrgRepos, verifyGhAuth, displayAuthInstructions } from '../../utils/github';
|
|
5
5
|
import { logInfo, logSuccess, logError } from '../../utils/logger';
|
|
6
6
|
import { colorize } from '../../utils/colors';
|
|
7
|
-
import
|
|
7
|
+
import { confirm, select } from '../../utils/prompt';
|
|
8
8
|
import * as fuzzy from 'fuzzy';
|
|
9
9
|
|
|
10
10
|
export async function cacheInfo() {
|
|
@@ -123,32 +123,24 @@ export async function main() {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
// Interactive mode (original behavior)
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
name: '
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
{ name: 'Clear cache', value: 'clear' },
|
|
135
|
-
],
|
|
136
|
-
},
|
|
137
|
-
]);
|
|
126
|
+
const selectedAction = await select({
|
|
127
|
+
message: 'Select action:',
|
|
128
|
+
choices: [
|
|
129
|
+
{ name: 'View cache info', value: 'info' },
|
|
130
|
+
{ name: 'Refresh cache (force fetch from GitHub)', value: 'refresh' },
|
|
131
|
+
{ name: 'Clear cache', value: 'clear' },
|
|
132
|
+
],
|
|
133
|
+
});
|
|
138
134
|
|
|
139
135
|
if (selectedAction === 'info') {
|
|
140
136
|
await cacheInfo();
|
|
141
137
|
} else if (selectedAction === 'refresh') {
|
|
142
138
|
await cacheRefresh();
|
|
143
139
|
} else if (selectedAction === 'clear') {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
message: 'Are you sure you want to clear the cache?',
|
|
149
|
-
default: false,
|
|
150
|
-
},
|
|
151
|
-
]);
|
|
140
|
+
const confirmed = await confirm({
|
|
141
|
+
message: 'Are you sure you want to clear the cache?',
|
|
142
|
+
default: false,
|
|
143
|
+
});
|
|
152
144
|
|
|
153
145
|
if (confirmed) {
|
|
154
146
|
await cacheClear();
|
package/src/commands/cleanup.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { loadMetadata } from '../utils/workspace-meta';
|
|
|
5
5
|
import { removeNodeModules, removeBuildArtifacts, gitClean } from '../utils/cleanup-operations';
|
|
6
6
|
import { logError, logInfo, logStep, logSuccess } from '../utils/logger';
|
|
7
7
|
import { colorize } from '../utils/colors';
|
|
8
|
-
import
|
|
8
|
+
import { checkbox, confirm } from '../utils/prompt';
|
|
9
9
|
import { getGlobalOpts, resolveWorkspace } from '../utils/command-helpers';
|
|
10
10
|
|
|
11
11
|
export function registerCleanupCommand(parent: Command) {
|
|
@@ -54,19 +54,14 @@ async function handleCleanup(workspaceArg: string | undefined, opts: {
|
|
|
54
54
|
if (build) operations.push('build');
|
|
55
55
|
if (gitCleanFlag) operations.push('git_clean');
|
|
56
56
|
} else {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
name: '
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{ name: 'Git clean (remove untracked files)', value: 'git_clean' },
|
|
66
|
-
],
|
|
67
|
-
},
|
|
68
|
-
]);
|
|
69
|
-
operations = result.operations;
|
|
57
|
+
operations = await checkbox({
|
|
58
|
+
message: 'Select cleanup operations:',
|
|
59
|
+
choices: [
|
|
60
|
+
{ name: 'Remove node_modules (all repos)', value: 'node_modules' },
|
|
61
|
+
{ name: 'Remove build artifacts (dist, build, .next, coverage)', value: 'build' },
|
|
62
|
+
{ name: 'Git clean (remove untracked files)', value: 'git_clean' },
|
|
63
|
+
],
|
|
64
|
+
});
|
|
70
65
|
}
|
|
71
66
|
|
|
72
67
|
if (operations.length === 0) {
|
|
@@ -75,16 +70,12 @@ async function handleCleanup(workspaceArg: string | undefined, opts: {
|
|
|
75
70
|
}
|
|
76
71
|
|
|
77
72
|
if (!opts.yes) {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
message: `Proceed with cleanup? This cannot be undone.`,
|
|
83
|
-
default: false,
|
|
84
|
-
},
|
|
85
|
-
]);
|
|
73
|
+
const confirmed = await confirm({
|
|
74
|
+
message: `Proceed with cleanup? This cannot be undone.`,
|
|
75
|
+
default: false,
|
|
76
|
+
});
|
|
86
77
|
|
|
87
|
-
if (!
|
|
78
|
+
if (!confirmed) {
|
|
88
79
|
logInfo('Cleanup cancelled');
|
|
89
80
|
return;
|
|
90
81
|
}
|
|
@@ -2,7 +2,7 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { loadClaudeConfig, saveClaudeConfig } from '../utils/claude-integration';
|
|
3
3
|
import { logSuccess, logError } from '../utils/logger';
|
|
4
4
|
import { colorize } from '../utils/colors';
|
|
5
|
-
import
|
|
5
|
+
import { confirm } from '../utils/prompt';
|
|
6
6
|
|
|
7
7
|
export function registerConfigureClaudeCommand(parent: Command) {
|
|
8
8
|
parent
|
|
@@ -27,10 +27,9 @@ async function handleConfigureClaude() {
|
|
|
27
27
|
console.log(` Generate context: ${currentConfig.generateContext ? colorize('Enabled', 'green') : colorize('Disabled', 'red')}`);
|
|
28
28
|
console.log('');
|
|
29
29
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
]);
|
|
30
|
+
const autoLaunch = await confirm({ message: 'Auto-launch Claude Code after workspace creation?', default: currentConfig.autoLaunch });
|
|
31
|
+
const generateContext = await confirm({ message: 'Generate CLAUDE.md context file in workspaces?', default: currentConfig.generateContext });
|
|
32
|
+
const answers = { autoLaunch, generateContext };
|
|
34
33
|
|
|
35
34
|
await saveClaudeConfig(answers);
|
|
36
35
|
|
|
@@ -2,7 +2,7 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { execFileSync } from 'child_process';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import * as path from 'path';
|
|
5
|
-
import
|
|
5
|
+
import { input, confirm, select } from '../utils/prompt';
|
|
6
6
|
import { getUserConfig, saveUserConfig, UserConfig } from '../utils/config';
|
|
7
7
|
import { clearCache } from '../utils/cache';
|
|
8
8
|
import { logSuccess, logError, logInfo, logWarning } from '../utils/logger';
|
|
@@ -39,40 +39,46 @@ async function handleConfigure() {
|
|
|
39
39
|
console.log('');
|
|
40
40
|
|
|
41
41
|
try {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
42
|
+
// Sequential modular prompts. The classic `when:` conditions become `if`
|
|
43
|
+
// guards; a skipped question leaves its answer key undefined, exactly as the
|
|
44
|
+
// classic API did (downstream code already tolerates that via `??`).
|
|
45
|
+
const answers: any = {};
|
|
46
|
+
answers.workspacesDir = await input({ message: 'Workspaces directory:', default: current.workspacesDir, validate: (val: string) => val.trim().length > 0 || 'Directory path is required' });
|
|
47
|
+
answers.githubOrg = await input({ message: 'GitHub organization:', default: current.githubOrg, validate: (val: string) => /^[a-zA-Z0-9_-]+$/.test(val.trim()) || 'Must be a valid GitHub org name' });
|
|
48
|
+
answers.cloneProtocol = await select({ message: 'Clone protocol:', choices: [{ name: 'SSH (git@github.com:...)', value: 'ssh' }, { name: 'HTTPS (https://github.com/...)', value: 'https' }], default: current.cloneProtocol });
|
|
49
|
+
answers.autoLaunchClaude = await confirm({ message: 'Auto-launch AI agent after workspace creation?', default: current.autoLaunchClaude });
|
|
50
|
+
answers.generateClaudeContext = await confirm({ message: 'Generate context file in workspaces?', default: current.generateClaudeContext });
|
|
51
|
+
answers.installMcp = await confirm({ message: 'Install MCP server (Claude Code only)?', default: current.installMcp });
|
|
52
|
+
answers.aiAgent = await select<string>({ message: 'AI Agent(s) to integrate with:', choices: [
|
|
53
|
+
{ name: 'Auto-detect (recommended)', value: 'auto' },
|
|
54
|
+
{ name: 'Claude Code only', value: 'claude' },
|
|
55
|
+
{ name: 'Pi only', value: 'pi' },
|
|
56
|
+
{ name: 'OpenCode only', value: 'opencode' },
|
|
57
|
+
{ name: 'All available', value: 'both' },
|
|
58
|
+
], default: current.aiAgent });
|
|
59
|
+
// Only ask about primary agent when aiAgent is 'both' or 'auto'
|
|
60
|
+
// (when specific agent chosen, primary is implicitly that agent)
|
|
61
|
+
if (answers.aiAgent === 'both' || answers.aiAgent === 'auto') {
|
|
62
|
+
answers.primaryAgent = await select<string>({ message: 'Primary agent (used for launching):', choices: [
|
|
59
63
|
{ name: 'Auto-detect (first available)', value: 'auto' },
|
|
60
64
|
{ name: 'Claude Code', value: 'claude' },
|
|
61
65
|
{ name: 'Pi', value: 'pi' },
|
|
62
66
|
{ name: 'OpenCode', value: 'opencode' },
|
|
63
|
-
], default: current.primaryAgent
|
|
64
|
-
|
|
67
|
+
], default: current.primaryAgent });
|
|
68
|
+
}
|
|
69
|
+
if (answers.aiAgent === 'pi' || answers.aiAgent === 'both' || answers.aiAgent === 'auto') {
|
|
70
|
+
answers.piWorkspaceInputStatus = await confirm({
|
|
65
71
|
message: 'Show workspace status widget in Pi input area (branch, PRs, CI)?',
|
|
66
|
-
default: current.piWorkspaceInputStatus !== false
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
default: current.piWorkspaceInputStatus !== false });
|
|
73
|
+
}
|
|
74
|
+
if (answers.aiAgent === 'claude' || answers.aiAgent === 'both' || answers.aiAgent === 'auto') {
|
|
75
|
+
answers.claudeWorkspaceStatusLine = await confirm({
|
|
69
76
|
message: 'Add workspace repo table to Claude Code status line?',
|
|
70
|
-
default: current.claudeWorkspaceStatusLine !== false
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
]);
|
|
77
|
+
default: current.claudeWorkspaceStatusLine !== false });
|
|
78
|
+
}
|
|
79
|
+
answers.autoReportBugs = await confirm({
|
|
80
|
+
message: 'Auto-file a GitHub issue when a command crashes? (deduped, sanitized)',
|
|
81
|
+
default: current.autoReportBugs === true });
|
|
76
82
|
|
|
77
83
|
// Validate and normalize config
|
|
78
84
|
let primaryAgent = answers.primaryAgent || 'auto';
|
|
@@ -9,12 +9,9 @@ import { getWorkspaceSessions, WorkspaceSession } from '../../utils/claude-sessi
|
|
|
9
9
|
import { launchAgentPane } from './launcher';
|
|
10
10
|
import { getAgentPaths, getPrimaryAgent, ConcreteAgentType } from '../../utils/agent-config';
|
|
11
11
|
import { colorize } from '../../utils/colors';
|
|
12
|
-
import
|
|
13
|
-
import autocompletePrompt from 'inquirer-autocomplete-prompt';
|
|
12
|
+
import { search } from '../../utils/prompt';
|
|
14
13
|
import * as fuzzy from 'fuzzy';
|
|
15
14
|
|
|
16
|
-
inquirer.registerPrompt('autocomplete', autocompletePrompt);
|
|
17
|
-
|
|
18
15
|
async function main() {
|
|
19
16
|
try {
|
|
20
17
|
const sessions = await getWorkspaceSessions();
|
|
@@ -30,12 +27,11 @@ async function main() {
|
|
|
30
27
|
timeLabel: session.lastActiveLabel,
|
|
31
28
|
}));
|
|
32
29
|
|
|
33
|
-
const
|
|
34
|
-
type: 'autocomplete',
|
|
35
|
-
name: 'selected',
|
|
30
|
+
const selected = await search<typeof items[number]>({
|
|
36
31
|
message: 'Select session to resume:',
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
pageSize: 15,
|
|
33
|
+
source: async (term: string | undefined) => {
|
|
34
|
+
const searchInput = term || '';
|
|
39
35
|
const source = items.map(item => ({
|
|
40
36
|
name: `${item.displayName} ${colorize(item.timeLabel, 'dim')}`,
|
|
41
37
|
value: item,
|
|
@@ -47,8 +43,7 @@ async function main() {
|
|
|
47
43
|
value: result.original,
|
|
48
44
|
}));
|
|
49
45
|
},
|
|
50
|
-
|
|
51
|
-
} as any]);
|
|
46
|
+
});
|
|
52
47
|
|
|
53
48
|
const item = selected as { session: WorkspaceSession };
|
|
54
49
|
const session = item.session;
|
|
@@ -8,12 +8,9 @@
|
|
|
8
8
|
import { listWorkspaces } from '../../utils/workspace-meta';
|
|
9
9
|
import { launchAgentPane } from './launcher';
|
|
10
10
|
import { getPrimaryAgent } from '../../utils/agent-config';
|
|
11
|
-
import
|
|
12
|
-
import autocompletePrompt from 'inquirer-autocomplete-prompt';
|
|
11
|
+
import { search } from '../../utils/prompt';
|
|
13
12
|
import * as fuzzy from 'fuzzy';
|
|
14
13
|
|
|
15
|
-
inquirer.registerPrompt('autocomplete', autocompletePrompt);
|
|
16
|
-
|
|
17
14
|
async function main() {
|
|
18
15
|
try {
|
|
19
16
|
const workspaces = await listWorkspaces();
|
|
@@ -29,12 +26,11 @@ async function main() {
|
|
|
29
26
|
repoCount: ws.metadata?.repositories?.length ?? 0,
|
|
30
27
|
}));
|
|
31
28
|
|
|
32
|
-
const
|
|
33
|
-
type: 'autocomplete',
|
|
34
|
-
name: 'selected',
|
|
29
|
+
const selected = await search<typeof items[number]>({
|
|
35
30
|
message: 'Select workspace to launch agent in:',
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
pageSize: 15,
|
|
32
|
+
source: async (term: string | undefined) => {
|
|
33
|
+
const searchInput = term || '';
|
|
38
34
|
const source = items.map(item => ({
|
|
39
35
|
name: `${item.name} (${item.repoCount} repos)`,
|
|
40
36
|
value: item,
|
|
@@ -46,8 +42,7 @@ async function main() {
|
|
|
46
42
|
value: result.original,
|
|
47
43
|
}));
|
|
48
44
|
},
|
|
49
|
-
|
|
50
|
-
} as any]);
|
|
45
|
+
});
|
|
51
46
|
|
|
52
47
|
const workspace = selected as { name: string; path: string };
|
|
53
48
|
const agent = getPrimaryAgent();
|