@nemus-cli/nemus 0.2.1
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 +86 -0
- package/LICENSE +21 -0
- package/README.md +275 -0
- package/assets/README.md +53 -0
- package/assets/banner.png +0 -0
- package/assets/banner.svg +66 -0
- package/assets/favicon-32.png +0 -0
- package/assets/favicon-64.png +0 -0
- package/assets/icon-256.png +0 -0
- package/assets/icon.svg +23 -0
- package/assets/logo-256.png +0 -0
- package/assets/logo-512.png +0 -0
- package/assets/logo-wordmark.svg +35 -0
- package/assets/logo.svg +32 -0
- package/bin/workspace.js +130 -0
- package/dist/cli/ai-prompt.js +421 -0
- package/dist/cli/dashboard/AgentList.js +61 -0
- package/dist/cli/dashboard/DashboardSidebar.js +280 -0
- package/dist/cli/dashboard/HelpFooter.js +73 -0
- package/dist/cli/dashboard/StatusBadge.js +50 -0
- package/dist/cli/dashboard/index.js +11 -0
- package/dist/cli/dashboard/types.js +2 -0
- package/dist/cli/tui.js +48 -0
- package/dist/commands/ai-prompt.js +22 -0
- package/dist/commands/analyze-deps.js +138 -0
- package/dist/commands/archive.js +113 -0
- package/dist/commands/branch/create.js +119 -0
- package/dist/commands/branch/index.js +104 -0
- package/dist/commands/branch/merge.js +90 -0
- package/dist/commands/branch/rebase.js +84 -0
- package/dist/commands/branch/switch.js +165 -0
- package/dist/commands/cache/index.js +80 -0
- package/dist/commands/cache/manager.js +198 -0
- package/dist/commands/cleanup.js +153 -0
- package/dist/commands/configure-claude.js +55 -0
- package/dist/commands/configure.js +231 -0
- package/dist/commands/create.js +204 -0
- package/dist/commands/dashboard/hook-handler.js +162 -0
- package/dist/commands/dashboard/index.js +258 -0
- package/dist/commands/dashboard/launcher.js +40 -0
- package/dist/commands/dashboard/session-picker.js +106 -0
- package/dist/commands/dashboard/sidebar.js +39 -0
- package/dist/commands/dashboard/workspace-picker.js +95 -0
- package/dist/commands/delete.js +194 -0
- package/dist/commands/deprecated-aliases.js +44 -0
- package/dist/commands/diff.js +129 -0
- package/dist/commands/doctor.js +141 -0
- package/dist/commands/generate-docs.js +77 -0
- package/dist/commands/ghq-status.js +72 -0
- package/dist/commands/go.js +154 -0
- package/dist/commands/history.js +124 -0
- package/dist/commands/list.js +191 -0
- package/dist/commands/mcp/index.js +69 -0
- package/dist/commands/migrate.js +296 -0
- package/dist/commands/remove-repo.js +217 -0
- package/dist/commands/report-bug.js +112 -0
- package/dist/commands/run.js +147 -0
- package/dist/commands/save-context.js +171 -0
- package/dist/commands/sessions.js +129 -0
- package/dist/commands/status.js +138 -0
- package/dist/commands/suite/create.js +212 -0
- package/dist/commands/suite/delete.js +64 -0
- package/dist/commands/suite/export.js +126 -0
- package/dist/commands/suite/import.js +128 -0
- package/dist/commands/suite/index.js +94 -0
- package/dist/commands/suite/list.js +49 -0
- package/dist/commands/suite/use.js +227 -0
- package/dist/commands/sync.js +117 -0
- package/dist/commands/update.js +203 -0
- package/dist/mcp/install.js +550 -0
- package/dist/mcp/server.js +398 -0
- package/dist/mcp/tools.js +922 -0
- package/dist/pi-extensions/permission-sync.ts.template +41 -0
- package/dist/pi-extensions/permissions-gate.ts.template +69 -0
- package/dist/pi-extensions/pr-fix-trigger.ts.template +124 -0
- package/dist/pi-extensions/review-reminder.ts.template +58 -0
- package/dist/pi-extensions/workspace-input-status.ts.template +919 -0
- package/dist/program.js +136 -0
- package/dist/scripts/workspace-table.py +394 -0
- package/dist/types/dashboard.js +11 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/agent-config.js +263 -0
- package/dist/utils/agent-state.js +178 -0
- package/dist/utils/banner.js +24 -0
- package/dist/utils/branch-operations.js +232 -0
- package/dist/utils/bug-report.js +355 -0
- package/dist/utils/cache.js +168 -0
- package/dist/utils/claude-integration.js +617 -0
- package/dist/utils/claude-sessions.js +260 -0
- package/dist/utils/cleanup-operations.js +120 -0
- package/dist/utils/colors.js +26 -0
- package/dist/utils/command-helpers.js +44 -0
- package/dist/utils/config.js +150 -0
- package/dist/utils/context-file.js +33 -0
- package/dist/utils/dashboard-hooks.js +172 -0
- package/dist/utils/dependency-analyzer.js +234 -0
- package/dist/utils/diff-operations.js +80 -0
- package/dist/utils/doc-generator.js +184 -0
- package/dist/utils/ghq-integration.js +332 -0
- package/dist/utils/git-operations.js +237 -0
- package/dist/utils/git-status.js +187 -0
- package/dist/utils/github.js +68 -0
- package/dist/utils/health-checks.js +345 -0
- package/dist/utils/history.js +150 -0
- package/dist/utils/hooks.js +100 -0
- package/dist/utils/logger.js +40 -0
- package/dist/utils/permission-sync.js +681 -0
- package/dist/utils/pi-extensions.js +224 -0
- package/dist/utils/progress.js +92 -0
- package/dist/utils/prompts.js +279 -0
- package/dist/utils/repo-resolver.js +260 -0
- package/dist/utils/retry.js +65 -0
- package/dist/utils/run-operations.js +30 -0
- package/dist/utils/suite.js +159 -0
- package/dist/utils/sync-operations.js +107 -0
- package/dist/utils/tmux-dashboard.js +184 -0
- package/dist/utils/validation.js +153 -0
- package/dist/utils/version-check.js +121 -0
- package/dist/utils/workspace-meta.js +185 -0
- package/install-shell-integration.sh +532 -0
- package/install.sh +401 -0
- package/package.json +90 -0
- package/remove-shell-block.awk +44 -0
- package/scripts/postinstall.js +85 -0
- package/skills/analyze-deps.md +23 -0
- package/skills/archive-workspace.md +26 -0
- package/skills/branch-create.md +18 -0
- package/skills/create-workspace.md +39 -0
- package/skills/delete-workspace.md +37 -0
- package/skills/list-org-repos.md +26 -0
- package/skills/list-suites.md +24 -0
- package/skills/list-workspaces.md +27 -0
- package/skills/refresh-workspace-docs.md +89 -0
- package/skills/remove-repo.md +25 -0
- package/skills/run-command.md +23 -0
- package/skills/save-context.md +68 -0
- package/skills/search-repos.md +31 -0
- package/skills/snapshot-list.md +18 -0
- package/skills/snapshot-save.md +12 -0
- package/skills/switch-branch.md +18 -0
- package/skills/update-cache.md +21 -0
- package/skills/update-workspace.md +66 -0
- package/skills/workspace-cleanup.md +18 -0
- package/skills/workspace-diff.md +23 -0
- package/skills/workspace-doctor.md +23 -0
- package/skills/workspace-info.md +45 -0
- package/skills/workspace-manager/SKILL.md +201 -0
- package/skills/workspace-manager/references/ai-prompt.md +44 -0
- package/skills/workspace-manager/references/analyze-deps.md +45 -0
- package/skills/workspace-manager/references/archive-workspace.md +38 -0
- package/skills/workspace-manager/references/branch-create.md +31 -0
- package/skills/workspace-manager/references/branch-merge.md +22 -0
- package/skills/workspace-manager/references/branch-rebase.md +22 -0
- package/skills/workspace-manager/references/cache-clear.md +18 -0
- package/skills/workspace-manager/references/cache-info.md +22 -0
- package/skills/workspace-manager/references/configure-claude.md +31 -0
- package/skills/workspace-manager/references/configure.md +35 -0
- package/skills/workspace-manager/references/create-workspace.md +45 -0
- package/skills/workspace-manager/references/dashboard.md +61 -0
- package/skills/workspace-manager/references/delete-workspace.md +33 -0
- package/skills/workspace-manager/references/generate-docs.md +36 -0
- package/skills/workspace-manager/references/ghq-status.md +28 -0
- package/skills/workspace-manager/references/go.md +33 -0
- package/skills/workspace-manager/references/history.md +41 -0
- package/skills/workspace-manager/references/list-org-repos.md +26 -0
- package/skills/workspace-manager/references/list-suites.md +21 -0
- package/skills/workspace-manager/references/list-workspaces.md +27 -0
- package/skills/workspace-manager/references/mcp.md +49 -0
- package/skills/workspace-manager/references/remove-repo.md +26 -0
- package/skills/workspace-manager/references/run-command.md +44 -0
- package/skills/workspace-manager/references/search-repos.md +24 -0
- package/skills/workspace-manager/references/sessions.md +27 -0
- package/skills/workspace-manager/references/suite-create.md +22 -0
- package/skills/workspace-manager/references/suite-delete.md +21 -0
- package/skills/workspace-manager/references/suite-export.md +19 -0
- package/skills/workspace-manager/references/suite-import.md +19 -0
- package/skills/workspace-manager/references/suite-use.md +27 -0
- package/skills/workspace-manager/references/switch-branch.md +25 -0
- package/skills/workspace-manager/references/update-cache.md +22 -0
- package/skills/workspace-manager/references/update-workspace.md +50 -0
- package/skills/workspace-manager/references/workspace-cleanup.md +33 -0
- package/skills/workspace-manager/references/workspace-diff.md +27 -0
- package/skills/workspace-manager/references/workspace-doctor.md +27 -0
- package/skills/workspace-manager/references/workspace-info.md +33 -0
- package/skills/workspace-manager/references/workspace-status.md +43 -0
- package/skills/workspace-manager/references/workspace-sync.md +26 -0
- package/skills/workspace-status.md +26 -0
- package/skills/workspace-sync.md +23 -0
- package/src/cli/ai-prompt.test.ts +667 -0
- package/src/cli/ai-prompt.ts +421 -0
- package/src/cli/dashboard/AgentList.tsx +44 -0
- package/src/cli/dashboard/DashboardSidebar.tsx +291 -0
- package/src/cli/dashboard/HelpFooter.tsx +22 -0
- package/src/cli/dashboard/StatusBadge.tsx +23 -0
- package/src/cli/dashboard/index.ts +5 -0
- package/src/cli/dashboard/types.ts +16 -0
- package/src/cli/tui.tsx +51 -0
- package/src/cli/workspace-cli.test.ts +30 -0
- package/src/commands/ai-prompt.ts +21 -0
- package/src/commands/analyze-deps.ts +119 -0
- package/src/commands/archive.ts +114 -0
- package/src/commands/branch/create.ts +94 -0
- package/src/commands/branch/index.ts +74 -0
- package/src/commands/branch/merge.ts +61 -0
- package/src/commands/branch/rebase.ts +54 -0
- package/src/commands/branch/switch.ts +150 -0
- package/src/commands/cache/index.ts +51 -0
- package/src/commands/cache/manager.ts +168 -0
- package/src/commands/cleanup.ts +132 -0
- package/src/commands/configure-claude.ts +55 -0
- package/src/commands/configure.ts +204 -0
- package/src/commands/create.ts +196 -0
- package/src/commands/dashboard/hook-handler.ts +138 -0
- package/src/commands/dashboard/index.ts +248 -0
- package/src/commands/dashboard/launcher.ts +42 -0
- package/src/commands/dashboard/session-picker.ts +73 -0
- package/src/commands/dashboard/sidebar.js +39 -0
- package/src/commands/dashboard/workspace-picker.ts +62 -0
- package/src/commands/delete.test.ts +250 -0
- package/src/commands/delete.ts +171 -0
- package/src/commands/deprecated-aliases.ts +55 -0
- package/src/commands/diff.ts +106 -0
- package/src/commands/doctor.ts +110 -0
- package/src/commands/generate-docs.ts +45 -0
- package/src/commands/ghq-status.ts +70 -0
- package/src/commands/go.ts +125 -0
- package/src/commands/history.ts +136 -0
- package/src/commands/list.test.ts +219 -0
- package/src/commands/list.ts +176 -0
- package/src/commands/mcp/index.ts +39 -0
- package/src/commands/migrate.ts +277 -0
- package/src/commands/remove-repo.ts +194 -0
- package/src/commands/report-bug.ts +88 -0
- package/src/commands/run.ts +125 -0
- package/src/commands/save-context.test.ts +113 -0
- package/src/commands/save-context.ts +141 -0
- package/src/commands/sessions.ts +99 -0
- package/src/commands/status.ts +111 -0
- package/src/commands/suite/create.ts +240 -0
- package/src/commands/suite/delete.ts +65 -0
- package/src/commands/suite/export.ts +97 -0
- package/src/commands/suite/import.ts +100 -0
- package/src/commands/suite/index.ts +66 -0
- package/src/commands/suite/list.ts +54 -0
- package/src/commands/suite/use.ts +232 -0
- package/src/commands/sync.ts +97 -0
- package/src/commands/update.ts +197 -0
- package/src/mcp/install.ts +529 -0
- package/src/mcp/server.ts +579 -0
- package/src/mcp/tools.test.ts +545 -0
- package/src/mcp/tools.ts +1019 -0
- package/src/mcp/update-workspace.test.ts +220 -0
- package/src/pi-extensions/permission-sync.ts.template +41 -0
- package/src/pi-extensions/permissions-gate.ts.template +69 -0
- package/src/pi-extensions/pr-fix-trigger.ts.template +124 -0
- package/src/pi-extensions/review-reminder.ts.template +58 -0
- package/src/pi-extensions/workspace-input-status.ts.template +919 -0
- package/src/program.ts +112 -0
- package/src/scripts/workspace-table.py +394 -0
- package/src/types/dashboard.ts +29 -0
- package/src/types/index.ts +109 -0
- package/src/types/ink.d.ts +171 -0
- package/src/utils/agent-config.test.ts +303 -0
- package/src/utils/agent-config.ts +264 -0
- package/src/utils/agent-state.test.ts +166 -0
- package/src/utils/agent-state.ts +135 -0
- package/src/utils/banner.ts +24 -0
- package/src/utils/branch-operations.ts +237 -0
- package/src/utils/bug-report.test.ts +174 -0
- package/src/utils/bug-report.ts +355 -0
- package/src/utils/cache.ts +150 -0
- package/src/utils/claude-integration.test.ts +381 -0
- package/src/utils/claude-integration.ts +649 -0
- package/src/utils/claude-sessions.test.ts +262 -0
- package/src/utils/claude-sessions.ts +251 -0
- package/src/utils/cleanup-operations.ts +94 -0
- package/src/utils/colors.ts +25 -0
- package/src/utils/command-helpers.ts +46 -0
- package/src/utils/config.test.ts +203 -0
- package/src/utils/config.ts +133 -0
- package/src/utils/context-file.ts +36 -0
- package/src/utils/dashboard-hooks.test.ts +168 -0
- package/src/utils/dashboard-hooks.ts +163 -0
- package/src/utils/dependency-analyzer.ts +243 -0
- package/src/utils/diff-operations.ts +59 -0
- package/src/utils/doc-generator.ts +187 -0
- package/src/utils/ghq-integration.test.ts +195 -0
- package/src/utils/ghq-integration.ts +317 -0
- package/src/utils/git-operations.test.ts +265 -0
- package/src/utils/git-operations.ts +233 -0
- package/src/utils/git-status.ts +171 -0
- package/src/utils/github.ts +74 -0
- package/src/utils/health-checks.ts +359 -0
- package/src/utils/history.ts +140 -0
- package/src/utils/hooks.ts +92 -0
- package/src/utils/logger.ts +37 -0
- package/src/utils/permission-sync.test.ts +593 -0
- package/src/utils/permission-sync.ts +720 -0
- package/src/utils/pi-extensions.test.ts +182 -0
- package/src/utils/pi-extensions.ts +226 -0
- package/src/utils/progress.ts +73 -0
- package/src/utils/prompts.test.ts +169 -0
- package/src/utils/prompts.ts +296 -0
- package/src/utils/repo-resolver.test.ts +313 -0
- package/src/utils/repo-resolver.ts +294 -0
- package/src/utils/retry.test.ts +124 -0
- package/src/utils/retry.ts +85 -0
- package/src/utils/run-operations.ts +38 -0
- package/src/utils/suite.test.ts +256 -0
- package/src/utils/suite.ts +144 -0
- package/src/utils/sync-operations.ts +87 -0
- package/src/utils/tmux-dashboard.ts +193 -0
- package/src/utils/validation.test.ts +139 -0
- package/src/utils/validation.ts +128 -0
- package/src/utils/version-check.test.ts +108 -0
- package/src/utils/version-check.ts +96 -0
- package/src/utils/workspace-meta.ts +173 -0
- package/sync-permissions.sh +137 -0
- package/tsconfig.json +20 -0
- package/uninstall.sh +162 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
import { clearCache, getCacheStats } from '../../utils/cache';
|
|
4
|
+
import { fetchOrgRepos, verifyGhAuth, displayAuthInstructions } from '../../utils/github';
|
|
5
|
+
import { logInfo, logSuccess, logError } from '../../utils/logger';
|
|
6
|
+
import { colorize } from '../../utils/colors';
|
|
7
|
+
import inquirer from 'inquirer';
|
|
8
|
+
import * as fuzzy from 'fuzzy';
|
|
9
|
+
|
|
10
|
+
export async function cacheInfo() {
|
|
11
|
+
const stats = await getCacheStats();
|
|
12
|
+
|
|
13
|
+
if (stats.exists) {
|
|
14
|
+
console.log('\n' + colorize('Cache Information:', 'cyan'));
|
|
15
|
+
console.log(` Status: ${colorize('Active', 'green')}`);
|
|
16
|
+
console.log(` Repositories: ${colorize(String(stats.repoCount), 'cyan')}`);
|
|
17
|
+
console.log(` Last updated: ${stats.age}`);
|
|
18
|
+
console.log(` Cache size: ${colorize(String(Math.round((stats.size || 0) / 1024)) + ' KB', 'yellow')}`);
|
|
19
|
+
console.log(` Location: ${colorize('~/.workspace-manager-cache/repos-cache.json', 'gray')}`);
|
|
20
|
+
} else {
|
|
21
|
+
console.log('\n' + colorize('Cache Status:', 'yellow'));
|
|
22
|
+
console.log(' No cache found. Cache will be created on next repository fetch.\n');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function cacheRefresh() {
|
|
27
|
+
const isAuthenticated = await verifyGhAuth();
|
|
28
|
+
if (!isAuthenticated) {
|
|
29
|
+
logError('GitHub CLI is not authenticated');
|
|
30
|
+
displayAuthInstructions();
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
logInfo('Forcing cache refresh...');
|
|
35
|
+
const repos = await fetchOrgRepos({ forceRefresh: true });
|
|
36
|
+
logSuccess(`Cache refreshed with ${colorize(String(repos.length), 'cyan')} repositories`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function cacheClear() {
|
|
40
|
+
await clearCache();
|
|
41
|
+
logSuccess('Cache cleared successfully');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function cacheSearch(query: string, limit: number = 20) {
|
|
45
|
+
if (!query || query.trim().length === 0) {
|
|
46
|
+
logError('Usage: w cache search <query>');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const allRepos = await fetchOrgRepos();
|
|
51
|
+
const results = fuzzy.filter(query, allRepos, {
|
|
52
|
+
extract: (repo: typeof allRepos[0]) => `${repo.name} ${repo.description || ''}`,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const matches = results.slice(0, limit);
|
|
56
|
+
|
|
57
|
+
if (matches.length === 0) {
|
|
58
|
+
logInfo(`No repositories matching '${query}'`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log('\n' + colorize(`Search results for "${query}" (${matches.length} matches):`, 'cyan') + '\n');
|
|
63
|
+
for (const match of matches) {
|
|
64
|
+
const repo = match.original;
|
|
65
|
+
const visibility = repo.isPrivate ? colorize('private', 'yellow') : colorize('public', 'green');
|
|
66
|
+
console.log(` ${colorize(repo.name, 'bright')} [${visibility}]`);
|
|
67
|
+
if (repo.description) {
|
|
68
|
+
console.log(` ${colorize(repo.description, 'gray')}`);
|
|
69
|
+
}
|
|
70
|
+
console.log(` ${colorize(repo.url, 'gray')}`);
|
|
71
|
+
}
|
|
72
|
+
console.log('');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function cacheList(forceRefresh: boolean = false) {
|
|
76
|
+
const isAuthenticated = await verifyGhAuth();
|
|
77
|
+
if (!isAuthenticated) {
|
|
78
|
+
logError('GitHub CLI is not authenticated');
|
|
79
|
+
displayAuthInstructions();
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (forceRefresh) {
|
|
84
|
+
logInfo('Forcing cache refresh...');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const repos = await fetchOrgRepos({ forceRefresh });
|
|
88
|
+
|
|
89
|
+
if (repos.length === 0) {
|
|
90
|
+
logInfo('No repositories found');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.log('\n' + colorize(`Organization repositories (${repos.length} total):`, 'cyan') + '\n');
|
|
95
|
+
for (const repo of repos) {
|
|
96
|
+
const visibility = repo.isPrivate ? colorize('private', 'yellow') : colorize('public', 'green');
|
|
97
|
+
console.log(` ${colorize(repo.name, 'bright')} [${visibility}]`);
|
|
98
|
+
if (repo.description) {
|
|
99
|
+
console.log(` ${colorize(repo.description, 'gray')}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
console.log('');
|
|
103
|
+
logInfo(`Showing ${repos.length} repositories. Use 'w cache search <query>' to filter.`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function main() {
|
|
107
|
+
console.log('\n' + '='.repeat(60));
|
|
108
|
+
console.log(colorize('Cache Manager', 'bright'));
|
|
109
|
+
console.log('='.repeat(60) + '\n');
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
// Support direct subcommand invocation (e.g. from cache-router)
|
|
113
|
+
const action = process.argv[2];
|
|
114
|
+
if (action === 'info' || action === 'refresh' || action === 'clear') {
|
|
115
|
+
if (action === 'info') {
|
|
116
|
+
await cacheInfo();
|
|
117
|
+
} else if (action === 'refresh') {
|
|
118
|
+
await cacheRefresh();
|
|
119
|
+
} else if (action === 'clear') {
|
|
120
|
+
await cacheClear();
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Interactive mode (original behavior)
|
|
126
|
+
const { selectedAction } = await inquirer.prompt([
|
|
127
|
+
{
|
|
128
|
+
type: 'list',
|
|
129
|
+
name: 'selectedAction',
|
|
130
|
+
message: 'Select action:',
|
|
131
|
+
choices: [
|
|
132
|
+
{ name: 'View cache info', value: 'info' },
|
|
133
|
+
{ name: 'Refresh cache (force fetch from GitHub)', value: 'refresh' },
|
|
134
|
+
{ name: 'Clear cache', value: 'clear' },
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
]);
|
|
138
|
+
|
|
139
|
+
if (selectedAction === 'info') {
|
|
140
|
+
await cacheInfo();
|
|
141
|
+
} else if (selectedAction === 'refresh') {
|
|
142
|
+
await cacheRefresh();
|
|
143
|
+
} else if (selectedAction === 'clear') {
|
|
144
|
+
const { confirmed } = await inquirer.prompt([
|
|
145
|
+
{
|
|
146
|
+
type: 'confirm',
|
|
147
|
+
name: 'confirmed',
|
|
148
|
+
message: 'Are you sure you want to clear the cache?',
|
|
149
|
+
default: false,
|
|
150
|
+
},
|
|
151
|
+
]);
|
|
152
|
+
|
|
153
|
+
if (confirmed) {
|
|
154
|
+
await cacheClear();
|
|
155
|
+
} else {
|
|
156
|
+
logInfo('Cache clear cancelled');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
} catch (error) {
|
|
160
|
+
logError('Failed to manage cache');
|
|
161
|
+
if (error instanceof Error) {
|
|
162
|
+
logError(error.message);
|
|
163
|
+
}
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (require.main === module) main();
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { WORKSPACES_DIR } from '../utils/config';
|
|
4
|
+
import { loadMetadata } from '../utils/workspace-meta';
|
|
5
|
+
import { removeNodeModules, removeBuildArtifacts, gitClean } from '../utils/cleanup-operations';
|
|
6
|
+
import { logError, logInfo, logStep, logSuccess } from '../utils/logger';
|
|
7
|
+
import { colorize } from '../utils/colors';
|
|
8
|
+
import inquirer from 'inquirer';
|
|
9
|
+
import { getGlobalOpts, resolveWorkspace } from '../utils/command-helpers';
|
|
10
|
+
|
|
11
|
+
export function registerCleanupCommand(parent: Command) {
|
|
12
|
+
parent
|
|
13
|
+
.command('cleanup')
|
|
14
|
+
.alias('cl')
|
|
15
|
+
.description('Remove node_modules and build artifacts')
|
|
16
|
+
.argument('[workspace]', 'Workspace name')
|
|
17
|
+
.option('--all', 'Clean everything')
|
|
18
|
+
.option('--node-modules', 'Clean node_modules')
|
|
19
|
+
.option('--build', 'Clean build artifacts')
|
|
20
|
+
.option('--git-clean', 'Git clean (remove untracked files)')
|
|
21
|
+
.action(async (workspace, opts, cmd) => {
|
|
22
|
+
const globalOpts = getGlobalOpts(cmd);
|
|
23
|
+
await handleCleanup(workspace, { ...opts, ...globalOpts });
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function handleCleanup(workspaceArg: string | undefined, opts: {
|
|
28
|
+
all?: boolean;
|
|
29
|
+
nodeModules?: boolean;
|
|
30
|
+
build?: boolean;
|
|
31
|
+
gitClean?: boolean;
|
|
32
|
+
yes: boolean;
|
|
33
|
+
forceRefresh: boolean;
|
|
34
|
+
}) {
|
|
35
|
+
try {
|
|
36
|
+
const workspaceName = await resolveWorkspace(workspaceArg);
|
|
37
|
+
const workspacePath = path.join(WORKSPACES_DIR, workspaceName);
|
|
38
|
+
const metadata = await loadMetadata(workspacePath);
|
|
39
|
+
|
|
40
|
+
if (!metadata) {
|
|
41
|
+
logError(`Workspace not found: ${workspaceName}`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const nodeModules = opts.nodeModules || opts.all;
|
|
46
|
+
const build = opts.build || opts.all;
|
|
47
|
+
const gitCleanFlag = opts.gitClean || opts.all;
|
|
48
|
+
|
|
49
|
+
let operations: string[];
|
|
50
|
+
|
|
51
|
+
if (nodeModules || build || gitCleanFlag) {
|
|
52
|
+
operations = [];
|
|
53
|
+
if (nodeModules) operations.push('node_modules');
|
|
54
|
+
if (build) operations.push('build');
|
|
55
|
+
if (gitCleanFlag) operations.push('git_clean');
|
|
56
|
+
} else {
|
|
57
|
+
const result = await inquirer.prompt([
|
|
58
|
+
{
|
|
59
|
+
type: 'checkbox',
|
|
60
|
+
name: 'operations',
|
|
61
|
+
message: 'Select cleanup operations:',
|
|
62
|
+
choices: [
|
|
63
|
+
{ name: 'Remove node_modules (all repos)', value: 'node_modules' },
|
|
64
|
+
{ name: 'Remove build artifacts (dist, build, .next, coverage)', value: 'build' },
|
|
65
|
+
{ name: 'Git clean (remove untracked files)', value: 'git_clean' },
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
operations = result.operations;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (operations.length === 0) {
|
|
73
|
+
logInfo('No operations selected');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!opts.yes) {
|
|
78
|
+
const { confirm } = await inquirer.prompt([
|
|
79
|
+
{
|
|
80
|
+
type: 'confirm',
|
|
81
|
+
name: 'confirm',
|
|
82
|
+
message: `Proceed with cleanup? This cannot be undone.`,
|
|
83
|
+
default: false,
|
|
84
|
+
},
|
|
85
|
+
]);
|
|
86
|
+
|
|
87
|
+
if (!confirm) {
|
|
88
|
+
logInfo('Cleanup cancelled');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
logStep('Running cleanup operations...');
|
|
94
|
+
|
|
95
|
+
for (const repo of metadata.repositories) {
|
|
96
|
+
const repoPath = path.join(workspacePath, repo.directoryName);
|
|
97
|
+
const displayName = repo.directoryName !== repo.name
|
|
98
|
+
? `${repo.directoryName} (${repo.name})`
|
|
99
|
+
: repo.name;
|
|
100
|
+
console.log(`\n${colorize(displayName, 'cyan')}:`);
|
|
101
|
+
|
|
102
|
+
if (operations.includes('node_modules')) {
|
|
103
|
+
const result = await removeNodeModules(repoPath);
|
|
104
|
+
if (result.success) {
|
|
105
|
+
logSuccess(` Removed node_modules (${result.spaceFreed})`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (operations.includes('build')) {
|
|
110
|
+
const result = await removeBuildArtifacts(repoPath);
|
|
111
|
+
if (result.success && result.filesRemoved > 0) {
|
|
112
|
+
logSuccess(` Removed ${result.filesRemoved} build artifacts (${result.spaceFreed})`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (operations.includes('git_clean')) {
|
|
117
|
+
const result = await gitClean(repoPath, false);
|
|
118
|
+
if (result.success && result.filesRemoved > 0) {
|
|
119
|
+
logSuccess(` Git clean: removed ${result.filesRemoved} files`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
logSuccess('\nCleanup completed!');
|
|
125
|
+
} catch (error) {
|
|
126
|
+
logError('Cleanup failed');
|
|
127
|
+
if (error instanceof Error) {
|
|
128
|
+
logError(error.message);
|
|
129
|
+
}
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { loadClaudeConfig, saveClaudeConfig } from '../utils/claude-integration';
|
|
3
|
+
import { logSuccess, logError } from '../utils/logger';
|
|
4
|
+
import { colorize } from '../utils/colors';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
|
|
7
|
+
export function registerConfigureClaudeCommand(parent: Command) {
|
|
8
|
+
parent
|
|
9
|
+
.command('configure-claude')
|
|
10
|
+
.alias('cc')
|
|
11
|
+
.description('Configure Claude Code integration')
|
|
12
|
+
.action(async () => {
|
|
13
|
+
await handleConfigureClaude();
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function handleConfigureClaude() {
|
|
18
|
+
console.log('\n' + '='.repeat(60));
|
|
19
|
+
console.log(colorize('Configure Claude Code Integration', 'bright'));
|
|
20
|
+
console.log('='.repeat(60) + '\n');
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const currentConfig = await loadClaudeConfig();
|
|
24
|
+
|
|
25
|
+
console.log('Current settings:');
|
|
26
|
+
console.log(` Auto-launch Claude: ${currentConfig.autoLaunch ? colorize('Enabled', 'green') : colorize('Disabled', 'red')}`);
|
|
27
|
+
console.log(` Generate context: ${currentConfig.generateContext ? colorize('Enabled', 'green') : colorize('Disabled', 'red')}`);
|
|
28
|
+
console.log('');
|
|
29
|
+
|
|
30
|
+
const answers = await inquirer.prompt([
|
|
31
|
+
{ type: 'confirm', name: 'autoLaunch', message: 'Auto-launch Claude Code after workspace creation?', default: currentConfig.autoLaunch },
|
|
32
|
+
{ type: 'confirm', name: 'generateContext', message: 'Generate CLAUDE.md context file in workspaces?', default: currentConfig.generateContext },
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
await saveClaudeConfig(answers);
|
|
36
|
+
|
|
37
|
+
console.log('');
|
|
38
|
+
logSuccess('Claude Code integration configured!');
|
|
39
|
+
console.log('');
|
|
40
|
+
console.log('Settings:');
|
|
41
|
+
console.log(` ${colorize('✓', 'green')} Auto-launch: ${answers.autoLaunch ? 'Enabled' : 'Disabled'}`);
|
|
42
|
+
console.log(` ${colorize('✓', 'green')} Generate context: ${answers.generateContext ? 'Enabled' : 'Disabled'}`);
|
|
43
|
+
|
|
44
|
+
if (answers.autoLaunch) {
|
|
45
|
+
console.log('');
|
|
46
|
+
console.log(colorize('Note:', 'yellow') + ' Claude Code will automatically launch when you create workspaces.');
|
|
47
|
+
console.log('Make sure Claude Code CLI is installed: https://claude.ai/download');
|
|
48
|
+
}
|
|
49
|
+
console.log('');
|
|
50
|
+
} catch (error) {
|
|
51
|
+
logError('Failed to configure Claude integration');
|
|
52
|
+
if (error instanceof Error) { logError(error.message); }
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { getUserConfig, saveUserConfig, UserConfig } from '../utils/config';
|
|
7
|
+
import { clearCache } from '../utils/cache';
|
|
8
|
+
import { logSuccess, logError, logInfo, logWarning } from '../utils/logger';
|
|
9
|
+
import { colorize } from '../utils/colors';
|
|
10
|
+
|
|
11
|
+
export function registerConfigureCommand(parent: Command) {
|
|
12
|
+
parent
|
|
13
|
+
.command('configure')
|
|
14
|
+
.alias('cfg')
|
|
15
|
+
.description('Configure workspace manager settings')
|
|
16
|
+
.action(async () => {
|
|
17
|
+
await handleConfigure();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function handleConfigure() {
|
|
22
|
+
console.log('\n' + '='.repeat(60));
|
|
23
|
+
console.log(colorize('Workspace Manager Configuration', 'bright'));
|
|
24
|
+
console.log('='.repeat(60) + '\n');
|
|
25
|
+
|
|
26
|
+
const current = getUserConfig();
|
|
27
|
+
|
|
28
|
+
console.log('Current settings:');
|
|
29
|
+
console.log(` Workspaces directory: ${colorize(current.workspacesDir, 'cyan')}`);
|
|
30
|
+
console.log(` GitHub organization: ${colorize(current.githubOrg, 'cyan')}`);
|
|
31
|
+
console.log(` Clone protocol: ${colorize(current.cloneProtocol, 'cyan')}`);
|
|
32
|
+
console.log(` Auto-launch agent: ${current.autoLaunchClaude ? colorize('Enabled', 'green') : colorize('Disabled', 'red')}`);
|
|
33
|
+
console.log(` Generate context file: ${current.generateClaudeContext ? colorize('Enabled', 'green') : colorize('Disabled', 'red')}`);
|
|
34
|
+
console.log(` MCP server: ${current.installMcp ? colorize('Enabled', 'green') : colorize('Disabled', 'red')}`);
|
|
35
|
+
console.log(` AI Agent: ${colorize(current.aiAgent, 'cyan')}`);
|
|
36
|
+
console.log(` Primary agent: ${colorize(current.primaryAgent, 'cyan')}`);
|
|
37
|
+
console.log(` Pi workspace widget: ${current.piWorkspaceInputStatus !== false ? colorize('Enabled', 'green') : colorize('Disabled', 'red')}`);
|
|
38
|
+
console.log(` Claude workspace table: ${current.claudeWorkspaceStatusLine !== false ? colorize('Enabled', 'green') : colorize('Disabled', 'red')}`);
|
|
39
|
+
console.log('');
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const answers = await inquirer.prompt([
|
|
43
|
+
{ type: 'input', name: 'workspacesDir', message: 'Workspaces directory:', default: current.workspacesDir, validate: (val: string) => val.trim().length > 0 || 'Directory path is required' },
|
|
44
|
+
{ type: 'input', name: 'githubOrg', message: 'GitHub organization:', default: current.githubOrg, validate: (val: string) => /^[a-zA-Z0-9_-]+$/.test(val.trim()) || 'Must be a valid GitHub org name' },
|
|
45
|
+
{ type: 'list', name: 'cloneProtocol', message: 'Clone protocol:', choices: [{ name: 'SSH (git@github.com:...)', value: 'ssh' }, { name: 'HTTPS (https://github.com/...)', value: 'https' }], default: current.cloneProtocol },
|
|
46
|
+
{ type: 'confirm', name: 'autoLaunchClaude', message: 'Auto-launch AI agent after workspace creation?', default: current.autoLaunchClaude },
|
|
47
|
+
{ type: 'confirm', name: 'generateClaudeContext', message: 'Generate context file in workspaces?', default: current.generateClaudeContext },
|
|
48
|
+
{ type: 'confirm', name: 'installMcp', message: 'Install MCP server (Claude Code only)?', default: current.installMcp },
|
|
49
|
+
{ type: 'list', name: 'aiAgent', message: 'AI Agent(s) to integrate with:', choices: [
|
|
50
|
+
{ name: 'Auto-detect (recommended)', value: 'auto' },
|
|
51
|
+
{ name: 'Claude Code only', value: 'claude' },
|
|
52
|
+
{ name: 'Pi only', value: 'pi' },
|
|
53
|
+
{ name: 'OpenCode only', value: 'opencode' },
|
|
54
|
+
{ name: 'All available', value: 'both' },
|
|
55
|
+
], default: current.aiAgent },
|
|
56
|
+
// Only ask about primary agent when aiAgent is 'both' or 'auto'
|
|
57
|
+
// (when specific agent chosen, primary is implicitly that agent)
|
|
58
|
+
{ type: 'list', name: 'primaryAgent', message: 'Primary agent (used for launching):', choices: [
|
|
59
|
+
{ name: 'Auto-detect (first available)', value: 'auto' },
|
|
60
|
+
{ name: 'Claude Code', value: 'claude' },
|
|
61
|
+
{ name: 'Pi', value: 'pi' },
|
|
62
|
+
{ name: 'OpenCode', value: 'opencode' },
|
|
63
|
+
], default: current.primaryAgent, when: (ans) => ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
|
|
64
|
+
{ type: 'confirm', name: 'piWorkspaceInputStatus',
|
|
65
|
+
message: 'Show workspace status widget in Pi input area (branch, PRs, CI)?',
|
|
66
|
+
default: current.piWorkspaceInputStatus !== false,
|
|
67
|
+
when: (ans) => ans.aiAgent === 'pi' || ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
|
|
68
|
+
{ type: 'confirm', name: 'claudeWorkspaceStatusLine',
|
|
69
|
+
message: 'Add workspace repo table to Claude Code status line?',
|
|
70
|
+
default: current.claudeWorkspaceStatusLine !== false,
|
|
71
|
+
when: (ans) => ans.aiAgent === 'claude' || ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
|
|
72
|
+
{ type: 'confirm', name: 'autoReportBugs',
|
|
73
|
+
message: 'Auto-file a GitHub issue when a command crashes? (deduped, sanitized)',
|
|
74
|
+
default: current.autoReportBugs === true },
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
// Validate and normalize config
|
|
78
|
+
let primaryAgent = answers.primaryAgent || 'auto';
|
|
79
|
+
// If aiAgent is specific, primaryAgent must match
|
|
80
|
+
if (answers.aiAgent === 'claude') primaryAgent = 'claude';
|
|
81
|
+
if (answers.aiAgent === 'pi') primaryAgent = 'pi';
|
|
82
|
+
if (answers.aiAgent === 'opencode') primaryAgent = 'opencode';
|
|
83
|
+
|
|
84
|
+
const newConfig: UserConfig = {
|
|
85
|
+
workspacesDir: answers.workspacesDir.trim(),
|
|
86
|
+
githubOrg: answers.githubOrg.trim(),
|
|
87
|
+
cloneProtocol: answers.cloneProtocol,
|
|
88
|
+
autoLaunchClaude: answers.autoLaunchClaude,
|
|
89
|
+
generateClaudeContext: answers.generateClaudeContext,
|
|
90
|
+
installMcp: answers.installMcp,
|
|
91
|
+
aiAgent: answers.aiAgent,
|
|
92
|
+
primaryAgent,
|
|
93
|
+
piWorkspaceInputStatus: answers.piWorkspaceInputStatus ?? current.piWorkspaceInputStatus ?? true,
|
|
94
|
+
claudeWorkspaceStatusLine: answers.claudeWorkspaceStatusLine ?? current.claudeWorkspaceStatusLine ?? true,
|
|
95
|
+
autoReportBugs: answers.autoReportBugs ?? current.autoReportBugs ?? false,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
saveUserConfig(newConfig);
|
|
99
|
+
|
|
100
|
+
console.log('');
|
|
101
|
+
logSuccess('Configuration saved!');
|
|
102
|
+
console.log('');
|
|
103
|
+
console.log(` ${colorize('Workspaces directory:', 'gray')} ${newConfig.workspacesDir}`);
|
|
104
|
+
console.log(` ${colorize('GitHub organization:', 'gray')} ${newConfig.githubOrg}`);
|
|
105
|
+
console.log(` ${colorize('Clone protocol:', 'gray')} ${newConfig.cloneProtocol}`);
|
|
106
|
+
console.log(` ${colorize('Auto-launch agent:', 'gray')} ${newConfig.autoLaunchClaude ? 'Yes' : 'No'}`);
|
|
107
|
+
console.log(` ${colorize('Generate context:', 'gray')} ${newConfig.generateClaudeContext ? 'Yes' : 'No'}`);
|
|
108
|
+
console.log(` ${colorize('MCP server:', 'gray')} ${newConfig.installMcp ? 'Yes' : 'No'}`);
|
|
109
|
+
console.log(` ${colorize('AI Agent:', 'gray')} ${newConfig.aiAgent}`);
|
|
110
|
+
console.log(` ${colorize('Primary agent:', 'gray')} ${newConfig.primaryAgent}`);
|
|
111
|
+
console.log('');
|
|
112
|
+
|
|
113
|
+
// Install / upgrade shell integration.
|
|
114
|
+
// Skip if MCP install just ran it (mcp/install always installs shell integration).
|
|
115
|
+
let mcpInstalled = false;
|
|
116
|
+
if (newConfig.installMcp && !current.installMcp) {
|
|
117
|
+
logInfo('Installing MCP server...');
|
|
118
|
+
try {
|
|
119
|
+
const mcpInstallScript = path.join(__dirname, '..', '..', 'dist', 'mcp', 'install.js');
|
|
120
|
+
execSync(`node "${mcpInstallScript}" install`, { stdio: 'inherit' });
|
|
121
|
+
mcpInstalled = true;
|
|
122
|
+
} catch { logError('MCP install failed. You can retry later with: w mcp install'); }
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (newConfig.githubOrg !== current.githubOrg) {
|
|
126
|
+
await clearCache();
|
|
127
|
+
logInfo(`GitHub org changed from "${current.githubOrg}" to "${newConfig.githubOrg}". Repo cache has been cleared.`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Always install / upgrade the shell integration so the 'w' function
|
|
131
|
+
// is available. This is especially important on first-time setup where
|
|
132
|
+
// postinstall may not have run or the user hasn't sourced their RC file.
|
|
133
|
+
// Skip if mcp install already did it to avoid printing the reminder twice.
|
|
134
|
+
if (!mcpInstalled) {
|
|
135
|
+
installShellIntegration();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
} catch (error) {
|
|
139
|
+
logError('Failed to save configuration');
|
|
140
|
+
if (error instanceof Error) { logError(error.message); }
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Install or upgrade the shell integration (w/workspace shell functions).
|
|
147
|
+
* Uses an absolute path derived from this file so it works regardless of CWD.
|
|
148
|
+
* Always prints a prominent "source your RC file" reminder afterwards.
|
|
149
|
+
*/
|
|
150
|
+
function installShellIntegration(): void {
|
|
151
|
+
// __dirname is dist/commands/ at runtime — script is two levels up at package root
|
|
152
|
+
const scriptPath = path.join(__dirname, '..', '..', 'install-shell-integration.sh');
|
|
153
|
+
|
|
154
|
+
if (!fs.existsSync(scriptPath)) {
|
|
155
|
+
logWarning('Shell integration script not found — skipping auto-install');
|
|
156
|
+
printSourceReminder();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const shell = process.env.SHELL || '';
|
|
161
|
+
const shellType = shell.endsWith('/zsh') ? 'zsh'
|
|
162
|
+
: shell.endsWith('/bash') ? 'bash'
|
|
163
|
+
: '';
|
|
164
|
+
|
|
165
|
+
if (!shellType) {
|
|
166
|
+
logWarning('Unknown shell — skipping shell integration (run install-shell-integration.sh manually)');
|
|
167
|
+
printSourceReminder();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
execSync(`bash "${scriptPath}" ${shellType}`, { stdio: 'inherit' });
|
|
173
|
+
} catch {
|
|
174
|
+
logWarning('Shell integration install failed — you can run it manually:');
|
|
175
|
+
logInfo(` bash "${scriptPath}" ${shellType}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
printSourceReminder();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Print a loud, impossible-to-miss reminder to source the RC file.
|
|
183
|
+
* Without this step the 'w' shell function is not available in the
|
|
184
|
+
* current terminal session even after a successful install.
|
|
185
|
+
*/
|
|
186
|
+
function printSourceReminder(): void {
|
|
187
|
+
const shell = process.env.SHELL || '';
|
|
188
|
+
const rcFile = shell.endsWith('/zsh') ? '~/.zshrc'
|
|
189
|
+
: shell.endsWith('/bash') ? '~/.bashrc'
|
|
190
|
+
: '~/.profile';
|
|
191
|
+
|
|
192
|
+
console.log('');
|
|
193
|
+
console.log(colorize(' ⚠️ IMPORTANT — activate the shell function in this session:', 'yellow'));
|
|
194
|
+
console.log('');
|
|
195
|
+
console.log(` ${colorize(`source ${rcFile}`, 'cyan')}`);
|
|
196
|
+
console.log('');
|
|
197
|
+
console.log(` Or open a new terminal tab. Until then the ${colorize('nemus', 'cyan')}/${colorize('nem', 'cyan')} shell`);
|
|
198
|
+
console.log(` functions (which auto-cd into new workspaces) aren't active yet.`);
|
|
199
|
+
console.log('');
|
|
200
|
+
console.log(` Tip: ${colorize('nemus', 'cyan')} works immediately without sourcing:`);
|
|
201
|
+
console.log(` ${colorize('nemus configure', 'cyan')} ${colorize('# first-time setup', 'gray')}`);
|
|
202
|
+
console.log(` ${colorize('nemus list', 'cyan')} ${colorize('# list workspaces', 'gray')}`);
|
|
203
|
+
console.log('');
|
|
204
|
+
}
|