@claudetree/cli 0.1.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/LICENSE +21 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +55 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +37 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +303 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +73 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +3 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +54 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/web.d.ts +3 -0
- package/dist/commands/web.d.ts.map +1 -0
- package/dist/commands/web.js +65 -0
- package/dist/commands/web.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lucas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,WAAW,SAsDpB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { mkdir, writeFile, access } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const CONFIG_DIR = '.claudetree';
|
|
5
|
+
const CONFIG_FILE = 'config.json';
|
|
6
|
+
export const initCommand = new Command('init')
|
|
7
|
+
.description('Initialize claudetree in current repository')
|
|
8
|
+
.option('-d, --worktree-dir <dir>', 'Base directory for worktrees', '.worktrees')
|
|
9
|
+
.option('-f, --force', 'Overwrite existing configuration', false)
|
|
10
|
+
.action(async (options) => {
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
const configDir = join(cwd, CONFIG_DIR);
|
|
13
|
+
const configPath = join(configDir, CONFIG_FILE);
|
|
14
|
+
// Check if already initialized
|
|
15
|
+
if (!options.force) {
|
|
16
|
+
try {
|
|
17
|
+
await access(configPath);
|
|
18
|
+
console.error('claudetree is already initialized. Use --force to reinitialize.');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Config doesn't exist, proceed
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Create config directory
|
|
26
|
+
await mkdir(configDir, { recursive: true });
|
|
27
|
+
// Create default config
|
|
28
|
+
const config = {
|
|
29
|
+
version: '0.1.0',
|
|
30
|
+
worktreeDir: options.worktreeDir,
|
|
31
|
+
sessions: {},
|
|
32
|
+
};
|
|
33
|
+
await writeFile(configPath, JSON.stringify(config, null, 2));
|
|
34
|
+
// Create worktree directory
|
|
35
|
+
const worktreeDir = join(cwd, options.worktreeDir);
|
|
36
|
+
await mkdir(worktreeDir, { recursive: true });
|
|
37
|
+
// Add to gitignore
|
|
38
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
39
|
+
try {
|
|
40
|
+
const gitignoreContent = await import('node:fs/promises')
|
|
41
|
+
.then((fs) => fs.readFile(gitignorePath, 'utf-8'))
|
|
42
|
+
.catch(() => '');
|
|
43
|
+
if (!gitignoreContent.includes(CONFIG_DIR)) {
|
|
44
|
+
const newContent = gitignoreContent + `\n# claudetree\n${CONFIG_DIR}/\n${options.worktreeDir}/\n`;
|
|
45
|
+
await writeFile(gitignorePath, newContent);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Ignore gitignore errors
|
|
50
|
+
}
|
|
51
|
+
console.log(`Initialized claudetree in ${cwd}`);
|
|
52
|
+
console.log(` Config: ${configPath}`);
|
|
53
|
+
console.log(` Worktrees: ${worktreeDir}`);
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,GAAG,aAAa,CAAC;AACjC,MAAM,WAAW,GAAG,aAAa,CAAC;AAOlC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,0BAA0B,EAAE,8BAA8B,EAAE,YAAY,CAAC;KAChF,MAAM,CAAC,aAAa,EAAE,kCAAkC,EAAE,KAAK,CAAC;KAChE,MAAM,CAAC,KAAK,EAAE,OAAoB,EAAE,EAAE;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAEhD,+BAA+B;IAC/B,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;YACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,wBAAwB;IACxB,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAE7D,4BAA4B;IAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9C,mBAAmB;IACnB,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,gBAAgB,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC;aACtD,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;aACjD,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAEnB,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3C,MAAM,UAAU,GAAG,gBAAgB,GAAG,mBAAmB,UAAU,MAAM,OAAO,CAAC,WAAW,KAAK,CAAC;YAClG,MAAM,SAAS,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,aAAa,UAAU,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,gBAAgB,WAAW,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,WAAW,SAoCpB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { GitWorktreeAdapter } from '@claudetree/core';
|
|
3
|
+
export const listCommand = new Command('list')
|
|
4
|
+
.alias('ls')
|
|
5
|
+
.description('List all worktrees')
|
|
6
|
+
.option('--json', 'Output as JSON', false)
|
|
7
|
+
.action(async (options) => {
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
const adapter = new GitWorktreeAdapter(cwd);
|
|
10
|
+
try {
|
|
11
|
+
const worktrees = await adapter.list();
|
|
12
|
+
if (options.json) {
|
|
13
|
+
console.log(JSON.stringify(worktrees, null, 2));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (worktrees.length === 0) {
|
|
17
|
+
console.log('No worktrees found.');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
console.log('Worktrees:\n');
|
|
21
|
+
for (const wt of worktrees) {
|
|
22
|
+
const mainTag = wt.isMainWorktree ? ' (main)' : '';
|
|
23
|
+
const branch = wt.branch || '(detached)';
|
|
24
|
+
console.log(` ${branch}${mainTag}`);
|
|
25
|
+
console.log(` Path: ${wt.path}`);
|
|
26
|
+
console.log(` Commit: ${wt.commit.slice(0, 8)}`);
|
|
27
|
+
console.log('');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof Error) {
|
|
32
|
+
console.error(`Error: ${error.message}`);
|
|
33
|
+
}
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAMtD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,KAAK,CAAC,IAAI,CAAC;KACX,WAAW,CAAC,oBAAoB,CAAC;KACjC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,KAAK,CAAC;KACzC,MAAM,CAAC,KAAK,EAAE,OAAoB,EAAE,EAAE;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAE5C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QAEvC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC5B,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,IAAI,YAAY,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,GAAG,OAAO,EAAE,CAAC,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6CpC,eAAO,MAAM,YAAY,SAuSrB,CAAC"}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { access, readFile } from 'node:fs/promises';
|
|
5
|
+
import { GitWorktreeAdapter, ClaudeSessionAdapter, FileSessionRepository, FileEventRepository, FileToolApprovalRepository, GitHubAdapter, } from '@claudetree/core';
|
|
6
|
+
const CONFIG_DIR = '.claudetree';
|
|
7
|
+
async function loadConfig(cwd) {
|
|
8
|
+
try {
|
|
9
|
+
const configPath = join(cwd, CONFIG_DIR, 'config.json');
|
|
10
|
+
await access(configPath);
|
|
11
|
+
const content = await readFile(configPath, 'utf-8');
|
|
12
|
+
return JSON.parse(content);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export const startCommand = new Command('start')
|
|
19
|
+
.description('Create worktree from issue and start Claude session')
|
|
20
|
+
.argument('<issue>', 'Issue number, GitHub URL, or task name')
|
|
21
|
+
.option('-p, --prompt <prompt>', 'Initial prompt for Claude')
|
|
22
|
+
.option('--no-session', 'Create worktree without starting Claude')
|
|
23
|
+
.option('-s, --skill <skill>', 'Skill to activate (tdd, review)')
|
|
24
|
+
.option('-b, --branch <branch>', 'Custom branch name')
|
|
25
|
+
.option('-t, --token <token>', 'GitHub token (or use GITHUB_TOKEN env)')
|
|
26
|
+
.action(async (issue, options) => {
|
|
27
|
+
const cwd = process.cwd();
|
|
28
|
+
const config = await loadConfig(cwd);
|
|
29
|
+
if (!config) {
|
|
30
|
+
console.error('Error: claudetree not initialized. Run "claudetree init" first.');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
let issueNumber = null;
|
|
34
|
+
let issueData = null;
|
|
35
|
+
let branchName;
|
|
36
|
+
// Check if it's a GitHub URL
|
|
37
|
+
const ghToken = options.token ?? process.env.GITHUB_TOKEN ?? config.github?.token;
|
|
38
|
+
if (issue.includes('github.com')) {
|
|
39
|
+
// Parse GitHub URL
|
|
40
|
+
if (!ghToken) {
|
|
41
|
+
console.error('Error: GitHub token required for URL. Set GITHUB_TOKEN or use --token.');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const ghAdapter = new GitHubAdapter(ghToken);
|
|
45
|
+
const parsed = ghAdapter.parseIssueUrl(issue);
|
|
46
|
+
if (!parsed) {
|
|
47
|
+
console.error('Error: Invalid GitHub URL format.');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
console.log(`Fetching issue #${parsed.number} from ${parsed.owner}/${parsed.repo}...`);
|
|
51
|
+
try {
|
|
52
|
+
issueData = await ghAdapter.getIssue(parsed.owner, parsed.repo, parsed.number);
|
|
53
|
+
issueNumber = issueData.number;
|
|
54
|
+
branchName = options.branch ?? ghAdapter.generateBranchName(issueNumber, issueData.title);
|
|
55
|
+
console.log(` Title: ${issueData.title}`);
|
|
56
|
+
console.log(` Labels: ${issueData.labels.join(', ') || 'none'}`);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error(`Error: Failed to fetch issue. ${error instanceof Error ? error.message : ''}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Parse as issue number or task name
|
|
65
|
+
const parsed = parseInt(issue, 10);
|
|
66
|
+
const isNumber = !isNaN(parsed);
|
|
67
|
+
if (isNumber && ghToken && config.github?.owner && config.github?.repo) {
|
|
68
|
+
// Try to fetch issue from configured repo
|
|
69
|
+
const ghAdapter = new GitHubAdapter(ghToken);
|
|
70
|
+
try {
|
|
71
|
+
console.log(`Fetching issue #${parsed}...`);
|
|
72
|
+
issueData = await ghAdapter.getIssue(config.github.owner, config.github.repo, parsed);
|
|
73
|
+
issueNumber = issueData.number;
|
|
74
|
+
branchName = options.branch ?? ghAdapter.generateBranchName(issueNumber, issueData.title);
|
|
75
|
+
console.log(` Title: ${issueData.title}`);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Fall back to simple issue number
|
|
79
|
+
issueNumber = parsed;
|
|
80
|
+
branchName = options.branch ?? `issue-${issueNumber}`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (isNumber) {
|
|
84
|
+
issueNumber = parsed;
|
|
85
|
+
branchName = options.branch ?? `issue-${issueNumber}`;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
branchName = options.branch ?? `task-${issue}`;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const worktreePath = join(cwd, config.worktreeDir, branchName);
|
|
92
|
+
// Check if worktree already exists
|
|
93
|
+
const gitAdapter = new GitWorktreeAdapter(cwd);
|
|
94
|
+
const existingWorktrees = await gitAdapter.list();
|
|
95
|
+
const existingWorktree = existingWorktrees.find((wt) => wt.branch === branchName || wt.path.endsWith(branchName));
|
|
96
|
+
let worktree;
|
|
97
|
+
if (existingWorktree) {
|
|
98
|
+
console.log(`\nUsing existing worktree: ${branchName}`);
|
|
99
|
+
worktree = {
|
|
100
|
+
id: randomUUID(),
|
|
101
|
+
path: existingWorktree.path,
|
|
102
|
+
branch: existingWorktree.branch,
|
|
103
|
+
};
|
|
104
|
+
console.log(` Branch: ${worktree.branch}`);
|
|
105
|
+
console.log(` Path: ${worktree.path}`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
console.log(`\nCreating worktree: ${branchName}`);
|
|
109
|
+
try {
|
|
110
|
+
worktree = await gitAdapter.create({
|
|
111
|
+
path: worktreePath,
|
|
112
|
+
branch: branchName,
|
|
113
|
+
issueNumber: issueNumber ?? undefined,
|
|
114
|
+
});
|
|
115
|
+
console.log(` Branch: ${worktree.branch}`);
|
|
116
|
+
console.log(` Path: ${worktree.path}`);
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (error instanceof Error) {
|
|
120
|
+
console.error(`Error: ${error.message}`);
|
|
121
|
+
}
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
if (options.noSession) {
|
|
127
|
+
console.log('\nWorktree created. Use "cd" to navigate and start working.');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// Check Claude availability
|
|
131
|
+
const claudeAdapter = new ClaudeSessionAdapter();
|
|
132
|
+
const available = await claudeAdapter.isClaudeAvailable();
|
|
133
|
+
if (!available) {
|
|
134
|
+
console.error('\nError: Claude CLI not found. Install it first.');
|
|
135
|
+
console.log('Worktree created but Claude session not started.');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// Create session record
|
|
139
|
+
const sessionRepo = new FileSessionRepository(join(cwd, CONFIG_DIR));
|
|
140
|
+
const session = {
|
|
141
|
+
id: randomUUID(),
|
|
142
|
+
worktreeId: worktree.id,
|
|
143
|
+
claudeSessionId: null,
|
|
144
|
+
status: 'pending',
|
|
145
|
+
issueNumber,
|
|
146
|
+
prompt: options.prompt ?? null,
|
|
147
|
+
createdAt: new Date(),
|
|
148
|
+
updatedAt: new Date(),
|
|
149
|
+
};
|
|
150
|
+
await sessionRepo.save(session);
|
|
151
|
+
// Build prompt
|
|
152
|
+
let prompt;
|
|
153
|
+
if (options.prompt) {
|
|
154
|
+
prompt = options.prompt;
|
|
155
|
+
}
|
|
156
|
+
else if (issueData) {
|
|
157
|
+
prompt = `You are working on Issue #${issueNumber}: "${issueData.title}"
|
|
158
|
+
|
|
159
|
+
Issue Description:
|
|
160
|
+
${issueData.body || 'No description provided.'}
|
|
161
|
+
|
|
162
|
+
IMPORTANT: Do NOT just analyze or suggest. Actually IMPLEMENT the solution.
|
|
163
|
+
|
|
164
|
+
Workflow:
|
|
165
|
+
1. Read the relevant code files
|
|
166
|
+
2. Write the code to solve this issue
|
|
167
|
+
3. Run tests to verify your implementation
|
|
168
|
+
4. When done, commit your changes with a clear message
|
|
169
|
+
5. Create a PR to the develop branch
|
|
170
|
+
|
|
171
|
+
Start implementing now.`;
|
|
172
|
+
}
|
|
173
|
+
else if (issueNumber) {
|
|
174
|
+
prompt = `Working on issue #${issueNumber}. Implement the solution - do not just analyze.`;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
prompt = `Working on ${branchName}. Implement any required changes.`;
|
|
178
|
+
}
|
|
179
|
+
// Add skill if specified
|
|
180
|
+
let systemPrompt;
|
|
181
|
+
if (options.skill === 'tdd') {
|
|
182
|
+
systemPrompt = 'Follow TDD workflow: write failing test first, then implement, then refactor.';
|
|
183
|
+
}
|
|
184
|
+
else if (options.skill === 'review') {
|
|
185
|
+
systemPrompt = 'Review code thoroughly for security, quality, and best practices.';
|
|
186
|
+
}
|
|
187
|
+
console.log('\nStarting Claude session...');
|
|
188
|
+
if (systemPrompt) {
|
|
189
|
+
console.log(` Skill: ${options.skill}`);
|
|
190
|
+
}
|
|
191
|
+
// Initialize event repositories
|
|
192
|
+
const eventRepo = new FileEventRepository(join(cwd, CONFIG_DIR));
|
|
193
|
+
const approvalRepo = new FileToolApprovalRepository(join(cwd, CONFIG_DIR));
|
|
194
|
+
// Setup event listener for recording
|
|
195
|
+
claudeAdapter.on('output', async (event) => {
|
|
196
|
+
const { output } = event;
|
|
197
|
+
// Map Claude output type to event type
|
|
198
|
+
let eventType = 'output';
|
|
199
|
+
if (output.type === 'tool_use') {
|
|
200
|
+
eventType = 'tool_call';
|
|
201
|
+
// Record tool approval request
|
|
202
|
+
try {
|
|
203
|
+
const parsed = parseToolCall(output.content);
|
|
204
|
+
if (parsed) {
|
|
205
|
+
await approvalRepo.save({
|
|
206
|
+
id: randomUUID(),
|
|
207
|
+
sessionId: session.id,
|
|
208
|
+
toolName: parsed.toolName,
|
|
209
|
+
parameters: parsed.parameters,
|
|
210
|
+
status: 'approved', // Auto-approved for now
|
|
211
|
+
approvedBy: 'auto',
|
|
212
|
+
requestedAt: output.timestamp,
|
|
213
|
+
resolvedAt: output.timestamp,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// Ignore parse errors
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (output.type === 'error') {
|
|
222
|
+
eventType = 'error';
|
|
223
|
+
}
|
|
224
|
+
// Record event
|
|
225
|
+
try {
|
|
226
|
+
await eventRepo.append({
|
|
227
|
+
id: randomUUID(),
|
|
228
|
+
sessionId: session.id,
|
|
229
|
+
type: eventType,
|
|
230
|
+
content: output.content,
|
|
231
|
+
timestamp: output.timestamp,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
// Ignore file write errors
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
// Start Claude session
|
|
239
|
+
console.log('\n\x1b[33m[Debug]\x1b[0m Starting Claude process...');
|
|
240
|
+
console.log(`\x1b[33m[Debug]\x1b[0m Prompt: ${prompt.slice(0, 100)}...`);
|
|
241
|
+
const result = await claudeAdapter.start({
|
|
242
|
+
workingDir: worktree.path,
|
|
243
|
+
prompt,
|
|
244
|
+
systemPrompt,
|
|
245
|
+
allowedTools: ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep'],
|
|
246
|
+
});
|
|
247
|
+
console.log(`\x1b[33m[Debug]\x1b[0m Process started with ID: ${result.processId.slice(0, 8)}`);
|
|
248
|
+
// Update session
|
|
249
|
+
session.status = 'running';
|
|
250
|
+
session.updatedAt = new Date();
|
|
251
|
+
await sessionRepo.save(session);
|
|
252
|
+
console.log(`\nSession started: ${session.id.slice(0, 8)}`);
|
|
253
|
+
console.log(`Working directory: ${worktree.path}`);
|
|
254
|
+
console.log('Claude is now working on the issue...\n');
|
|
255
|
+
console.log('\x1b[33m[Debug]\x1b[0m Waiting for Claude output...\n');
|
|
256
|
+
// Wait for Claude to complete and show output
|
|
257
|
+
let outputCount = 0;
|
|
258
|
+
for await (const output of claudeAdapter.getOutput(result.processId)) {
|
|
259
|
+
outputCount++;
|
|
260
|
+
console.log(`\x1b[33m[Debug]\x1b[0m Received output #${outputCount}: type=${output.type}`);
|
|
261
|
+
if (output.type === 'text') {
|
|
262
|
+
console.log(output.content);
|
|
263
|
+
}
|
|
264
|
+
else if (output.type === 'tool_use') {
|
|
265
|
+
console.log(`\x1b[36m[Tool]\x1b[0m ${output.content}`);
|
|
266
|
+
}
|
|
267
|
+
else if (output.type === 'error') {
|
|
268
|
+
console.error(`\x1b[31m[Error]\x1b[0m ${output.content}`);
|
|
269
|
+
}
|
|
270
|
+
else if (output.type === 'done') {
|
|
271
|
+
console.log(`\x1b[32m[Done]\x1b[0m Session ID: ${output.content}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
console.log(`\x1b[33m[Debug]\x1b[0m Total outputs received: ${outputCount}`);
|
|
275
|
+
// Session completed
|
|
276
|
+
session.status = 'completed';
|
|
277
|
+
session.updatedAt = new Date();
|
|
278
|
+
await sessionRepo.save(session);
|
|
279
|
+
console.log('\nSession completed.');
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
if (error instanceof Error) {
|
|
283
|
+
console.error(`Error: ${error.message}`);
|
|
284
|
+
}
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
function parseToolCall(content) {
|
|
289
|
+
// Format: "ToolName: {json}"
|
|
290
|
+
const match = content.match(/^(\w+):\s*(.+)$/);
|
|
291
|
+
if (!match)
|
|
292
|
+
return null;
|
|
293
|
+
try {
|
|
294
|
+
return {
|
|
295
|
+
toolName: match[1] ?? '',
|
|
296
|
+
parameters: JSON.parse(match[2] ?? '{}'),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,eAAO,MAAM,aAAa,SAmEtB,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { access } from 'node:fs/promises';
|
|
4
|
+
import { FileSessionRepository } from '@claudetree/core';
|
|
5
|
+
const CONFIG_DIR = '.claudetree';
|
|
6
|
+
const STATUS_COLORS = {
|
|
7
|
+
pending: '\x1b[33m', // yellow
|
|
8
|
+
running: '\x1b[32m', // green
|
|
9
|
+
paused: '\x1b[34m', // blue
|
|
10
|
+
completed: '\x1b[36m', // cyan
|
|
11
|
+
failed: '\x1b[31m', // red
|
|
12
|
+
};
|
|
13
|
+
const RESET = '\x1b[0m';
|
|
14
|
+
export const statusCommand = new Command('status')
|
|
15
|
+
.description('Show status of all sessions')
|
|
16
|
+
.option('--json', 'Output as JSON', false)
|
|
17
|
+
.option('-w, --watch', 'Watch mode with real-time updates', false)
|
|
18
|
+
.action(async (options) => {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
const configDir = join(cwd, CONFIG_DIR);
|
|
21
|
+
try {
|
|
22
|
+
await access(configDir);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
console.error('Error: claudetree not initialized. Run "claudetree init" first.');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const sessionRepo = new FileSessionRepository(configDir);
|
|
29
|
+
const displayStatus = async () => {
|
|
30
|
+
const sessions = await sessionRepo.findAll();
|
|
31
|
+
if (options.json) {
|
|
32
|
+
console.log(JSON.stringify(sessions, null, 2));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (sessions.length === 0) {
|
|
36
|
+
console.log('No active sessions.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
console.log('Sessions:\n');
|
|
40
|
+
for (const session of sessions) {
|
|
41
|
+
const color = STATUS_COLORS[session.status] ?? '';
|
|
42
|
+
const statusStr = `${color}${session.status}${RESET}`;
|
|
43
|
+
const issueStr = session.issueNumber ? ` (Issue #${session.issueNumber})` : '';
|
|
44
|
+
console.log(` ${session.id.slice(0, 8)} - ${statusStr}${issueStr}`);
|
|
45
|
+
console.log(` Worktree: ${session.worktreeId.slice(0, 8)}`);
|
|
46
|
+
if (session.prompt) {
|
|
47
|
+
const truncatedPrompt = session.prompt.length > 50
|
|
48
|
+
? session.prompt.slice(0, 50) + '...'
|
|
49
|
+
: session.prompt;
|
|
50
|
+
console.log(` Prompt: ${truncatedPrompt}`);
|
|
51
|
+
}
|
|
52
|
+
console.log(` Created: ${session.createdAt.toLocaleString()}`);
|
|
53
|
+
console.log('');
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
if (options.watch) {
|
|
57
|
+
console.log('Watching sessions... (Ctrl+C to exit)\n');
|
|
58
|
+
const interval = setInterval(async () => {
|
|
59
|
+
console.clear();
|
|
60
|
+
console.log('Watching sessions... (Ctrl+C to exit)\n');
|
|
61
|
+
await displayStatus();
|
|
62
|
+
}, 2000);
|
|
63
|
+
process.on('SIGINT', () => {
|
|
64
|
+
clearInterval(interval);
|
|
65
|
+
process.exit(0);
|
|
66
|
+
});
|
|
67
|
+
await displayStatus();
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
await displayStatus();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,WAAW,SAuDpB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { access } from 'node:fs/promises';
|
|
4
|
+
import { FileSessionRepository } from '@claudetree/core';
|
|
5
|
+
const CONFIG_DIR = '.claudetree';
|
|
6
|
+
export const stopCommand = new Command('stop')
|
|
7
|
+
.description('Stop a Claude session')
|
|
8
|
+
.argument('[session-id]', 'Session ID (or "all" to stop all)')
|
|
9
|
+
.option('--all', 'Stop all sessions', false)
|
|
10
|
+
.option('--keep-worktree', 'Keep worktree after stopping', false)
|
|
11
|
+
.action(async (sessionId, options) => {
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const configDir = join(cwd, CONFIG_DIR);
|
|
14
|
+
try {
|
|
15
|
+
await access(configDir);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
console.error('Error: claudetree not initialized. Run "claudetree init" first.');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const sessionRepo = new FileSessionRepository(configDir);
|
|
22
|
+
const sessions = await sessionRepo.findAll();
|
|
23
|
+
if (sessions.length === 0) {
|
|
24
|
+
console.log('No active sessions.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const toStop = options.all
|
|
28
|
+
? sessions
|
|
29
|
+
: sessions.filter((s) => s.id.startsWith(sessionId ?? ''));
|
|
30
|
+
if (toStop.length === 0) {
|
|
31
|
+
console.error(`No session found matching: ${sessionId}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
for (const session of toStop) {
|
|
35
|
+
console.log(`Stopping session: ${session.id.slice(0, 8)}`);
|
|
36
|
+
// Update session status
|
|
37
|
+
session.status = 'completed';
|
|
38
|
+
session.updatedAt = new Date();
|
|
39
|
+
await sessionRepo.save(session);
|
|
40
|
+
// Optionally remove worktree
|
|
41
|
+
if (!options.keepWorktree) {
|
|
42
|
+
try {
|
|
43
|
+
// Note: We'd need to store the actual worktree path
|
|
44
|
+
console.log(` Session stopped. Worktree kept (use --keep-worktree=false to remove).`);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.log(` Warning: Could not remove worktree.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
console.log(` Status: completed`);
|
|
51
|
+
}
|
|
52
|
+
console.log(`\nStopped ${toStop.length} session(s).`);
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=stop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,UAAU,GAAG,aAAa,CAAC;AAOjC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,uBAAuB,CAAC;KACpC,QAAQ,CAAC,cAAc,EAAE,mCAAmC,CAAC;KAC7D,MAAM,CAAC,OAAO,EAAE,mBAAmB,EAAE,KAAK,CAAC;KAC3C,MAAM,CAAC,iBAAiB,EAAE,8BAA8B,EAAE,KAAK,CAAC;KAChE,MAAM,CAAC,KAAK,EAAE,SAA6B,EAAE,OAAoB,EAAE,EAAE;IACpE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;IAE7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG;QACxB,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;IAE7D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,8BAA8B,SAAS,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,MAAM,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,qBAAqB,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAE3D,wBAAwB;QACxB,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC;QAC7B,OAAO,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAC/B,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEhC,6BAA6B;QAC7B,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,oDAAoD;gBACpD,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;YACzF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,MAAM,cAAc,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,UAAU,SAmEnB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { access } from 'node:fs/promises';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { WebSocketBroadcaster } from '@claudetree/core';
|
|
6
|
+
const CONFIG_DIR = '.claudetree';
|
|
7
|
+
export const webCommand = new Command('web')
|
|
8
|
+
.description('Start web dashboard')
|
|
9
|
+
.option('-p, --port <port>', 'Web server port', '3000')
|
|
10
|
+
.option('--ws-port <port>', 'WebSocket server port', '3001')
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const configDir = join(cwd, CONFIG_DIR);
|
|
14
|
+
try {
|
|
15
|
+
await access(configDir);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
console.error('Error: claudetree not initialized. Run "claudetree init" first.');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const port = parseInt(options.port, 10);
|
|
22
|
+
const wsPort = parseInt(options.wsPort, 10);
|
|
23
|
+
console.log('Starting claudetree dashboard...\n');
|
|
24
|
+
// Start WebSocket server
|
|
25
|
+
const wss = new WebSocketBroadcaster(wsPort);
|
|
26
|
+
console.log(` WebSocket: ws://localhost:${wsPort}`);
|
|
27
|
+
// Start Next.js dev server
|
|
28
|
+
const webPath = join(cwd, 'node_modules', '@claudetree', 'web');
|
|
29
|
+
// For development, use the packages/web directly
|
|
30
|
+
const devWebPath = join(cwd, 'packages', 'web');
|
|
31
|
+
let webDir;
|
|
32
|
+
try {
|
|
33
|
+
await access(devWebPath);
|
|
34
|
+
webDir = devWebPath;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
webDir = webPath;
|
|
38
|
+
}
|
|
39
|
+
console.log(` Web UI: http://localhost:${port}`);
|
|
40
|
+
console.log('\nPress Ctrl+C to stop.\n');
|
|
41
|
+
const nextProcess = spawn('npx', ['next', 'dev', '-p', String(port)], {
|
|
42
|
+
cwd: webDir,
|
|
43
|
+
stdio: 'inherit',
|
|
44
|
+
env: {
|
|
45
|
+
...process.env,
|
|
46
|
+
CLAUDETREE_ROOT: cwd,
|
|
47
|
+
CLAUDETREE_WS_PORT: String(wsPort),
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
// Handle cleanup
|
|
51
|
+
const cleanup = () => {
|
|
52
|
+
console.log('\nShutting down...');
|
|
53
|
+
wss.close();
|
|
54
|
+
nextProcess.kill();
|
|
55
|
+
process.exit(0);
|
|
56
|
+
};
|
|
57
|
+
process.on('SIGINT', cleanup);
|
|
58
|
+
process.on('SIGTERM', cleanup);
|
|
59
|
+
nextProcess.on('error', (err) => {
|
|
60
|
+
console.error('Failed to start web server:', err.message);
|
|
61
|
+
wss.close();
|
|
62
|
+
process.exit(1);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import { initCommand } from './commands/init.js';
|
|
4
|
+
import { listCommand } from './commands/list.js';
|
|
5
|
+
import { startCommand } from './commands/start.js';
|
|
6
|
+
import { statusCommand } from './commands/status.js';
|
|
7
|
+
import { stopCommand } from './commands/stop.js';
|
|
8
|
+
import { webCommand } from './commands/web.js';
|
|
9
|
+
program
|
|
10
|
+
.name('claudetree')
|
|
11
|
+
.description('Git Worktree-based Claude Code multi-session manager')
|
|
12
|
+
.version('0.1.0');
|
|
13
|
+
program.addCommand(initCommand);
|
|
14
|
+
program.addCommand(listCommand);
|
|
15
|
+
program.addCommand(startCommand);
|
|
16
|
+
program.addCommand(statusCommand);
|
|
17
|
+
program.addCommand(stopCommand);
|
|
18
|
+
program.addCommand(webCommand);
|
|
19
|
+
program.parse();
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,sDAAsD,CAAC;KACnE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAE/B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@claudetree/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for claudetree - Manage Claude sessions with git worktrees",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"claudetree": "./dist/index.js",
|
|
8
|
+
"ct": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"claude",
|
|
15
|
+
"cli",
|
|
16
|
+
"git",
|
|
17
|
+
"worktree",
|
|
18
|
+
"ai",
|
|
19
|
+
"session"
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/notwonjang/claude-tree.git",
|
|
24
|
+
"directory": "packages/cli"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@claudetree/core": "0.1.0",
|
|
29
|
+
"@claudetree/shared": "0.1.0",
|
|
30
|
+
"commander": "^13.0.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^22.10.0",
|
|
34
|
+
"typescript": "^5.7.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"dev": "tsc --watch",
|
|
39
|
+
"start": "node dist/index.js"
|
|
40
|
+
}
|
|
41
|
+
}
|