@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,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.registerConfigureCommand = registerConfigureCommand;
|
|
40
|
+
const child_process_1 = require("child_process");
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
44
|
+
const config_1 = require("../utils/config");
|
|
45
|
+
const cache_1 = require("../utils/cache");
|
|
46
|
+
const logger_1 = require("../utils/logger");
|
|
47
|
+
const colors_1 = require("../utils/colors");
|
|
48
|
+
function registerConfigureCommand(parent) {
|
|
49
|
+
parent
|
|
50
|
+
.command('configure')
|
|
51
|
+
.alias('cfg')
|
|
52
|
+
.description('Configure workspace manager settings')
|
|
53
|
+
.action(async () => {
|
|
54
|
+
await handleConfigure();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async function handleConfigure() {
|
|
58
|
+
console.log('\n' + '='.repeat(60));
|
|
59
|
+
console.log((0, colors_1.colorize)('Workspace Manager Configuration', 'bright'));
|
|
60
|
+
console.log('='.repeat(60) + '\n');
|
|
61
|
+
const current = (0, config_1.getUserConfig)();
|
|
62
|
+
console.log('Current settings:');
|
|
63
|
+
console.log(` Workspaces directory: ${(0, colors_1.colorize)(current.workspacesDir, 'cyan')}`);
|
|
64
|
+
console.log(` GitHub organization: ${(0, colors_1.colorize)(current.githubOrg, 'cyan')}`);
|
|
65
|
+
console.log(` Clone protocol: ${(0, colors_1.colorize)(current.cloneProtocol, 'cyan')}`);
|
|
66
|
+
console.log(` Auto-launch agent: ${current.autoLaunchClaude ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
|
|
67
|
+
console.log(` Generate context file: ${current.generateClaudeContext ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
|
|
68
|
+
console.log(` MCP server: ${current.installMcp ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
|
|
69
|
+
console.log(` AI Agent: ${(0, colors_1.colorize)(current.aiAgent, 'cyan')}`);
|
|
70
|
+
console.log(` Primary agent: ${(0, colors_1.colorize)(current.primaryAgent, 'cyan')}`);
|
|
71
|
+
console.log(` Pi workspace widget: ${current.piWorkspaceInputStatus !== false ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
|
|
72
|
+
console.log(` Claude workspace table: ${current.claudeWorkspaceStatusLine !== false ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
|
|
73
|
+
console.log('');
|
|
74
|
+
try {
|
|
75
|
+
const answers = await inquirer_1.default.prompt([
|
|
76
|
+
{ type: 'input', name: 'workspacesDir', message: 'Workspaces directory:', default: current.workspacesDir, validate: (val) => val.trim().length > 0 || 'Directory path is required' },
|
|
77
|
+
{ type: 'input', name: 'githubOrg', message: 'GitHub organization:', default: current.githubOrg, validate: (val) => /^[a-zA-Z0-9_-]+$/.test(val.trim()) || 'Must be a valid GitHub org name' },
|
|
78
|
+
{ 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 },
|
|
79
|
+
{ type: 'confirm', name: 'autoLaunchClaude', message: 'Auto-launch AI agent after workspace creation?', default: current.autoLaunchClaude },
|
|
80
|
+
{ type: 'confirm', name: 'generateClaudeContext', message: 'Generate context file in workspaces?', default: current.generateClaudeContext },
|
|
81
|
+
{ type: 'confirm', name: 'installMcp', message: 'Install MCP server (Claude Code only)?', default: current.installMcp },
|
|
82
|
+
{ type: 'list', name: 'aiAgent', message: 'AI Agent(s) to integrate with:', choices: [
|
|
83
|
+
{ name: 'Auto-detect (recommended)', value: 'auto' },
|
|
84
|
+
{ name: 'Claude Code only', value: 'claude' },
|
|
85
|
+
{ name: 'Pi only', value: 'pi' },
|
|
86
|
+
{ name: 'OpenCode only', value: 'opencode' },
|
|
87
|
+
{ name: 'All available', value: 'both' },
|
|
88
|
+
], default: current.aiAgent },
|
|
89
|
+
// Only ask about primary agent when aiAgent is 'both' or 'auto'
|
|
90
|
+
// (when specific agent chosen, primary is implicitly that agent)
|
|
91
|
+
{ type: 'list', name: 'primaryAgent', message: 'Primary agent (used for launching):', choices: [
|
|
92
|
+
{ name: 'Auto-detect (first available)', value: 'auto' },
|
|
93
|
+
{ name: 'Claude Code', value: 'claude' },
|
|
94
|
+
{ name: 'Pi', value: 'pi' },
|
|
95
|
+
{ name: 'OpenCode', value: 'opencode' },
|
|
96
|
+
], default: current.primaryAgent, when: (ans) => ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
|
|
97
|
+
{ type: 'confirm', name: 'piWorkspaceInputStatus',
|
|
98
|
+
message: 'Show workspace status widget in Pi input area (branch, PRs, CI)?',
|
|
99
|
+
default: current.piWorkspaceInputStatus !== false,
|
|
100
|
+
when: (ans) => ans.aiAgent === 'pi' || ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
|
|
101
|
+
{ type: 'confirm', name: 'claudeWorkspaceStatusLine',
|
|
102
|
+
message: 'Add workspace repo table to Claude Code status line?',
|
|
103
|
+
default: current.claudeWorkspaceStatusLine !== false,
|
|
104
|
+
when: (ans) => ans.aiAgent === 'claude' || ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
|
|
105
|
+
{ type: 'confirm', name: 'autoReportBugs',
|
|
106
|
+
message: 'Auto-file a GitHub issue when a command crashes? (deduped, sanitized)',
|
|
107
|
+
default: current.autoReportBugs === true },
|
|
108
|
+
]);
|
|
109
|
+
// Validate and normalize config
|
|
110
|
+
let primaryAgent = answers.primaryAgent || 'auto';
|
|
111
|
+
// If aiAgent is specific, primaryAgent must match
|
|
112
|
+
if (answers.aiAgent === 'claude')
|
|
113
|
+
primaryAgent = 'claude';
|
|
114
|
+
if (answers.aiAgent === 'pi')
|
|
115
|
+
primaryAgent = 'pi';
|
|
116
|
+
if (answers.aiAgent === 'opencode')
|
|
117
|
+
primaryAgent = 'opencode';
|
|
118
|
+
const newConfig = {
|
|
119
|
+
workspacesDir: answers.workspacesDir.trim(),
|
|
120
|
+
githubOrg: answers.githubOrg.trim(),
|
|
121
|
+
cloneProtocol: answers.cloneProtocol,
|
|
122
|
+
autoLaunchClaude: answers.autoLaunchClaude,
|
|
123
|
+
generateClaudeContext: answers.generateClaudeContext,
|
|
124
|
+
installMcp: answers.installMcp,
|
|
125
|
+
aiAgent: answers.aiAgent,
|
|
126
|
+
primaryAgent,
|
|
127
|
+
piWorkspaceInputStatus: answers.piWorkspaceInputStatus ?? current.piWorkspaceInputStatus ?? true,
|
|
128
|
+
claudeWorkspaceStatusLine: answers.claudeWorkspaceStatusLine ?? current.claudeWorkspaceStatusLine ?? true,
|
|
129
|
+
autoReportBugs: answers.autoReportBugs ?? current.autoReportBugs ?? false,
|
|
130
|
+
};
|
|
131
|
+
(0, config_1.saveUserConfig)(newConfig);
|
|
132
|
+
console.log('');
|
|
133
|
+
(0, logger_1.logSuccess)('Configuration saved!');
|
|
134
|
+
console.log('');
|
|
135
|
+
console.log(` ${(0, colors_1.colorize)('Workspaces directory:', 'gray')} ${newConfig.workspacesDir}`);
|
|
136
|
+
console.log(` ${(0, colors_1.colorize)('GitHub organization:', 'gray')} ${newConfig.githubOrg}`);
|
|
137
|
+
console.log(` ${(0, colors_1.colorize)('Clone protocol:', 'gray')} ${newConfig.cloneProtocol}`);
|
|
138
|
+
console.log(` ${(0, colors_1.colorize)('Auto-launch agent:', 'gray')} ${newConfig.autoLaunchClaude ? 'Yes' : 'No'}`);
|
|
139
|
+
console.log(` ${(0, colors_1.colorize)('Generate context:', 'gray')} ${newConfig.generateClaudeContext ? 'Yes' : 'No'}`);
|
|
140
|
+
console.log(` ${(0, colors_1.colorize)('MCP server:', 'gray')} ${newConfig.installMcp ? 'Yes' : 'No'}`);
|
|
141
|
+
console.log(` ${(0, colors_1.colorize)('AI Agent:', 'gray')} ${newConfig.aiAgent}`);
|
|
142
|
+
console.log(` ${(0, colors_1.colorize)('Primary agent:', 'gray')} ${newConfig.primaryAgent}`);
|
|
143
|
+
console.log('');
|
|
144
|
+
// Install / upgrade shell integration.
|
|
145
|
+
// Skip if MCP install just ran it (mcp/install always installs shell integration).
|
|
146
|
+
let mcpInstalled = false;
|
|
147
|
+
if (newConfig.installMcp && !current.installMcp) {
|
|
148
|
+
(0, logger_1.logInfo)('Installing MCP server...');
|
|
149
|
+
try {
|
|
150
|
+
const mcpInstallScript = path.join(__dirname, '..', '..', 'dist', 'mcp', 'install.js');
|
|
151
|
+
(0, child_process_1.execSync)(`node "${mcpInstallScript}" install`, { stdio: 'inherit' });
|
|
152
|
+
mcpInstalled = true;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
(0, logger_1.logError)('MCP install failed. You can retry later with: w mcp install');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (newConfig.githubOrg !== current.githubOrg) {
|
|
159
|
+
await (0, cache_1.clearCache)();
|
|
160
|
+
(0, logger_1.logInfo)(`GitHub org changed from "${current.githubOrg}" to "${newConfig.githubOrg}". Repo cache has been cleared.`);
|
|
161
|
+
}
|
|
162
|
+
// Always install / upgrade the shell integration so the 'w' function
|
|
163
|
+
// is available. This is especially important on first-time setup where
|
|
164
|
+
// postinstall may not have run or the user hasn't sourced their RC file.
|
|
165
|
+
// Skip if mcp install already did it to avoid printing the reminder twice.
|
|
166
|
+
if (!mcpInstalled) {
|
|
167
|
+
installShellIntegration();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
(0, logger_1.logError)('Failed to save configuration');
|
|
172
|
+
if (error instanceof Error) {
|
|
173
|
+
(0, logger_1.logError)(error.message);
|
|
174
|
+
}
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Install or upgrade the shell integration (w/workspace shell functions).
|
|
180
|
+
* Uses an absolute path derived from this file so it works regardless of CWD.
|
|
181
|
+
* Always prints a prominent "source your RC file" reminder afterwards.
|
|
182
|
+
*/
|
|
183
|
+
function installShellIntegration() {
|
|
184
|
+
// __dirname is dist/commands/ at runtime — script is two levels up at package root
|
|
185
|
+
const scriptPath = path.join(__dirname, '..', '..', 'install-shell-integration.sh');
|
|
186
|
+
if (!fs.existsSync(scriptPath)) {
|
|
187
|
+
(0, logger_1.logWarning)('Shell integration script not found — skipping auto-install');
|
|
188
|
+
printSourceReminder();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const shell = process.env.SHELL || '';
|
|
192
|
+
const shellType = shell.endsWith('/zsh') ? 'zsh'
|
|
193
|
+
: shell.endsWith('/bash') ? 'bash'
|
|
194
|
+
: '';
|
|
195
|
+
if (!shellType) {
|
|
196
|
+
(0, logger_1.logWarning)('Unknown shell — skipping shell integration (run install-shell-integration.sh manually)');
|
|
197
|
+
printSourceReminder();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
(0, child_process_1.execSync)(`bash "${scriptPath}" ${shellType}`, { stdio: 'inherit' });
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
(0, logger_1.logWarning)('Shell integration install failed — you can run it manually:');
|
|
205
|
+
(0, logger_1.logInfo)(` bash "${scriptPath}" ${shellType}`);
|
|
206
|
+
}
|
|
207
|
+
printSourceReminder();
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Print a loud, impossible-to-miss reminder to source the RC file.
|
|
211
|
+
* Without this step the 'w' shell function is not available in the
|
|
212
|
+
* current terminal session even after a successful install.
|
|
213
|
+
*/
|
|
214
|
+
function printSourceReminder() {
|
|
215
|
+
const shell = process.env.SHELL || '';
|
|
216
|
+
const rcFile = shell.endsWith('/zsh') ? '~/.zshrc'
|
|
217
|
+
: shell.endsWith('/bash') ? '~/.bashrc'
|
|
218
|
+
: '~/.profile';
|
|
219
|
+
console.log('');
|
|
220
|
+
console.log((0, colors_1.colorize)(' ⚠️ IMPORTANT — activate the shell function in this session:', 'yellow'));
|
|
221
|
+
console.log('');
|
|
222
|
+
console.log(` ${(0, colors_1.colorize)(`source ${rcFile}`, 'cyan')}`);
|
|
223
|
+
console.log('');
|
|
224
|
+
console.log(` Or open a new terminal tab. Until then the ${(0, colors_1.colorize)('nemus', 'cyan')}/${(0, colors_1.colorize)('nem', 'cyan')} shell`);
|
|
225
|
+
console.log(` functions (which auto-cd into new workspaces) aren't active yet.`);
|
|
226
|
+
console.log('');
|
|
227
|
+
console.log(` Tip: ${(0, colors_1.colorize)('nemus', 'cyan')} works immediately without sourcing:`);
|
|
228
|
+
console.log(` ${(0, colors_1.colorize)('nemus configure', 'cyan')} ${(0, colors_1.colorize)('# first-time setup', 'gray')}`);
|
|
229
|
+
console.log(` ${(0, colors_1.colorize)('nemus list', 'cyan')} ${(0, colors_1.colorize)('# list workspaces', 'gray')}`);
|
|
230
|
+
console.log('');
|
|
231
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerCreateCommand = registerCreateCommand;
|
|
37
|
+
const config_1 = require("../utils/config");
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const github_1 = require("../utils/github");
|
|
40
|
+
const prompts_1 = require("../utils/prompts");
|
|
41
|
+
const git_operations_1 = require("../utils/git-operations");
|
|
42
|
+
const ghq_integration_1 = require("../utils/ghq-integration");
|
|
43
|
+
const workspace_meta_1 = require("../utils/workspace-meta");
|
|
44
|
+
const claude_integration_1 = require("../utils/claude-integration");
|
|
45
|
+
const logger_1 = require("../utils/logger");
|
|
46
|
+
const colors_1 = require("../utils/colors");
|
|
47
|
+
const banner_1 = require("../utils/banner");
|
|
48
|
+
const validation_1 = require("../utils/validation");
|
|
49
|
+
const command_helpers_1 = require("../utils/command-helpers");
|
|
50
|
+
const repo_resolver_1 = require("../utils/repo-resolver");
|
|
51
|
+
function registerCreateCommand(parent) {
|
|
52
|
+
parent
|
|
53
|
+
.command('create')
|
|
54
|
+
.alias('c')
|
|
55
|
+
.description('Create a new workspace')
|
|
56
|
+
.option('-w, --workspace <name>', 'Workspace name')
|
|
57
|
+
.option('-r, --repos <repos>', 'Comma-separated repository names. Use repo:suffix to add the same repo more than once under a separate folder, e.g. casper:cas-101 -> casper-cas-101')
|
|
58
|
+
.option('--prompt <prompt>', 'Original prompt that triggered workspace creation (saved to metadata)')
|
|
59
|
+
.option('--allow-empty', 'Create the workspace with no repositories (e.g. investigate-first: the agent adds repos later)')
|
|
60
|
+
.action(async (opts, cmd) => {
|
|
61
|
+
const globalOpts = (0, command_helpers_1.getGlobalOpts)(cmd);
|
|
62
|
+
await handleCreate({ ...opts, ...globalOpts });
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async function handleCreate(opts) {
|
|
66
|
+
(0, banner_1.printBanner)();
|
|
67
|
+
try {
|
|
68
|
+
// Step 1: Verify gh CLI authentication
|
|
69
|
+
(0, logger_1.logStep)(1, 6, 'Verifying GitHub CLI authentication...');
|
|
70
|
+
const isAuthenticated = await (0, github_1.verifyGhAuth)();
|
|
71
|
+
if (!isAuthenticated) {
|
|
72
|
+
(0, logger_1.logError)('GitHub CLI is not authenticated');
|
|
73
|
+
(0, github_1.displayAuthInstructions)();
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
(0, logger_1.logSuccess)('GitHub CLI authenticated');
|
|
77
|
+
// Investigate-first empty workspace: no repos to resolve, so skip the org
|
|
78
|
+
// catalog fetch entirely — otherwise an empty/failed catalog would abort
|
|
79
|
+
// creation on the guard below even though we need no repos.
|
|
80
|
+
const investigateEmpty = !!opts.allowEmpty && !opts.repos;
|
|
81
|
+
// Step 2: Fetch repositories (only when we actually need to resolve repos)
|
|
82
|
+
let repos = [];
|
|
83
|
+
if (!investigateEmpty) {
|
|
84
|
+
(0, logger_1.logStep)(2, 6, 'Fetching repositories...');
|
|
85
|
+
repos = await (0, github_1.fetchOrgRepos)({ forceRefresh: opts.forceRefresh });
|
|
86
|
+
if (repos.length === 0) {
|
|
87
|
+
(0, logger_1.logError)('No repositories found');
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Step 3: Select repositories
|
|
92
|
+
(0, logger_1.logStep)(3, 6, 'Select repositories to clone...');
|
|
93
|
+
let selectedEntries;
|
|
94
|
+
if (investigateEmpty) {
|
|
95
|
+
// Investigate-first: start with no repos; the in-session agent discovers
|
|
96
|
+
// and adds the relevant repos itself.
|
|
97
|
+
(0, logger_1.logInfo)('Creating an empty workspace (no repositories) — repos can be added later.');
|
|
98
|
+
selectedEntries = [];
|
|
99
|
+
}
|
|
100
|
+
else if (opts.repos) {
|
|
101
|
+
const repoSpecs = (0, command_helpers_1.parseList)(opts.repos);
|
|
102
|
+
const { resolved, notFound, invalidSuffix } = (0, repo_resolver_1.resolveRepoSpecs)(repoSpecs, repos);
|
|
103
|
+
if (invalidSuffix.length > 0) {
|
|
104
|
+
(0, logger_1.logError)(`Invalid instance suffix in: ${invalidSuffix.join(', ')}`);
|
|
105
|
+
(0, logger_1.logInfo)('Use repo:suffix (e.g. casper:cas-101). Suffix may contain letters, numbers, hyphens, underscores.');
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
// Warn about fuzzy-resolved names so the user knows what was used
|
|
109
|
+
for (const r of resolved) {
|
|
110
|
+
if (!r.exact) {
|
|
111
|
+
(0, logger_1.logInfo)(`Repo "${r.input}" not found exactly — using "${(0, colors_1.colorize)(r.repo.name, 'cyan')}" (best match)`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (notFound.length > 0) {
|
|
115
|
+
(0, logger_1.logError)(`Repositories not found: ${notFound.join(', ')}`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
selectedEntries = resolved.map(r => ({ repo: r.repo, directoryName: r.directoryName }));
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
selectedEntries = await (0, prompts_1.promptRepositorySelection)(repos);
|
|
122
|
+
}
|
|
123
|
+
if (selectedEntries.length === 0 && !opts.allowEmpty) {
|
|
124
|
+
(0, logger_1.logInfo)('No repositories selected');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Step 4: Get workspace name
|
|
128
|
+
(0, logger_1.logStep)(4, 6, 'Configure workspace...');
|
|
129
|
+
let workspaceName;
|
|
130
|
+
if (opts.workspace) {
|
|
131
|
+
workspaceName = (0, validation_1.sanitizeWorkspaceName)(opts.workspace);
|
|
132
|
+
const nameError = (0, validation_1.validateWorkspaceName)(workspaceName);
|
|
133
|
+
if (nameError !== true) {
|
|
134
|
+
(0, logger_1.logError)(typeof nameError === 'string' ? nameError : 'Invalid workspace name');
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
const exists = await (0, validation_1.checkWorkspaceExists)(workspaceName);
|
|
138
|
+
if (exists) {
|
|
139
|
+
const resolved = await (0, validation_1.resolveWorkspaceNameConflict)(workspaceName, selectedEntries.map(e => e.directoryName));
|
|
140
|
+
(0, logger_1.logInfo)(`Workspace "${workspaceName}" already exists — using "${(0, colors_1.colorize)(resolved, 'cyan')}" instead.`);
|
|
141
|
+
workspaceName = resolved;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
workspaceName = await (0, prompts_1.promptWorkspaceName)();
|
|
146
|
+
// Auto-resolve conflict in case the interactively chosen name already exists
|
|
147
|
+
// (the prompt validates format but not uniqueness at this point)
|
|
148
|
+
const interactiveExists = await (0, validation_1.checkWorkspaceExists)(workspaceName);
|
|
149
|
+
if (interactiveExists) {
|
|
150
|
+
const resolved = await (0, validation_1.resolveWorkspaceNameConflict)(workspaceName, selectedEntries.map(e => e.directoryName));
|
|
151
|
+
(0, logger_1.logInfo)(`Workspace "${workspaceName}" already exists — using "${(0, colors_1.colorize)(resolved, 'cyan')}" instead.`);
|
|
152
|
+
workspaceName = resolved;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Step 5: Confirm
|
|
156
|
+
const workspacePath = path.join(config_1.WORKSPACES_DIR, workspaceName);
|
|
157
|
+
if (!opts.yes) {
|
|
158
|
+
const confirmed = await (0, prompts_1.confirmWorkspaceCreation)(workspaceName, selectedEntries.length, workspacePath);
|
|
159
|
+
if (!confirmed) {
|
|
160
|
+
(0, logger_1.logInfo)('Operation cancelled');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Step 6: Clone repositories
|
|
165
|
+
(0, logger_1.logStep)(5, 6, 'Creating workspace...');
|
|
166
|
+
const { mkdir } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
167
|
+
await mkdir(workspacePath, { recursive: true });
|
|
168
|
+
if (selectedEntries.length > 0)
|
|
169
|
+
await (0, ghq_integration_1.warnIfGhqMissing)();
|
|
170
|
+
const results = await (0, git_operations_1.cloneRepositories)(selectedEntries, workspacePath);
|
|
171
|
+
(0, git_operations_1.reportCloneResults)(results);
|
|
172
|
+
// Step 7: Save metadata & generate context
|
|
173
|
+
(0, logger_1.logStep)(6, 6, 'Saving workspace metadata...');
|
|
174
|
+
const metadata = (0, workspace_meta_1.createMetadata)(workspaceName, results, { prompt: opts.prompt });
|
|
175
|
+
await (0, workspace_meta_1.saveMetadata)(workspacePath, metadata);
|
|
176
|
+
const successfulRepos = results
|
|
177
|
+
.filter(r => r.status === 'success')
|
|
178
|
+
.map(r => r.repo);
|
|
179
|
+
// Generate context + .mcp.json even for an empty (investigate-first)
|
|
180
|
+
// workspace, so the in-session agent lands with the MCP tools (search-repos
|
|
181
|
+
// / update-workspace) needed to discover and add repos.
|
|
182
|
+
if (successfulRepos.length > 0 || opts.allowEmpty) {
|
|
183
|
+
await (0, claude_integration_1.generateClaudeContext)(workspacePath, workspaceName, successfulRepos, metadata);
|
|
184
|
+
}
|
|
185
|
+
(0, logger_1.logSuccess)(`Workspace "${(0, colors_1.colorize)(workspaceName, 'cyan')}" created successfully!`);
|
|
186
|
+
// Write workspace path to temp file for shell integration auto-CD
|
|
187
|
+
const { writeFile } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
188
|
+
const os = await Promise.resolve().then(() => __importStar(require('os')));
|
|
189
|
+
const tempFile = path.join(os.homedir(), '.workspace-last-created');
|
|
190
|
+
try {
|
|
191
|
+
await writeFile(tempFile, workspacePath, 'utf-8');
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// Non-critical — shell integration CD won't work but workspace was created
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
(0, logger_1.logError)('Failed to create workspace');
|
|
199
|
+
if (error instanceof Error) {
|
|
200
|
+
(0, logger_1.logError)(error.message);
|
|
201
|
+
}
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Hook handler for Claude Code hooks.
|
|
5
|
+
* Invoked via ~/.claude/settings.json hooks — reads JSON from stdin,
|
|
6
|
+
* maps the event to an agent status, and writes to state file.
|
|
7
|
+
*
|
|
8
|
+
* Status model:
|
|
9
|
+
* idle — agent is not working (new, finished, waiting for input)
|
|
10
|
+
* working — agent is actively processing (thinking, calling tools)
|
|
11
|
+
* waiting — agent needs user action (permission approval)
|
|
12
|
+
* stopped — session ended
|
|
13
|
+
*
|
|
14
|
+
* Event mapping:
|
|
15
|
+
* SessionStart → idle (session opened, not working yet)
|
|
16
|
+
* UserPromptSubmit → working (user sent prompt, agent starts)
|
|
17
|
+
* PreToolUse → working (agent calling a tool)
|
|
18
|
+
* PostToolUse → working (tool done, agent still processing)
|
|
19
|
+
* Notification:
|
|
20
|
+
* permission_prompt → waiting (needs user to approve tool use)
|
|
21
|
+
* idle_prompt → idle (agent finished, waiting for input)
|
|
22
|
+
* Stop → idle (agent finished its turn)
|
|
23
|
+
* SessionEnd → stopped (session ended)
|
|
24
|
+
*
|
|
25
|
+
* IMPORTANT: Must never write to stderr or throw — always exit 0.
|
|
26
|
+
*/
|
|
27
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
30
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
31
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
32
|
+
}
|
|
33
|
+
Object.defineProperty(o, k2, desc);
|
|
34
|
+
}) : (function(o, m, k, k2) {
|
|
35
|
+
if (k2 === undefined) k2 = k;
|
|
36
|
+
o[k2] = m[k];
|
|
37
|
+
}));
|
|
38
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
39
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
40
|
+
}) : function(o, v) {
|
|
41
|
+
o["default"] = v;
|
|
42
|
+
});
|
|
43
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
44
|
+
var ownKeys = function(o) {
|
|
45
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
46
|
+
var ar = [];
|
|
47
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
48
|
+
return ar;
|
|
49
|
+
};
|
|
50
|
+
return ownKeys(o);
|
|
51
|
+
};
|
|
52
|
+
return function (mod) {
|
|
53
|
+
if (mod && mod.__esModule) return mod;
|
|
54
|
+
var result = {};
|
|
55
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
56
|
+
__setModuleDefault(result, mod);
|
|
57
|
+
return result;
|
|
58
|
+
};
|
|
59
|
+
})();
|
|
60
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
61
|
+
const fs = __importStar(require("fs"));
|
|
62
|
+
const path = __importStar(require("path"));
|
|
63
|
+
const agent_state_1 = require("../../utils/agent-state");
|
|
64
|
+
const config_1 = require("../../utils/config");
|
|
65
|
+
function main() {
|
|
66
|
+
try {
|
|
67
|
+
const args = process.argv.slice(2);
|
|
68
|
+
const eventIdx = args.indexOf('--event');
|
|
69
|
+
const event = eventIdx >= 0 ? args[eventIdx + 1] : null;
|
|
70
|
+
if (!event) {
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
let input;
|
|
74
|
+
try {
|
|
75
|
+
const raw = fs.readFileSync('/dev/stdin', 'utf-8');
|
|
76
|
+
input = JSON.parse(raw);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
const sessionId = input.session_id;
|
|
82
|
+
if (!sessionId || !/^[a-zA-Z0-9\-]{1,100}$/.test(sessionId)) {
|
|
83
|
+
process.exit(0); // reject missing or invalid session IDs
|
|
84
|
+
}
|
|
85
|
+
(0, agent_state_1.ensureStateDir)();
|
|
86
|
+
let newStatus;
|
|
87
|
+
switch (event) {
|
|
88
|
+
case 'SessionStart':
|
|
89
|
+
newStatus = 'idle';
|
|
90
|
+
break;
|
|
91
|
+
case 'UserPromptSubmit':
|
|
92
|
+
newStatus = 'working';
|
|
93
|
+
break;
|
|
94
|
+
case 'PreToolUse':
|
|
95
|
+
newStatus = 'working';
|
|
96
|
+
break;
|
|
97
|
+
case 'PostToolUse':
|
|
98
|
+
newStatus = 'working';
|
|
99
|
+
break;
|
|
100
|
+
case 'Notification': {
|
|
101
|
+
const notifType = input.notification_type || '';
|
|
102
|
+
if (notifType === 'permission_prompt') {
|
|
103
|
+
newStatus = 'waiting'; // needs user to approve
|
|
104
|
+
}
|
|
105
|
+
else if (notifType === 'idle_prompt') {
|
|
106
|
+
newStatus = 'idle'; // just idle, not a special state
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case 'Stop':
|
|
114
|
+
newStatus = 'idle';
|
|
115
|
+
break;
|
|
116
|
+
case 'SessionEnd':
|
|
117
|
+
newStatus = 'stopped';
|
|
118
|
+
break;
|
|
119
|
+
default:
|
|
120
|
+
process.exit(0);
|
|
121
|
+
}
|
|
122
|
+
const now = new Date().toISOString();
|
|
123
|
+
const existing = (0, agent_state_1.readAgentState)(sessionId);
|
|
124
|
+
if (existing) {
|
|
125
|
+
existing.status = newStatus;
|
|
126
|
+
existing.lastUpdatedAt = now;
|
|
127
|
+
// Always update PID — handles resumed sessions where the old
|
|
128
|
+
// process is dead but session ID is reused with a new process
|
|
129
|
+
existing.pid = process.ppid || existing.pid;
|
|
130
|
+
(0, agent_state_1.writeAgentState)(existing);
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}
|
|
133
|
+
// New session — infer workspace from cwd
|
|
134
|
+
const cwd = input.cwd || process.cwd();
|
|
135
|
+
let workspace = 'unknown';
|
|
136
|
+
let workspacePath = cwd;
|
|
137
|
+
const workspacesDir = config_1.WORKSPACES_DIR;
|
|
138
|
+
if (cwd.startsWith(workspacesDir + path.sep) || cwd === workspacesDir) {
|
|
139
|
+
const relative = cwd.slice(workspacesDir.length + 1);
|
|
140
|
+
const parts = relative.split(path.sep);
|
|
141
|
+
if (parts[0]) {
|
|
142
|
+
workspace = parts[0];
|
|
143
|
+
workspacePath = path.join(workspacesDir, workspace);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const state = {
|
|
147
|
+
sessionId,
|
|
148
|
+
workspace,
|
|
149
|
+
workspacePath,
|
|
150
|
+
pid: process.ppid || 0,
|
|
151
|
+
status: newStatus,
|
|
152
|
+
startedAt: now,
|
|
153
|
+
lastUpdatedAt: now,
|
|
154
|
+
};
|
|
155
|
+
(0, agent_state_1.writeAgentState)(state);
|
|
156
|
+
process.exit(0);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
process.exit(0);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
main();
|