bonzai-burn 1.0.6 → 1.0.8

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.
@@ -0,0 +1,4 @@
1
+ {
2
+ "headlessClaude": true,
3
+ "autoModeration": false
4
+ }
@@ -0,0 +1,8 @@
1
+ # Bonzai Specs
2
+
3
+ Define your cleanup requirements below. btrim will follow these instructions.
4
+
5
+ ## Requirements:
6
+ - Remove unused imports
7
+ - Delete files matching pattern "*.tmp"
8
+ - Clean up console.log statements
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bonzai-burn",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Git branch-based cleanup tool with btrim and brevert commands",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -19,6 +19,7 @@
19
19
  "node": ">=16.0.0"
20
20
  },
21
21
  "files": [
22
- "src"
22
+ "src",
23
+ "bonzai"
23
24
  ]
24
25
  }
package/src/btrim.js CHANGED
@@ -2,36 +2,40 @@
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';
9
14
 
10
- const DEFAULT_SPECS = `# Bonzai Specs
11
-
12
- Define your cleanup requirements below. btrim will follow these instructions.
13
-
14
- ## Example:
15
- - Remove unused imports
16
- - Delete files matching pattern "*.tmp"
17
- - Clean up console.log statements
18
- `;
15
+ // Template folder in the package
16
+ const TEMPLATE_DIR = join(__dirname, '..', 'bonzai');
19
17
 
20
18
  function initializeBonzai() {
21
19
  const bonzaiPath = join(process.cwd(), BONZAI_DIR);
22
20
  const specsPath = join(bonzaiPath, SPECS_FILE);
21
+ const configPath = join(bonzaiPath, CONFIG_FILE);
23
22
 
24
23
  // Check if bonzai/ folder exists
25
24
  if (!fs.existsSync(bonzaiPath)) {
26
- // Create bonzai/ folder
27
25
  fs.mkdirSync(bonzaiPath, { recursive: true });
28
26
  console.log(`šŸ“ Created ${BONZAI_DIR}/ folder`);
29
27
  }
30
28
 
31
- // Generate bonzai/specs.md with template
29
+ // Copy specs.md from package template
32
30
  if (!fs.existsSync(specsPath)) {
33
- fs.writeFileSync(specsPath, DEFAULT_SPECS);
31
+ fs.copyFileSync(join(TEMPLATE_DIR, SPECS_FILE), specsPath);
34
32
  console.log(`šŸ“ Created ${BONZAI_DIR}/${SPECS_FILE}`);
33
+ }
34
+
35
+ // Copy config.json from package template
36
+ if (!fs.existsSync(configPath)) {
37
+ fs.copyFileSync(join(TEMPLATE_DIR, CONFIG_FILE), configPath);
38
+ console.log(`āš™ļø Created ${BONZAI_DIR}/${CONFIG_FILE}`);
35
39
  console.log(`\nāš ļø Please edit ${BONZAI_DIR}/${SPECS_FILE} to define your cleanup rules before running btrim.\n`);
36
40
  process.exit(0);
37
41
  }
@@ -40,6 +44,7 @@ function initializeBonzai() {
40
44
  function ensureBonzaiDir() {
41
45
  const bonzaiPath = join(process.cwd(), BONZAI_DIR);
42
46
  const specsPath = join(bonzaiPath, SPECS_FILE);
47
+ const configPath = join(bonzaiPath, CONFIG_FILE);
43
48
 
44
49
  if (!fs.existsSync(bonzaiPath)) {
45
50
  fs.mkdirSync(bonzaiPath, { recursive: true });
@@ -47,11 +52,25 @@ function ensureBonzaiDir() {
47
52
  }
48
53
 
49
54
  if (!fs.existsSync(specsPath)) {
50
- fs.writeFileSync(specsPath, DEFAULT_SPECS);
55
+ fs.copyFileSync(join(TEMPLATE_DIR, SPECS_FILE), specsPath);
51
56
  console.log(`šŸ“ Created ${BONZAI_DIR}/${SPECS_FILE} - edit this file to define your cleanup specs\n`);
52
57
  }
53
58
 
54
- return specsPath;
59
+ if (!fs.existsSync(configPath)) {
60
+ fs.copyFileSync(join(TEMPLATE_DIR, CONFIG_FILE), configPath);
61
+ console.log(`āš™ļø Created ${BONZAI_DIR}/${CONFIG_FILE}\n`);
62
+ }
63
+
64
+ return { specsPath, configPath };
65
+ }
66
+
67
+ function loadConfig(configPath) {
68
+ try {
69
+ const content = fs.readFileSync(configPath, 'utf-8');
70
+ return JSON.parse(content);
71
+ } catch {
72
+ return { headlessClaude: true };
73
+ }
55
74
  }
56
75
 
57
76
  function loadSpecs(specsPath) {
@@ -67,7 +86,7 @@ function execVisible(command) {
67
86
  execSync(command, { stdio: 'inherit' });
68
87
  }
69
88
 
70
- function executeClaude(requirements) {
89
+ function executeClaude(requirements, config) {
71
90
  // Check if Claude CLI exists
72
91
  try {
73
92
  execSync('which claude', { encoding: 'utf-8', stdio: 'pipe' });
@@ -78,13 +97,40 @@ function executeClaude(requirements) {
78
97
  );
79
98
  }
80
99
 
81
- // Track token usage
100
+ const headless = config.headlessClaude !== false;
101
+
102
+ // Non-headless mode: run Claude interactively
103
+ if (!headless) {
104
+ console.log('šŸ–„ļø Running in interactive mode...\n');
105
+ return new Promise((resolve, reject) => {
106
+ const args = [
107
+ '--allowedTools', 'Read,Write,Edit,Bash',
108
+ '--permission-mode', 'dontAsk'
109
+ ];
110
+
111
+ const claude = spawn('claude', args, {
112
+ stdio: 'inherit'
113
+ });
114
+
115
+ claude.on('close', (code) => {
116
+ if (code === 0) {
117
+ resolve();
118
+ } else {
119
+ reject(new Error(`Claude exited with code ${code}`));
120
+ }
121
+ });
122
+
123
+ claude.on('error', (err) => {
124
+ reject(new Error(`Failed to execute Claude: ${err.message}`));
125
+ });
126
+ });
127
+ }
128
+
129
+ // Headless mode with token tracking
82
130
  let totalInputTokens = 0;
83
131
  let totalOutputTokens = 0;
84
132
  let lastToolName = '';
85
133
 
86
- // Execute Claude with streaming JSON output
87
-
88
134
  return new Promise((resolve, reject) => {
89
135
  const args = [
90
136
  '-p', requirements,
@@ -189,8 +235,9 @@ async function burn() {
189
235
  initializeBonzai();
190
236
 
191
237
  // Ensure bonzai directory and specs file exist
192
- const specsPath = ensureBonzaiDir();
238
+ const { specsPath, configPath } = ensureBonzaiDir();
193
239
  const specs = loadSpecs(specsPath);
240
+ const config = loadConfig(configPath);
194
241
 
195
242
  // Check if Claude CLI exists and execute
196
243
  console.log('šŸ” Checking for Claude Code CLI...');
@@ -235,12 +282,13 @@ async function burn() {
235
282
  exec(`git config bonzai.madeWipCommit ${madeWipCommit}`);
236
283
 
237
284
  console.log(`šŸ“‹ Specs loaded from: ${BONZAI_DIR}/${SPECS_FILE}`);
285
+ console.log(`āš™ļø Headless mode: ${config.headlessClaude !== false ? 'on' : 'off'}`);
238
286
  console.log('šŸ”„ Running Bonzai burn...\n');
239
287
 
240
288
  const startTime = Date.now();
241
289
 
242
290
  // Execute Claude with specs from bonzai/specs.md
243
- await executeClaude(specs);
291
+ await executeClaude(specs, config);
244
292
 
245
293
  const duration = Math.round((Date.now() - startTime) / 1000);
246
294