bonzai-burn 1.0.6 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/btrim.js +87 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bonzai-burn",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Git branch-based cleanup tool with btrim and brevert commands",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/btrim.js CHANGED
@@ -2,24 +2,45 @@
2
2
  import { execSync, spawn } from 'child_process';
3
3
  import crypto from 'crypto';
4
4
  import fs from 'fs';
5
- 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);
6
10
 
7
11
  const BONZAI_DIR = 'bonzai';
8
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
+ }
9
25
 
10
26
  const DEFAULT_SPECS = `# Bonzai Specs
11
27
 
12
28
  Define your cleanup requirements below. btrim will follow these instructions.
13
29
 
14
- ## Example:
30
+ ## Requirements:
15
31
  - Remove unused imports
16
32
  - Delete files matching pattern "*.tmp"
17
33
  - Clean up console.log statements
18
34
  `;
19
35
 
36
+ const DEFAULT_CONFIG = {
37
+ headlessClaude: true
38
+ };
39
+
20
40
  function initializeBonzai() {
21
41
  const bonzaiPath = join(process.cwd(), BONZAI_DIR);
22
42
  const specsPath = join(bonzaiPath, SPECS_FILE);
43
+ const configPath = join(bonzaiPath, CONFIG_FILE);
23
44
 
24
45
  // Check if bonzai/ folder exists
25
46
  if (!fs.existsSync(bonzaiPath)) {
@@ -28,10 +49,18 @@ function initializeBonzai() {
28
49
  console.log(`šŸ“ Created ${BONZAI_DIR}/ folder`);
29
50
  }
30
51
 
31
- // Generate bonzai/specs.md with template
52
+ // Generate bonzai/specs.md from package template
32
53
  if (!fs.existsSync(specsPath)) {
33
- fs.writeFileSync(specsPath, DEFAULT_SPECS);
54
+ const specsContent = getTemplate(SPECS_FILE) || DEFAULT_SPECS;
55
+ fs.writeFileSync(specsPath, specsContent);
34
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}`);
35
64
  console.log(`\nāš ļø Please edit ${BONZAI_DIR}/${SPECS_FILE} to define your cleanup rules before running btrim.\n`);
36
65
  process.exit(0);
37
66
  }
@@ -40,6 +69,7 @@ function initializeBonzai() {
40
69
  function ensureBonzaiDir() {
41
70
  const bonzaiPath = join(process.cwd(), BONZAI_DIR);
42
71
  const specsPath = join(bonzaiPath, SPECS_FILE);
72
+ const configPath = join(bonzaiPath, CONFIG_FILE);
43
73
 
44
74
  if (!fs.existsSync(bonzaiPath)) {
45
75
  fs.mkdirSync(bonzaiPath, { recursive: true });
@@ -47,11 +77,27 @@ function ensureBonzaiDir() {
47
77
  }
48
78
 
49
79
  if (!fs.existsSync(specsPath)) {
50
- fs.writeFileSync(specsPath, DEFAULT_SPECS);
80
+ const specsContent = getTemplate(SPECS_FILE) || DEFAULT_SPECS;
81
+ fs.writeFileSync(specsPath, specsContent);
51
82
  console.log(`šŸ“ Created ${BONZAI_DIR}/${SPECS_FILE} - edit this file to define your cleanup specs\n`);
52
83
  }
53
84
 
54
- return specsPath;
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
+ }
55
101
  }
56
102
 
57
103
  function loadSpecs(specsPath) {
@@ -67,7 +113,7 @@ function execVisible(command) {
67
113
  execSync(command, { stdio: 'inherit' });
68
114
  }
69
115
 
70
- function executeClaude(requirements) {
116
+ function executeClaude(requirements, config) {
71
117
  // Check if Claude CLI exists
72
118
  try {
73
119
  execSync('which claude', { encoding: 'utf-8', stdio: 'pipe' });
@@ -78,13 +124,40 @@ function executeClaude(requirements) {
78
124
  );
79
125
  }
80
126
 
81
- // Track token usage
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
82
157
  let totalInputTokens = 0;
83
158
  let totalOutputTokens = 0;
84
159
  let lastToolName = '';
85
160
 
86
- // Execute Claude with streaming JSON output
87
-
88
161
  return new Promise((resolve, reject) => {
89
162
  const args = [
90
163
  '-p', requirements,
@@ -189,8 +262,9 @@ async function burn() {
189
262
  initializeBonzai();
190
263
 
191
264
  // Ensure bonzai directory and specs file exist
192
- const specsPath = ensureBonzaiDir();
265
+ const { specsPath, configPath } = ensureBonzaiDir();
193
266
  const specs = loadSpecs(specsPath);
267
+ const config = loadConfig(configPath);
194
268
 
195
269
  // Check if Claude CLI exists and execute
196
270
  console.log('šŸ” Checking for Claude Code CLI...');
@@ -235,12 +309,13 @@ async function burn() {
235
309
  exec(`git config bonzai.madeWipCommit ${madeWipCommit}`);
236
310
 
237
311
  console.log(`šŸ“‹ Specs loaded from: ${BONZAI_DIR}/${SPECS_FILE}`);
312
+ console.log(`āš™ļø Headless mode: ${config.headlessClaude !== false ? 'on' : 'off'}`);
238
313
  console.log('šŸ”„ Running Bonzai burn...\n');
239
314
 
240
315
  const startTime = Date.now();
241
316
 
242
317
  // Execute Claude with specs from bonzai/specs.md
243
- await executeClaude(specs);
318
+ await executeClaude(specs, config);
244
319
 
245
320
  const duration = Math.round((Date.now() - startTime) / 1000);
246
321