@claudetree/cli 0.1.0 → 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/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # @claudetree/cli
2
+
3
+ **Run multiple Claude Code sessions in parallel** — each in its own isolated git worktree.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @claudetree/cli
9
+ # or
10
+ pnpm add -g @claudetree/cli
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # Initialize in your project
17
+ ct init
18
+
19
+ # Start working on a GitHub issue
20
+ ct start https://github.com/you/repo/issues/42
21
+
22
+ # Monitor progress
23
+ ct status
24
+
25
+ # Open web dashboard
26
+ ct web
27
+ ```
28
+
29
+ ## Commands
30
+
31
+ | Command | Description |
32
+ |---------|-------------|
33
+ | `ct init` | Initialize claudetree in your project |
34
+ | `ct start <issue>` | Create worktree and start Claude session |
35
+ | `ct status` | Show all session statuses |
36
+ | `ct stop [id]` | Stop a session |
37
+ | `ct doctor` | Check environment health |
38
+ | `ct demo` | Interactive demo (no tokens used) |
39
+ | `ct batch` | Process multiple issues in parallel |
40
+ | `ct web` | Start web dashboard |
41
+
42
+ ## Key Features
43
+
44
+ - **Multi-session**: Run unlimited Claude sessions in parallel
45
+ - **Isolated workspaces**: Each task gets its own git worktree
46
+ - **Fire and forget**: Pass a GitHub issue URL and Claude handles the rest
47
+ - **Token tracking**: See exactly how many tokens each session uses
48
+ - **Web dashboard**: Monitor all sessions in real-time
49
+
50
+ ## Links
51
+
52
+ - [GitHub Repository](https://github.com/wonjangcloud9/claude-tree)
53
+ - [Full Documentation](https://github.com/wonjangcloud9/claude-tree#readme)
54
+
55
+ ## License
56
+
57
+ MIT
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const batchCommand: Command;
3
+ //# sourceMappingURL=batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/commands/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsGpC,eAAO,MAAM,YAAY,SA0KrB,CAAC"}
@@ -0,0 +1,201 @@
1
+ import { Command } from 'commander';
2
+ import { join } from 'node:path';
3
+ import { access, readFile } from 'node:fs/promises';
4
+ import { spawn } from 'node:child_process';
5
+ import { GitHubAdapter, SlackNotifier } 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
+ async function startSession(issue, options) {
19
+ return new Promise((resolve, reject) => {
20
+ const args = ['start', issue];
21
+ if (options.template) {
22
+ args.push('--template', options.template);
23
+ }
24
+ const proc = spawn('claudetree', args, {
25
+ cwd: options.cwd,
26
+ stdio: 'inherit',
27
+ detached: true,
28
+ });
29
+ proc.unref();
30
+ // Don't wait for completion, just start
31
+ setTimeout(() => resolve(), 1000);
32
+ proc.on('error', reject);
33
+ });
34
+ }
35
+ function printStatus(items) {
36
+ console.clear();
37
+ console.log('\n=== Batch Progress ===\n');
38
+ for (const item of items) {
39
+ const icon = item.status === 'pending' ? '○' :
40
+ item.status === 'running' ? '◐' :
41
+ item.status === 'completed' ? '●' :
42
+ '✗';
43
+ const color = item.status === 'pending' ? '\x1b[90m' :
44
+ item.status === 'running' ? '\x1b[33m' :
45
+ item.status === 'completed' ? '\x1b[32m' :
46
+ '\x1b[31m';
47
+ console.log(`${color}${icon}\x1b[0m ${item.issue} - ${item.status}`);
48
+ if (item.error) {
49
+ console.log(` \x1b[31m${item.error}\x1b[0m`);
50
+ }
51
+ }
52
+ const completed = items.filter((i) => i.status === 'completed').length;
53
+ const failed = items.filter((i) => i.status === 'failed').length;
54
+ const running = items.filter((i) => i.status === 'running').length;
55
+ console.log(`\n[${completed}/${items.length}] completed, ${running} running, ${failed} failed`);
56
+ }
57
+ export const batchCommand = new Command('batch')
58
+ .description('Start multiple Claude sessions in parallel')
59
+ .argument('[issues...]', 'Issue numbers or GitHub URLs')
60
+ .option('-l, --label <label>', 'Filter GitHub issues by label')
61
+ .option('-n, --limit <number>', 'Maximum number of issues to process', '5')
62
+ .option('-T, --template <template>', 'Session template to use')
63
+ .option('-t, --token <token>', 'GitHub token (or use GITHUB_TOKEN env)')
64
+ .option('-f, --file <file>', 'Read issues from file (one per line)')
65
+ .option('-P, --parallel <number>', 'Number of parallel sessions', '3')
66
+ .option('--dry-run', 'Show what would be started without starting', false)
67
+ .action(async (issueArgs, options) => {
68
+ const cwd = process.cwd();
69
+ const config = await loadConfig(cwd);
70
+ if (!config) {
71
+ console.error('Error: claudetree not initialized. Run "claudetree init" first.');
72
+ process.exit(1);
73
+ }
74
+ const ghToken = options.token ?? process.env.GITHUB_TOKEN ?? config.github?.token;
75
+ let issues = [];
76
+ // Collect issues from arguments
77
+ if (issueArgs.length > 0) {
78
+ issues = issueArgs;
79
+ }
80
+ // Read from file if specified
81
+ if (options.file) {
82
+ try {
83
+ const content = await readFile(options.file, 'utf-8');
84
+ const fileIssues = content
85
+ .split('\n')
86
+ .map((line) => line.trim())
87
+ .filter((line) => line && !line.startsWith('#'));
88
+ issues.push(...fileIssues);
89
+ }
90
+ catch (err) {
91
+ console.error(`Error reading file: ${options.file}`);
92
+ process.exit(1);
93
+ }
94
+ }
95
+ // Fetch from GitHub by label
96
+ if (options.label) {
97
+ if (!ghToken || !config.github?.owner || !config.github?.repo) {
98
+ console.error('Error: GitHub token and repo config required for --label');
99
+ process.exit(1);
100
+ }
101
+ const ghAdapter = new GitHubAdapter(ghToken);
102
+ console.log(`Fetching issues with label: ${options.label}...`);
103
+ try {
104
+ const ghIssues = await ghAdapter.listIssues(config.github.owner, config.github.repo, { labels: options.label, state: 'open' });
105
+ const issueNumbers = ghIssues
106
+ .slice(0, parseInt(options.limit, 10))
107
+ .map((i) => String(i.number));
108
+ console.log(`Found ${ghIssues.length} issues, using first ${issueNumbers.length}`);
109
+ issues.push(...issueNumbers);
110
+ }
111
+ catch (err) {
112
+ console.error(`Error fetching issues: ${err instanceof Error ? err.message : err}`);
113
+ process.exit(1);
114
+ }
115
+ }
116
+ if (issues.length === 0) {
117
+ console.error('Error: No issues specified.');
118
+ console.log('\nUsage:');
119
+ console.log(' ct batch 101 102 103 # Issue numbers');
120
+ console.log(' ct batch --label bug # By GitHub label');
121
+ console.log(' ct batch --file issues.txt # From file');
122
+ process.exit(1);
123
+ }
124
+ // Deduplicate
125
+ issues = [...new Set(issues)];
126
+ // Apply limit
127
+ const limit = parseInt(options.limit, 10);
128
+ if (issues.length > limit) {
129
+ console.log(`Limiting to ${limit} issues (use --limit to change)`);
130
+ issues = issues.slice(0, limit);
131
+ }
132
+ console.log(`\nBatch: ${issues.length} issues`);
133
+ if (options.template) {
134
+ console.log(`Template: ${options.template}`);
135
+ }
136
+ // Dry run mode
137
+ if (options.dryRun) {
138
+ console.log('\n[Dry Run] Would start sessions for:');
139
+ issues.forEach((issue, i) => {
140
+ console.log(` ${i + 1}. ${issue}`);
141
+ });
142
+ return;
143
+ }
144
+ // Initialize batch items
145
+ const items = issues.map((issue) => ({
146
+ issue,
147
+ status: 'pending',
148
+ }));
149
+ const parallelLimit = parseInt(options.parallel, 10);
150
+ let runningCount = 0;
151
+ let currentIndex = 0;
152
+ const startNext = async () => {
153
+ while (runningCount < parallelLimit && currentIndex < items.length) {
154
+ const item = items[currentIndex];
155
+ if (!item)
156
+ break;
157
+ currentIndex++;
158
+ runningCount++;
159
+ item.status = 'running';
160
+ printStatus(items);
161
+ try {
162
+ await startSession(item.issue, {
163
+ template: options.template,
164
+ cwd,
165
+ });
166
+ item.status = 'completed';
167
+ }
168
+ catch (err) {
169
+ item.status = 'failed';
170
+ item.error = err instanceof Error ? err.message : 'Unknown error';
171
+ }
172
+ runningCount--;
173
+ printStatus(items);
174
+ }
175
+ };
176
+ // Start initial batch
177
+ const promises = [];
178
+ for (let i = 0; i < parallelLimit && i < items.length; i++) {
179
+ promises.push(startNext());
180
+ }
181
+ await Promise.all(promises);
182
+ // Final status
183
+ console.log('\n=== Batch Complete ===');
184
+ const completed = items.filter((i) => i.status === 'completed').length;
185
+ const failed = items.filter((i) => i.status === 'failed').length;
186
+ console.log(`Completed: ${completed}, Failed: ${failed}`);
187
+ // Send Slack notification
188
+ if (config.slack?.webhookUrl) {
189
+ const slack = new SlackNotifier(config.slack.webhookUrl);
190
+ await slack.notifyBatch(items.map((item) => ({
191
+ issue: item.issue,
192
+ status: item.status === 'completed' ? 'completed' : 'failed',
193
+ error: item.error,
194
+ })));
195
+ console.log('\nSlack notification sent.');
196
+ }
197
+ // Show session status command
198
+ console.log('\nView all sessions: claudetree status');
199
+ console.log('Open dashboard: claudetree web');
200
+ });
201
+ //# sourceMappingURL=batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/commands/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEhE,MAAM,UAAU,GAAG,aAAa,CAAC;AA8BjC,KAAK,UAAU,UAAU,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QACxD,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACzB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,KAAa,EACb,OAA2C;IAE3C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC9B,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,IAAI,EAAE;YACrC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,wCAAwC;QACxC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC;QAElC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,KAAkB;IACrC,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GACR,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACjC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACjC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;oBACnC,GAAG,CAAC;QAEN,MAAM,KAAK,GACT,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;gBACxC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;oBAC1C,UAAU,CAAC;QAEb,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,IAAI,WAAW,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;IACvE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IACjE,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IAEnE,OAAO,CAAC,GAAG,CAAC,MAAM,SAAS,IAAI,KAAK,CAAC,MAAM,gBAAgB,OAAO,aAAa,MAAM,SAAS,CAAC,CAAC;AAClG,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,4CAA4C,CAAC;KACzD,QAAQ,CAAC,aAAa,EAAE,8BAA8B,CAAC;KACvD,MAAM,CAAC,qBAAqB,EAAE,+BAA+B,CAAC;KAC9D,MAAM,CAAC,sBAAsB,EAAE,qCAAqC,EAAE,GAAG,CAAC;KAC1E,MAAM,CAAC,2BAA2B,EAAE,yBAAyB,CAAC;KAC9D,MAAM,CAAC,qBAAqB,EAAE,wCAAwC,CAAC;KACvE,MAAM,CAAC,mBAAmB,EAAE,sCAAsC,CAAC;KACnE,MAAM,CAAC,yBAAyB,EAAE,6BAA6B,EAAE,GAAG,CAAC;KACrE,MAAM,CAAC,WAAW,EAAE,6CAA6C,EAAE,KAAK,CAAC;KACzE,MAAM,CAAC,KAAK,EAAE,SAAmB,EAAE,OAAqB,EAAE,EAAE;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAClF,IAAI,MAAM,GAAa,EAAE,CAAC;IAE1B,gCAAgC;IAChC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,GAAG,SAAS,CAAC;IACrB,CAAC;IAED,8BAA8B;IAC9B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,UAAU,GAAG,OAAO;iBACvB,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;iBAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,uBAAuB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;YAC9D,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,+BAA+B,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC;QAE/D,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,UAAU,CACzC,MAAM,CAAC,MAAM,CAAC,KAAK,EACnB,MAAM,CAAC,MAAM,CAAC,IAAI,EAClB,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CACzC,CAAC;YAEF,MAAM,YAAY,GAAG,QAAQ;iBAC1B,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,KAA0B,EAAE,EAAE,CAAC,CAAC;iBAC1D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAEhC,OAAO,CAAC,GAAG,CAAC,SAAS,QAAQ,CAAC,MAAM,wBAAwB,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;YACnF,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,0BAA0B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,cAAc;IACd,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9B,cAAc;IACd,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,KAA0B,EAAE,EAAE,CAAC,CAAC;IAC/D,IAAI,MAAM,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,iCAAiC,CAAC,CAAC;QACnE,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,eAAe;IACf,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QACrD,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,yBAAyB;IACzB,MAAM,KAAK,GAAgB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAChD,KAAK;QACL,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC,CAAC;IAEJ,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,QAA6B,EAAE,EAAE,CAAC,CAAC;IAC1E,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;QAC3B,OAAO,YAAY,GAAG,aAAa,IAAI,YAAY,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACnE,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,IAAI;gBAAE,MAAM;YAEjB,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YACxB,WAAW,CAAC,KAAK,CAAC,CAAC;YAEnB,IAAI,CAAC;gBACH,MAAM,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE;oBAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,GAAG;iBACJ,CAAC,CAAC;gBACH,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;YAC5B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACvB,IAAI,CAAC,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACpE,CAAC;YAED,YAAY,EAAE,CAAC;YACf,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC;IAEF,sBAAsB;IACtB,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3D,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE5B,eAAe;IACf,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;IACvE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,cAAc,SAAS,aAAa,MAAM,EAAE,CAAC,CAAC;IAE1D,0BAA0B;IAC1B,IAAI,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,KAAK,CAAC,WAAW,CACrB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ;YAC5D,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC,CACJ,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC5C,CAAC;IAED,8BAA8B;IAC9B,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const demoCommand: Command;
3
+ //# sourceMappingURL=demo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/commands/demo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoNpC,eAAO,MAAM,WAAW,SASpB,CAAC"}
@@ -0,0 +1,173 @@
1
+ import { Command } from 'commander';
2
+ import * as readline from 'node:readline';
3
+ const COLORS = {
4
+ green: '\x1b[32m',
5
+ red: '\x1b[31m',
6
+ yellow: '\x1b[33m',
7
+ cyan: '\x1b[36m',
8
+ magenta: '\x1b[35m',
9
+ blue: '\x1b[34m',
10
+ dim: '\x1b[2m',
11
+ reset: '\x1b[0m',
12
+ bold: '\x1b[1m',
13
+ };
14
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
15
+ async function typeText(text, delay = 30) {
16
+ for (const char of text) {
17
+ process.stdout.write(char);
18
+ await sleep(delay);
19
+ }
20
+ console.log();
21
+ }
22
+ async function simulateProgress(steps, delayMs = 800) {
23
+ for (const step of steps) {
24
+ process.stdout.write(` ${COLORS.dim}○${COLORS.reset} ${step}`);
25
+ await sleep(delayMs);
26
+ process.stdout.write(`\r ${COLORS.green}✓${COLORS.reset} ${step}\n`);
27
+ }
28
+ }
29
+ function printBox(lines, color = COLORS.cyan) {
30
+ const maxLen = Math.max(...lines.map((l) => l.replace(/\x1b\[[0-9;]*m/g, '').length));
31
+ const border = '─'.repeat(maxLen + 2);
32
+ console.log(`${color}┌${border}┐${COLORS.reset}`);
33
+ for (const line of lines) {
34
+ const plainLen = line.replace(/\x1b\[[0-9;]*m/g, '').length;
35
+ const padding = ' '.repeat(maxLen - plainLen);
36
+ console.log(`${color}│${COLORS.reset} ${line}${padding} ${color}│${COLORS.reset}`);
37
+ }
38
+ console.log(`${color}└${border}┘${COLORS.reset}`);
39
+ }
40
+ async function waitForEnter(message = 'Press Enter to continue...') {
41
+ const rl = readline.createInterface({
42
+ input: process.stdin,
43
+ output: process.stdout,
44
+ });
45
+ return new Promise((resolve) => {
46
+ rl.question(`\n${COLORS.dim}${message}${COLORS.reset}`, () => {
47
+ rl.close();
48
+ resolve();
49
+ });
50
+ });
51
+ }
52
+ async function runDemo() {
53
+ console.clear();
54
+ console.log(`\n${COLORS.bold}${COLORS.cyan}🌳 claudetree Demo${COLORS.reset}\n`);
55
+ console.log(`${COLORS.dim}This is a simulated walkthrough - no tokens will be consumed.${COLORS.reset}\n`);
56
+ await waitForEnter();
57
+ // Step 1: Issue
58
+ console.clear();
59
+ console.log(`\n${COLORS.bold}Step 1: You have a GitHub issue${COLORS.reset}\n`);
60
+ printBox([
61
+ `${COLORS.bold}Issue #42: Fix login button not responding${COLORS.reset}`,
62
+ '',
63
+ `${COLORS.dim}When clicking the login button, nothing happens.${COLORS.reset}`,
64
+ `${COLORS.dim}Expected: Should redirect to /auth${COLORS.reset}`,
65
+ `${COLORS.dim}Actual: No response${COLORS.reset}`,
66
+ '',
67
+ `${COLORS.yellow}Labels: bug, high-priority${COLORS.reset}`,
68
+ ], COLORS.blue);
69
+ console.log(`\n${COLORS.dim}Normally you'd copy-paste this and manually implement...${COLORS.reset}`);
70
+ console.log(`${COLORS.green}With claudetree, just run one command:${COLORS.reset}\n`);
71
+ console.log(` ${COLORS.cyan}$ ct start https://github.com/you/repo/issues/42${COLORS.reset}\n`);
72
+ await waitForEnter();
73
+ // Step 2: Worktree creation
74
+ console.clear();
75
+ console.log(`\n${COLORS.bold}Step 2: claudetree creates an isolated workspace${COLORS.reset}\n`);
76
+ await simulateProgress([
77
+ 'Fetching issue #42 from GitHub...',
78
+ 'Creating branch: fix/issue-42-login-button',
79
+ 'Creating worktree: .worktrees/issue-42-fix-login/',
80
+ 'Initializing Claude session...',
81
+ ]);
82
+ console.log(`\n${COLORS.dim}Your main branch stays untouched.${COLORS.reset}`);
83
+ console.log(`${COLORS.dim}Claude works in a completely isolated directory.${COLORS.reset}\n`);
84
+ printBox([
85
+ `${COLORS.bold}Project Structure${COLORS.reset}`,
86
+ '',
87
+ `my-app/ ${COLORS.dim}← You work here${COLORS.reset}`,
88
+ `├── src/`,
89
+ `└── .worktrees/`,
90
+ ` └── issue-42-fix-login/ ${COLORS.cyan}← Claude works here${COLORS.reset}`,
91
+ ], COLORS.green);
92
+ await waitForEnter();
93
+ // Step 3: Claude working
94
+ console.clear();
95
+ console.log(`\n${COLORS.bold}Step 3: Claude works autonomously${COLORS.reset}\n`);
96
+ console.log(`${COLORS.cyan}Claude:${COLORS.reset} I'll analyze the login button issue...\n`);
97
+ await typeText(`${COLORS.dim}> Reading src/components/LoginButton.tsx...${COLORS.reset}`, 20);
98
+ await sleep(500);
99
+ await typeText(`${COLORS.dim}> Found the issue: onClick handler is missing await${COLORS.reset}`, 20);
100
+ await sleep(500);
101
+ await typeText(`${COLORS.dim}> Editing src/components/LoginButton.tsx...${COLORS.reset}`, 20);
102
+ await sleep(500);
103
+ await typeText(`${COLORS.dim}> Running npm test...${COLORS.reset}`, 20);
104
+ await sleep(800);
105
+ console.log(`\n${COLORS.green}✓ All tests passing${COLORS.reset}\n`);
106
+ await typeText(`${COLORS.dim}> Creating commit: "fix: add await to login handler"${COLORS.reset}`, 20);
107
+ await typeText(`${COLORS.dim}> Pushing to origin/fix/issue-42-login-button...${COLORS.reset}`, 20);
108
+ await typeText(`${COLORS.dim}> Creating pull request...${COLORS.reset}`, 20);
109
+ await waitForEnter();
110
+ // Step 4: Result
111
+ console.clear();
112
+ console.log(`\n${COLORS.bold}Step 4: PR is ready for review!${COLORS.reset}\n`);
113
+ printBox([
114
+ `${COLORS.bold}${COLORS.green}Pull Request #123${COLORS.reset}`,
115
+ '',
116
+ `${COLORS.bold}fix: add await to login handler${COLORS.reset}`,
117
+ '',
118
+ `Fixes #42`,
119
+ '',
120
+ `${COLORS.dim}Changes:${COLORS.reset}`,
121
+ ` ${COLORS.green}+ await${COLORS.reset} router.push('/auth')`,
122
+ ` ${COLORS.red}- ${COLORS.reset}router.push('/auth')`,
123
+ '',
124
+ `${COLORS.cyan}→ github.com/you/repo/pull/123${COLORS.reset}`,
125
+ ], COLORS.green);
126
+ console.log(`\n${COLORS.dim}Meanwhile, you were doing something else entirely.${COLORS.reset}`);
127
+ console.log(`${COLORS.dim}Now just review and merge!${COLORS.reset}\n`);
128
+ await waitForEnter();
129
+ // Step 5: Parallel
130
+ console.clear();
131
+ console.log(`\n${COLORS.bold}Bonus: Run multiple issues in parallel!${COLORS.reset}\n`);
132
+ console.log(` ${COLORS.cyan}$ ct start 42${COLORS.reset} ${COLORS.dim}# Fix login button${COLORS.reset}`);
133
+ console.log(` ${COLORS.cyan}$ ct start 43${COLORS.reset} ${COLORS.dim}# Add dark mode${COLORS.reset}`);
134
+ console.log(` ${COLORS.cyan}$ ct start 44${COLORS.reset} ${COLORS.dim}# Update deps${COLORS.reset}\n`);
135
+ console.log(`${COLORS.dim}Monitor all sessions:${COLORS.reset}\n`);
136
+ console.log(` ${COLORS.cyan}$ ct status${COLORS.reset} ${COLORS.dim}# CLI view${COLORS.reset}`);
137
+ console.log(` ${COLORS.cyan}$ ct web${COLORS.reset} ${COLORS.dim}# Web dashboard at localhost:3000${COLORS.reset}\n`);
138
+ printBox([
139
+ `${COLORS.bold}Session Status${COLORS.reset}`,
140
+ '',
141
+ `${COLORS.green}●${COLORS.reset} issue-42 ${COLORS.dim}running${COLORS.reset} fix login button`,
142
+ `${COLORS.green}●${COLORS.reset} issue-43 ${COLORS.dim}running${COLORS.reset} add dark mode`,
143
+ `${COLORS.yellow}●${COLORS.reset} issue-44 ${COLORS.dim}pending${COLORS.reset} update dependencies`,
144
+ ], COLORS.magenta);
145
+ await waitForEnter();
146
+ // Final
147
+ console.clear();
148
+ console.log(`\n${COLORS.bold}${COLORS.green}🎉 That's claudetree!${COLORS.reset}\n`);
149
+ console.log(`${COLORS.bold}Quick Start:${COLORS.reset}\n`);
150
+ console.log(` ${COLORS.cyan}1.${COLORS.reset} ct init ${COLORS.dim}# Initialize in your project${COLORS.reset}`);
151
+ console.log(` ${COLORS.cyan}2.${COLORS.reset} ct doctor ${COLORS.dim}# Check everything is ready${COLORS.reset}`);
152
+ console.log(` ${COLORS.cyan}3.${COLORS.reset} ct start <issue-url> ${COLORS.dim}# Start working on an issue${COLORS.reset}`);
153
+ console.log(` ${COLORS.cyan}4.${COLORS.reset} ct status ${COLORS.dim}# Monitor progress${COLORS.reset}\n`);
154
+ console.log(`${COLORS.bold}Key Commands:${COLORS.reset}\n`);
155
+ console.log(` ct start <issue> ${COLORS.dim}Create worktree + start Claude${COLORS.reset}`);
156
+ console.log(` ct status ${COLORS.dim}View all sessions${COLORS.reset}`);
157
+ console.log(` ct stop [id] ${COLORS.dim}Stop a session${COLORS.reset}`);
158
+ console.log(` ct web ${COLORS.dim}Open web dashboard${COLORS.reset}`);
159
+ console.log(` ct batch <label> ${COLORS.dim}Process multiple issues${COLORS.reset}\n`);
160
+ console.log(`${COLORS.dim}Learn more: https://github.com/wonjangcloud9/claude-tree${COLORS.reset}\n`);
161
+ }
162
+ export const demoCommand = new Command('demo')
163
+ .description('Interactive demo of claudetree workflow (no tokens used)')
164
+ .action(async () => {
165
+ try {
166
+ await runDemo();
167
+ }
168
+ catch {
169
+ // User interrupted (Ctrl+C)
170
+ console.log(`\n${COLORS.dim}Demo interrupted.${COLORS.reset}\n`);
171
+ }
172
+ });
173
+ //# sourceMappingURL=demo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo.js","sourceRoot":"","sources":["../../src/commands/demo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const doctorCommand: Command;
3
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoJpC,eAAO,MAAM,aAAa,SAiDtB,CAAC"}
@@ -0,0 +1,175 @@
1
+ import { Command } from 'commander';
2
+ import { execSync } from 'node:child_process';
3
+ import { access } from 'node:fs/promises';
4
+ import { join } from 'node:path';
5
+ const CONFIG_DIR = '.claudetree';
6
+ const CONFIG_FILE = 'config.json';
7
+ const COLORS = {
8
+ green: '\x1b[32m',
9
+ red: '\x1b[31m',
10
+ yellow: '\x1b[33m',
11
+ cyan: '\x1b[36m',
12
+ dim: '\x1b[2m',
13
+ reset: '\x1b[0m',
14
+ bold: '\x1b[1m',
15
+ };
16
+ const ICONS = {
17
+ pass: `${COLORS.green}✓${COLORS.reset}`,
18
+ fail: `${COLORS.red}✗${COLORS.reset}`,
19
+ warn: `${COLORS.yellow}!${COLORS.reset}`,
20
+ };
21
+ async function checkGitRepo() {
22
+ try {
23
+ execSync('git rev-parse --git-dir', { stdio: 'pipe' });
24
+ return { name: 'Git Repository', status: 'pass', message: 'Inside a git repository' };
25
+ }
26
+ catch {
27
+ return {
28
+ name: 'Git Repository',
29
+ status: 'fail',
30
+ message: 'Not a git repository',
31
+ fix: 'Run: git init',
32
+ };
33
+ }
34
+ }
35
+ async function checkClaudeCli() {
36
+ try {
37
+ const stdout = execSync('claude --version', { stdio: 'pipe', encoding: 'utf-8' });
38
+ const version = stdout.trim().split('\n')[0];
39
+ return { name: 'Claude CLI', status: 'pass', message: `Installed (${version})` };
40
+ }
41
+ catch {
42
+ return {
43
+ name: 'Claude CLI',
44
+ status: 'fail',
45
+ message: 'Claude CLI not found',
46
+ fix: 'Install: npm install -g @anthropic-ai/claude-code',
47
+ };
48
+ }
49
+ }
50
+ async function checkGhCli() {
51
+ try {
52
+ const stdout = execSync('gh --version', { stdio: 'pipe', encoding: 'utf-8' });
53
+ const version = stdout.trim().split('\n')[0];
54
+ return { name: 'GitHub CLI', status: 'pass', message: `Installed (${version})` };
55
+ }
56
+ catch {
57
+ return {
58
+ name: 'GitHub CLI',
59
+ status: 'warn',
60
+ message: 'GitHub CLI not found (optional)',
61
+ fix: 'Install: brew install gh',
62
+ };
63
+ }
64
+ }
65
+ async function checkGhAuth() {
66
+ try {
67
+ execSync('gh auth status', { stdio: 'pipe' });
68
+ return { name: 'GitHub Auth', status: 'pass', message: 'Authenticated' };
69
+ }
70
+ catch {
71
+ const token = process.env.GITHUB_TOKEN;
72
+ if (token) {
73
+ return { name: 'GitHub Auth', status: 'pass', message: 'Using GITHUB_TOKEN env' };
74
+ }
75
+ return {
76
+ name: 'GitHub Auth',
77
+ status: 'warn',
78
+ message: 'Not authenticated (needed for issue fetching)',
79
+ fix: 'Run: gh auth login OR export GITHUB_TOKEN=<token>',
80
+ };
81
+ }
82
+ }
83
+ async function checkClaudetreeInit() {
84
+ const cwd = process.cwd();
85
+ const configPath = join(cwd, CONFIG_DIR, CONFIG_FILE);
86
+ try {
87
+ await access(configPath);
88
+ return { name: 'claudetree Init', status: 'pass', message: 'Initialized (.claudetree/config.json exists)' };
89
+ }
90
+ catch {
91
+ return {
92
+ name: 'claudetree Init',
93
+ status: 'fail',
94
+ message: 'Not initialized in this directory',
95
+ fix: 'Run: ct init',
96
+ };
97
+ }
98
+ }
99
+ async function checkNodeVersion() {
100
+ const version = process.version;
101
+ const major = parseInt(version.slice(1).split('.')[0] ?? '0', 10);
102
+ if (major >= 18) {
103
+ return { name: 'Node.js', status: 'pass', message: `${version} (>= 18 required)` };
104
+ }
105
+ return {
106
+ name: 'Node.js',
107
+ status: 'fail',
108
+ message: `${version} (>= 18 required)`,
109
+ fix: 'Upgrade Node.js to v18 or higher',
110
+ };
111
+ }
112
+ async function checkAnthropicKey() {
113
+ const key = process.env.ANTHROPIC_API_KEY;
114
+ if (key) {
115
+ const masked = key.slice(0, 10) + '...' + key.slice(-4);
116
+ return { name: 'Anthropic API Key', status: 'pass', message: `Set (${masked})` };
117
+ }
118
+ return {
119
+ name: 'Anthropic API Key',
120
+ status: 'warn',
121
+ message: 'Not set (Claude CLI may use its own auth)',
122
+ fix: 'export ANTHROPIC_API_KEY=<your-key>',
123
+ };
124
+ }
125
+ function printResult(result) {
126
+ const icon = ICONS[result.status];
127
+ console.log(` ${icon} ${COLORS.bold}${result.name}${COLORS.reset}`);
128
+ console.log(` ${COLORS.dim}${result.message}${COLORS.reset}`);
129
+ if (result.fix && result.status !== 'pass') {
130
+ console.log(` ${COLORS.cyan}→ ${result.fix}${COLORS.reset}`);
131
+ }
132
+ }
133
+ export const doctorCommand = new Command('doctor')
134
+ .description('Check environment and dependencies for claudetree')
135
+ .option('-q, --quiet', 'Only show failures and warnings', false)
136
+ .action(async (options) => {
137
+ console.log(`\n${COLORS.bold}claudetree doctor${COLORS.reset}\n`);
138
+ console.log(`${COLORS.dim}Checking your environment...${COLORS.reset}\n`);
139
+ const checks = [
140
+ checkNodeVersion,
141
+ checkGitRepo,
142
+ checkClaudeCli,
143
+ checkGhCli,
144
+ checkGhAuth,
145
+ checkAnthropicKey,
146
+ checkClaudetreeInit,
147
+ ];
148
+ const results = [];
149
+ for (const check of checks) {
150
+ const result = await check();
151
+ results.push(result);
152
+ if (!options.quiet || result.status !== 'pass') {
153
+ printResult(result);
154
+ console.log();
155
+ }
156
+ }
157
+ const fails = results.filter((r) => r.status === 'fail');
158
+ const warns = results.filter((r) => r.status === 'warn');
159
+ const passes = results.filter((r) => r.status === 'pass');
160
+ console.log(`${COLORS.dim}${'─'.repeat(40)}${COLORS.reset}`);
161
+ console.log(`\n ${COLORS.green}${passes.length} passed${COLORS.reset} ` +
162
+ `${warns.length > 0 ? `${COLORS.yellow}${warns.length} warnings${COLORS.reset} ` : ''}` +
163
+ `${fails.length > 0 ? `${COLORS.red}${fails.length} failed${COLORS.reset}` : ''}`);
164
+ if (fails.length === 0) {
165
+ console.log(`\n ${COLORS.green}${COLORS.bold}✓ Ready to use claudetree!${COLORS.reset}\n`);
166
+ if (warns.length > 0) {
167
+ console.log(` ${COLORS.dim}Fix warnings above for full functionality.${COLORS.reset}\n`);
168
+ }
169
+ }
170
+ else {
171
+ console.log(`\n ${COLORS.red}${COLORS.bold}✗ Fix the issues above before using claudetree.${COLORS.reset}\n`);
172
+ process.exit(1);
173
+ }
174
+ });
175
+ //# sourceMappingURL=doctor.js.map