bonzai-burn 1.0.5 โ 1.0.7
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/package.json +1 -1
- package/src/btrim.js +91 -22
package/package.json
CHANGED
package/src/btrim.js
CHANGED
|
@@ -1,24 +1,46 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execSync, spawn } from 'child_process';
|
|
3
|
+
import crypto from 'crypto';
|
|
3
4
|
import fs from 'fs';
|
|
4
|
-
import { join } from 'path';
|
|
5
|
+
import { join, dirname } from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
5
10
|
|
|
6
11
|
const BONZAI_DIR = 'bonzai';
|
|
7
12
|
const SPECS_FILE = 'specs.md';
|
|
13
|
+
const CONFIG_FILE = 'config.json';
|
|
14
|
+
|
|
15
|
+
// Template folder in the package
|
|
16
|
+
const TEMPLATE_DIR = join(__dirname, '..', 'bonzai');
|
|
17
|
+
|
|
18
|
+
function getTemplate(filename) {
|
|
19
|
+
const templatePath = join(TEMPLATE_DIR, filename);
|
|
20
|
+
if (fs.existsSync(templatePath)) {
|
|
21
|
+
return fs.readFileSync(templatePath, 'utf-8');
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
8
25
|
|
|
9
26
|
const DEFAULT_SPECS = `# Bonzai Specs
|
|
10
27
|
|
|
11
28
|
Define your cleanup requirements below. btrim will follow these instructions.
|
|
12
29
|
|
|
13
|
-
##
|
|
30
|
+
## Requirements:
|
|
14
31
|
- Remove unused imports
|
|
15
32
|
- Delete files matching pattern "*.tmp"
|
|
16
33
|
- Clean up console.log statements
|
|
17
34
|
`;
|
|
18
35
|
|
|
36
|
+
const DEFAULT_CONFIG = {
|
|
37
|
+
headlessClaude: true
|
|
38
|
+
};
|
|
39
|
+
|
|
19
40
|
function initializeBonzai() {
|
|
20
41
|
const bonzaiPath = join(process.cwd(), BONZAI_DIR);
|
|
21
42
|
const specsPath = join(bonzaiPath, SPECS_FILE);
|
|
43
|
+
const configPath = join(bonzaiPath, CONFIG_FILE);
|
|
22
44
|
|
|
23
45
|
// Check if bonzai/ folder exists
|
|
24
46
|
if (!fs.existsSync(bonzaiPath)) {
|
|
@@ -27,10 +49,18 @@ function initializeBonzai() {
|
|
|
27
49
|
console.log(`๐ Created ${BONZAI_DIR}/ folder`);
|
|
28
50
|
}
|
|
29
51
|
|
|
30
|
-
// Generate bonzai/specs.md
|
|
52
|
+
// Generate bonzai/specs.md from package template
|
|
31
53
|
if (!fs.existsSync(specsPath)) {
|
|
32
|
-
|
|
54
|
+
const specsContent = getTemplate(SPECS_FILE) || DEFAULT_SPECS;
|
|
55
|
+
fs.writeFileSync(specsPath, specsContent);
|
|
33
56
|
console.log(`๐ Created ${BONZAI_DIR}/${SPECS_FILE}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Generate bonzai/config.json from package template
|
|
60
|
+
if (!fs.existsSync(configPath)) {
|
|
61
|
+
const configContent = getTemplate(CONFIG_FILE) || JSON.stringify(DEFAULT_CONFIG, null, 2) + '\n';
|
|
62
|
+
fs.writeFileSync(configPath, configContent);
|
|
63
|
+
console.log(`โ๏ธ Created ${BONZAI_DIR}/${CONFIG_FILE}`);
|
|
34
64
|
console.log(`\nโ ๏ธ Please edit ${BONZAI_DIR}/${SPECS_FILE} to define your cleanup rules before running btrim.\n`);
|
|
35
65
|
process.exit(0);
|
|
36
66
|
}
|
|
@@ -39,6 +69,7 @@ function initializeBonzai() {
|
|
|
39
69
|
function ensureBonzaiDir() {
|
|
40
70
|
const bonzaiPath = join(process.cwd(), BONZAI_DIR);
|
|
41
71
|
const specsPath = join(bonzaiPath, SPECS_FILE);
|
|
72
|
+
const configPath = join(bonzaiPath, CONFIG_FILE);
|
|
42
73
|
|
|
43
74
|
if (!fs.existsSync(bonzaiPath)) {
|
|
44
75
|
fs.mkdirSync(bonzaiPath, { recursive: true });
|
|
@@ -46,11 +77,27 @@ function ensureBonzaiDir() {
|
|
|
46
77
|
}
|
|
47
78
|
|
|
48
79
|
if (!fs.existsSync(specsPath)) {
|
|
49
|
-
|
|
80
|
+
const specsContent = getTemplate(SPECS_FILE) || DEFAULT_SPECS;
|
|
81
|
+
fs.writeFileSync(specsPath, specsContent);
|
|
50
82
|
console.log(`๐ Created ${BONZAI_DIR}/${SPECS_FILE} - edit this file to define your cleanup specs\n`);
|
|
51
83
|
}
|
|
52
84
|
|
|
53
|
-
|
|
85
|
+
if (!fs.existsSync(configPath)) {
|
|
86
|
+
const configContent = getTemplate(CONFIG_FILE) || JSON.stringify(DEFAULT_CONFIG, null, 2) + '\n';
|
|
87
|
+
fs.writeFileSync(configPath, configContent);
|
|
88
|
+
console.log(`โ๏ธ Created ${BONZAI_DIR}/${CONFIG_FILE}\n`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { specsPath, configPath };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function loadConfig(configPath) {
|
|
95
|
+
try {
|
|
96
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
97
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(content) };
|
|
98
|
+
} catch {
|
|
99
|
+
return DEFAULT_CONFIG;
|
|
100
|
+
}
|
|
54
101
|
}
|
|
55
102
|
|
|
56
103
|
function loadSpecs(specsPath) {
|
|
@@ -66,7 +113,7 @@ function execVisible(command) {
|
|
|
66
113
|
execSync(command, { stdio: 'inherit' });
|
|
67
114
|
}
|
|
68
115
|
|
|
69
|
-
function executeClaude(requirements) {
|
|
116
|
+
function executeClaude(requirements, config) {
|
|
70
117
|
// Check if Claude CLI exists
|
|
71
118
|
try {
|
|
72
119
|
execSync('which claude', { encoding: 'utf-8', stdio: 'pipe' });
|
|
@@ -77,13 +124,40 @@ function executeClaude(requirements) {
|
|
|
77
124
|
);
|
|
78
125
|
}
|
|
79
126
|
|
|
80
|
-
|
|
127
|
+
const headless = config.headlessClaude !== false;
|
|
128
|
+
|
|
129
|
+
// Non-headless mode: run Claude interactively
|
|
130
|
+
if (!headless) {
|
|
131
|
+
console.log('๐ฅ๏ธ Running in interactive mode...\n');
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
const args = [
|
|
134
|
+
'--allowedTools', 'Read,Write,Edit,Bash',
|
|
135
|
+
'--permission-mode', 'dontAsk'
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
const claude = spawn('claude', args, {
|
|
139
|
+
stdio: 'inherit'
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
claude.on('close', (code) => {
|
|
143
|
+
if (code === 0) {
|
|
144
|
+
resolve();
|
|
145
|
+
} else {
|
|
146
|
+
reject(new Error(`Claude exited with code ${code}`));
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
claude.on('error', (err) => {
|
|
151
|
+
reject(new Error(`Failed to execute Claude: ${err.message}`));
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Headless mode with token tracking
|
|
81
157
|
let totalInputTokens = 0;
|
|
82
158
|
let totalOutputTokens = 0;
|
|
83
159
|
let lastToolName = '';
|
|
84
160
|
|
|
85
|
-
// Execute Claude with streaming JSON output
|
|
86
|
-
|
|
87
161
|
return new Promise((resolve, reject) => {
|
|
88
162
|
const args = [
|
|
89
163
|
'-p', requirements,
|
|
@@ -188,8 +262,9 @@ async function burn() {
|
|
|
188
262
|
initializeBonzai();
|
|
189
263
|
|
|
190
264
|
// Ensure bonzai directory and specs file exist
|
|
191
|
-
const specsPath = ensureBonzaiDir();
|
|
265
|
+
const { specsPath, configPath } = ensureBonzaiDir();
|
|
192
266
|
const specs = loadSpecs(specsPath);
|
|
267
|
+
const config = loadConfig(configPath);
|
|
193
268
|
|
|
194
269
|
// Check if Claude CLI exists and execute
|
|
195
270
|
console.log('๐ Checking for Claude Code CLI...');
|
|
@@ -218,16 +293,9 @@ async function burn() {
|
|
|
218
293
|
console.log(`โ Work saved on ${originalBranch}\n`);
|
|
219
294
|
}
|
|
220
295
|
|
|
221
|
-
//
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
// Delete existing burn branch if it exists
|
|
225
|
-
try {
|
|
226
|
-
exec(`git branch -D ${burnBranch}`);
|
|
227
|
-
console.log(`๐งน Cleaned up old ${burnBranch} branch\n`);
|
|
228
|
-
} catch {
|
|
229
|
-
// Branch doesn't exist, that's fine
|
|
230
|
-
}
|
|
296
|
+
// Generate unique branch name with short UUID
|
|
297
|
+
const shortId = crypto.randomUUID().slice(0, 8);
|
|
298
|
+
const burnBranch = `bonzai-burn-${shortId}`;
|
|
231
299
|
|
|
232
300
|
console.log(`๐ Starting from: ${originalBranch}`);
|
|
233
301
|
console.log(`๐ฟ Creating: ${burnBranch}\n`);
|
|
@@ -241,12 +309,13 @@ async function burn() {
|
|
|
241
309
|
exec(`git config bonzai.madeWipCommit ${madeWipCommit}`);
|
|
242
310
|
|
|
243
311
|
console.log(`๐ Specs loaded from: ${BONZAI_DIR}/${SPECS_FILE}`);
|
|
312
|
+
console.log(`โ๏ธ Headless mode: ${config.headlessClaude !== false ? 'on' : 'off'}`);
|
|
244
313
|
console.log('๐ฅ Running Bonzai burn...\n');
|
|
245
314
|
|
|
246
315
|
const startTime = Date.now();
|
|
247
316
|
|
|
248
317
|
// Execute Claude with specs from bonzai/specs.md
|
|
249
|
-
await executeClaude(specs);
|
|
318
|
+
await executeClaude(specs, config);
|
|
250
319
|
|
|
251
320
|
const duration = Math.round((Date.now() - startTime) / 1000);
|
|
252
321
|
|