bunosh 0.4.13 β†’ 0.5.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/README.md CHANGED
@@ -1,87 +1,33 @@
1
- # 🍲 Bunosh
1
+ # Bunosh
2
2
 
3
3
  <p align="center">
4
4
  <img src="assets/logo.png" alt="Logo" width="150">
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
- <strong>Your exceptional task runner</strong>
8
+ A task runner for JavaScript. Transform functions into CLI commands.
9
9
  </p>
10
10
 
11
- <p align="center">
12
- Transform JavaScript functions into CLI commands.
13
- </p>
14
-
15
- ---
16
-
17
- ## What is Bunosh?
18
-
19
- Bunosh is a modern task runner that turns your JavaScript functions into CLI commands instantly. No configuration, no boilerplate - just write functions and run them from the terminal.
20
-
21
11
  > *Named after **banosh**, a traditional Ukrainian dish from cornmeal cooked with various ingredients*
22
12
 
13
+ ---
23
14
 
24
- ## Hello World
25
-
26
- No nore words, just code:
15
+ ## Quick Example
27
16
 
28
17
  ```js
29
- // this is a command in Bunoshfile.js
30
- // bunosh hello:world
31
-
32
- export async function helloWorld(name = 'person') {
33
- name = await ask("What's your name?", name);
34
- say(`πŸ‘‹ Hello, ${name}!`);
35
- const city = await ask('Which city do you live in?')
36
- const result = await fetch(`https://wttr.in/${city}?format=3`)
37
- say(`Weather in your city ${result.output}`)
38
-
39
- const toCleanup = await ask('Do you want me to cleanup tmp for you?', true);
40
-
41
- if (!toCleanup) {
42
- say('Bye, then!');
43
- return;
44
- }
45
-
46
- await shell`rm -rf ${require('os').tmpdir()}/*`;
47
- say('🧹 Cleaned up! Have a great day!');
18
+ // Bunoshfile.js β€” run with: bunosh deploy
19
+ export async function deploy(env = 'production') {
20
+ await exec`npm run build`.env({ NODE_ENV: env });
21
+ await exec`rsync -az dist/ server:/var/www/`;
22
+ say(`Deployed to ${env}`);
48
23
  }
49
- ````
50
-
51
- ## Why Choose Bunosh?
52
-
53
- | Comparison | 🐚 Bash Scripts | πŸ“¦ npm scripts | πŸ› οΈ Task Runners | 🍲 **Bunosh** |
54
- |------------|-----------------|----------------|------------------------------|----------------|
55
- | **Syntax** | bash/zsh | Simple commands | Custom DSL | βœ… JavaScript |
56
- | **Cross-platform** | No | Yes | Yes | βœ… Yes |
57
- | **Ecosystem** | CLI tools | npm packages | Plugin dependent | βœ… Bash + npm |
58
- | **Composability** | Commands | Separate scripts | Task dependencies | βœ… Import any JS code |
59
-
60
- ** Migrate to Bunosh**
61
-
62
- - [Migrating from Bash Scripts](docs/bash-migration-guide.md)
63
- - [Migrating from Node.js Scripts](docs/nodejs-migration-guide.md)
64
-
65
- Hint: Provide this link to a coding agent and make it convert scripts into Bunosh!
66
-
67
- ## TOC
68
-
69
- - [Installation](#installation)
70
- - [MCP Integration](#mcp-integration)
71
- - [Quickstart](#quickstart)
72
- - [Commands](#commands)
73
- - [Tasks](#tasks)
74
- - [Input/Output](#inputoutput)
75
- - [Task Control](#task-control)
76
- - [AI Integration](#ai-integration)
77
- - [MCP](#mcp)
78
- - [Examples](#examples)
24
+ ```
79
25
 
80
26
  ## Installation
81
27
 
82
- ### Option 1: Single Executable (Recommended)
28
+ ### Single Executable (Recommended)
83
29
 
84
- Download the standalone executable - no Node.js or Bun required:
30
+ Download the standalone executable β€” no Node.js or Bun required:
85
31
 
86
32
  **macOS:**
87
33
  ```bash
@@ -102,7 +48,7 @@ Expand-Archive -Path "bunosh.zip" -DestinationPath .
102
48
  Move-Item "bunosh-windows-x64.exe" "bunosh.exe"
103
49
  ```
104
50
 
105
- ### Option 2: Package Managers
51
+ ### Package Managers
106
52
 
107
53
  ```bash
108
54
  # Using Bun
@@ -119,7 +65,7 @@ npm install -g bunosh
119
65
  bunosh init
120
66
  ```
121
67
 
122
- 2. **Write your first command:**
68
+ 2. **Write a command:**
123
69
  ```javascript
124
70
  // Bunoshfile.js
125
71
  const { exec, say } = global.bunosh;
@@ -128,63 +74,51 @@ const { exec, say } = global.bunosh;
128
74
  * Builds the project for production
129
75
  */
130
76
  export async function build(env = 'production') {
131
- say(`πŸ”¨ Building for ${env}...`);
132
77
  await exec`npm run build`.env({ NODE_ENV: env });
133
- say('βœ… Build complete!');
78
+ say('Build complete');
134
79
  }
135
80
  ```
136
81
 
82
+ 3. **Run it:**
83
+ ```bash
84
+ bunosh build
85
+ bunosh build staging
86
+ ```
87
+
137
88
  ## Commands
138
89
 
139
90
  By default, Bunosh loads commands from `Bunoshfile.js` in the current directory.
140
91
 
141
92
  ```
142
- # reads Bunoshfile form cwd and runs hello()
143
93
  bunosh hello
144
94
  ```
145
95
 
146
- You can specify custom configuration file using CLI option:
96
+ You can specify a custom file using `--bunoshfile` or the `BUNOSHFILE` environment variable:
147
97
 
148
98
  ```bash
149
- # Load commands from a different file
150
99
  bunosh --bunoshfile Bunoshfile.dev.js hello
151
- ```
152
-
153
- or via environment variable:
154
-
155
- ```bash
156
- # Set default bunoshfile for session
157
- export BUNOSHFILE=Bunoshfile.dev.js
158
- bunosh hello # Uses Bunoshfile.dev.js
159
-
160
- # One-time usage
161
100
  BUNOSHFILE=Bunoshfile.prod.js bunosh deploy
162
101
  ```
163
102
 
164
-
165
103
  ### Creating Commands
166
104
 
167
105
  Every exported function in `Bunoshfile.js` becomes a CLI command:
168
106
 
169
107
  ```javascript
170
- // Simple command
171
108
  export function hello() {
172
109
  console.log('Hello, World!');
173
110
  }
174
111
 
175
- // Command with parameters
176
112
  export function greet(name = 'friend') {
177
113
  console.log(`Hello, ${name}!`);
178
114
  }
179
115
 
180
- // Command with options
181
116
  export function deploy(env = 'staging', options = { force: false, verbose: false }) {
182
117
  if (options.verbose) console.log('Verbose mode enabled');
183
118
  console.log(`Deploying to ${env}${options.force ? ' (forced)' : ''}`);
184
119
  }
185
120
  ```
186
121
 
187
- **CLI Usage:**
188
122
  ```bash
189
123
  bunosh hello
190
124
  bunosh greet John
@@ -193,7 +127,7 @@ bunosh deploy production --force --verbose
193
127
 
194
128
  ### Arguments and Options
195
129
 
196
- Bunosh automatically maps function parameters to CLI arguments:
130
+ Bunosh maps function parameters to CLI arguments automatically:
197
131
 
198
132
  ```javascript
199
133
  /**
@@ -212,7 +146,6 @@ export async function feature(name, base = 'main', options = { push: false }) {
212
146
  }
213
147
  ```
214
148
 
215
- **Generated CLI:**
216
149
  ```bash
217
150
  bunosh feature my-feature # Creates from main
218
151
  bunosh feature my-feature develop # Creates from develop
@@ -230,211 +163,56 @@ Functions are automatically converted to kebab-case commands:
230
163
  | `npmInstall` | `bunosh npm:install` |
231
164
  | `buildAndDeploy` | `bunosh build:and-deploy` |
232
165
 
233
-
234
-
235
-
236
166
  ### Project Namespaces
237
167
 
238
- Organize your project tasks by creating multiple Bunoshfiles with namespaces. This helps keep large projects organized and separates concerns.
168
+ Organize tasks by creating multiple Bunoshfiles. Files named `Bunoshfile.<namespace>.js` register commands under that namespace:
239
169
 
240
- **Create namespace files:**
241
170
  ```bash
242
- # Main tasks (no namespace)
243
- Bunoshfile.js
244
-
245
- # Development tasks
246
- Bunoshfile.dev.js
247
-
248
- # API tasks
249
- Bunoshfile.api.js
250
-
251
- # Database tasks
252
- Bunoshfile.db.js
171
+ Bunoshfile.js # bunosh build, bunosh test
172
+ Bunoshfile.dev.js # bunosh dev:start, bunosh dev:debug
173
+ Bunoshfile.api.js # bunosh api:deploy, bunosh api:test
253
174
  ```
254
175
 
255
- **Example structure:**
256
- ```javascript
257
- // Bunoshfile.js - Core project tasks
258
- export function build() {
259
- console.log('Building project...');
260
- }
261
-
262
- export function test() {
263
- console.log('Running tests...');
264
- }
265
-
266
- // Bunoshfile.dev.js - Development tasks
267
- export function start() {
268
- console.log('Starting dev server...');
269
- }
176
+ ## Comparison
270
177
 
271
- export function debug() {
272
- console.log('Debugging...');
273
- }
274
-
275
- // Bunoshfile.api.js - API specific tasks
276
- export function deploy() {
277
- console.log('Deploying API...');
278
- }
279
-
280
- export function test() {
281
- console.log('Running API tests...');
282
- }
283
- ```
284
-
285
- **Usage:**
286
- ```bash
287
- # Core tasks (no namespace)
288
- bunosh build
289
- bunosh test
290
-
291
- # Namespaced tasks
292
- bunosh dev:start
293
- bunosh dev:debug
294
- bunosh api:deploy
295
- bunosh api:test
296
- ```
297
-
298
- ## MCP
299
-
300
- Bunosh supports the **Model Context Protocol (MCP)**, allowing you to expose your Bunoshfile commands as tools for AI assistants like Claude Desktop, Cursor, and other MCP-compatible applications.
301
-
302
- ### Quick Start
303
-
304
- 1. **Start MCP server** in your project directory:
305
- ```bash
306
- # Uses Bunoshfile.js from current directory
307
- bunosh -mcp
308
-
309
- # Or with custom Bunoshfile
310
- bunosh --bunoshfile Bunoshfile.dev.js -mcp
311
- ```
312
-
313
- 2. **Configure your AI assistant** to use Bunosh as an MCP server (see instructions below).
314
-
315
- <details>
316
- <summary>Claude Desktop Setup</summary>
317
-
318
- 1. **Edit Claude Desktop configuration** (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
319
-
320
- ```json
321
- {
322
- "mcpServers": {
323
- "bunosh": {
324
- "command": "bunosh",
325
- "args": ["-mcp"],
326
- "cwd": "/path/to/your/project"
327
- }
328
- }
329
- }
330
- ```
331
-
332
- 2. **Restart Claude Desktop** - your Bunosh commands will now be available as tools.
333
-
334
- 3. **Use your commands** in Claude:
335
- - "Build my project with bunosh"
336
- - "Run tests using bunosh"
337
- - "Deploy to staging with bunosh"
338
-
339
- **Multiple Projects:**
340
- ```json
341
- {
342
- "mcpServers": {
343
- "my-app": {
344
- "command": "bunosh",
345
- "args": ["-mcp"],
346
- "cwd": "/path/to/my-app"
347
- },
348
- "my-api": {
349
- "command": "bunosh",
350
- "args": ["-mcp"],
351
- "cwd": "/path/to/my-api"
352
- }
353
- }
354
- }
355
- ```
356
-
357
- </details>
358
-
359
- <details>
360
- <summary>Cursor Setup</summary>
361
-
362
- 1. **Open Cursor settings** (`Cmd/Ctrl + ,`)
363
-
364
- 2. **Navigate to** `Extensions` β†’ `MCP Servers`
365
-
366
- 3. **Add new MCP server:**
367
- - **Name**: `bunosh`
368
- - **Command**: `bunosh`
369
- - **Arguments**: `-mcp`
370
- - **Working Directory**: `/path/to/your/project`
371
-
372
- 4. **Save and restart** Cursor
373
-
374
- 5. **Your Bunosh commands** will now appear in the AI chat sidebar as available tools.
375
-
376
- </details>
377
-
378
- <details>
379
- <summary>Cline Setup (VS Code Extension)</summary>
380
-
381
- 1. **Install Cline** extension from VS Code marketplace
382
-
383
- 2. **Open Cline settings** (click the gear icon in Cline panel)
384
-
385
- 3. **Add MCP server** under "MCP Servers" section:
386
- ```json
387
- {
388
- "name": "bunosh",
389
- "command": "bunosh",
390
- "args": ["-mcp"],
391
- "cwd": "/path/to/your/project"
392
- }
393
- ```
394
-
395
- 4. **Save and reload** the VS Code window
396
-
397
- 5. **Your commands** will be available in Cline's tool selection
398
-
399
- </details>
178
+ | | Bash Scripts | npm scripts | Task Runners | **Bunosh** |
179
+ |--|--|--|--|--|
180
+ | **Syntax** | bash/zsh | Simple commands | Custom DSL | JavaScript |
181
+ | **Cross-platform** | No | Yes | Yes | Yes |
182
+ | **Ecosystem** | CLI tools | npm packages | Plugin dependent | Bash + npm |
183
+ | **Composability** | Commands | Separate scripts | Task dependencies | Import any JS code |
400
184
 
401
185
  ## Tasks
402
186
 
403
- Bunosh provides built-in tasks which are available via `global.bunosh`:
187
+ Built-in tasks are available via `global.bunosh`:
404
188
 
405
189
  ```javascript
406
190
  const { exec, shell, fetch, writeToFile, copyFile, task } = global.bunosh;
407
191
  ```
408
192
 
409
- > We use global variables instead of imports to ensure you can use it with bunosh single-executable on any platform.
410
-
193
+ > Global variables are used instead of imports so bunosh works with the single-executable on any platform.
411
194
 
412
195
  * Async tasks: `exec`, `shell`, `fetch`
413
196
  * Sync tasks: `writeToFile`, `copyFile`
414
197
  * Task wrapper: `task`
415
198
 
416
- Each executed task returns `TaskResult` object which can be analyzed and used in next steps:
199
+ Each task returns a `TaskResult` object:
417
200
 
418
201
  ```js
419
202
  const result = await shell`echo "Hello"`;
420
- console.log(result.status); // 'success', 'fail', or 'warning'
421
- console.log(result.output); // Command output or result data
422
- console.log(result.hasFailed); // true if status is 'fail'
203
+ console.log(result.status); // 'success', 'fail', or 'warning'
204
+ console.log(result.output); // Command output
205
+ console.log(result.hasFailed); // true if status is 'fail'
423
206
  console.log(result.hasSucceeded); // true if status is 'success'
424
- console.log(result.hasWarning); // true if status is 'warning'
425
207
 
426
- // Get structured JSON data from any task (async method)
427
- const json = await result.json();
208
+ const json = await result.json(); // Structured data
428
209
  ```
429
210
 
430
- Now let's look into other tasks:
431
-
432
- #### `task`
211
+ ### `task`
433
212
 
434
- General method that transforms a function into a task. Adds it to tasks registry and prints task information:
213
+ Wraps a function into a named task with tracking and output:
435
214
 
436
215
  ```js
437
- // register operation as a task
438
216
  const result = task('Fetch Readme file', () => {
439
217
  const content = fs.readFileSync('README.md', 'utf8');
440
218
  console.log(content);
@@ -442,17 +220,15 @@ const result = task('Fetch Readme file', () => {
442
220
  });
443
221
  ```
444
222
 
445
- If a another task is executed inside a task function, its description will be appended to all child tasks.
223
+ If another task runs inside a task function, its description is appended to child tasks.
446
224
 
447
- #### `exec`
225
+ ### `exec`
448
226
 
449
- Run single command using [child process `spawn`](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options)
227
+ Runs a command using [child process `spawn`](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options):
450
228
 
451
229
  ```javascript
452
- // Complex commands with pipes and streaming output
453
230
  await exec`npm install --verbose`;
454
231
  await exec`docker build . | tee build.log`;
455
- await exec`find . -name "*.js" | grep -v node_modules | wc -l`;
456
232
 
457
233
  // With environment variables
458
234
  await exec`echo $NODE_ENV`.env({ NODE_ENV: 'production' });
@@ -460,75 +236,58 @@ await exec`echo $NODE_ENV`.env({ NODE_ENV: 'production' });
460
236
  // In specific directory
461
237
  await exec`npm install`.cwd('/tmp/project');
462
238
 
463
- // Get structured output with stdout, stderr, exit code and lines
239
+ // Structured output
464
240
  const result = await exec`git status --porcelain`;
465
241
  const data = await result.json();
466
242
  // Returns: { stdout: "...", stderr: "...", exitCode: 0, lines: [...] }
467
243
  ```
468
244
 
469
- By default task prints live line-by-line output from stdout and stderr. To disable output, use `silent` method:
245
+ By default tasks print live output from stdout and stderr. To disable, use `silent`:
470
246
 
471
247
  ```javascript
472
-
473
- // disable printing output
474
248
  await task.silent(() => exec`npm install`);
475
249
 
476
- // disable output for all commands
477
- await task.silence();
250
+ // Or disable for all commands
251
+ task.silence();
478
252
  ```
479
253
 
480
- See more [#silent](#silent)
254
+ ### `shell`
481
255
 
482
- #### `shell` - Fast Native Execution
483
-
484
- Optimized for simple, fast commands when running under Bun:
256
+ Optimized for simple commands when running under Bun:
485
257
 
486
258
  ```javascript
487
- // Simple, fast commands
488
259
  await shell`pwd`;
489
260
  await shell`ls -la`;
490
261
  await shell`cat package.json`;
491
262
 
492
- // Get structured output with stdout, stderr, exit code and lines
493
263
  const result = await shell`ls -la`;
494
264
  const data = await result.json();
495
- // Returns: { stdout: "...", stderr: "...", exitCode: 0, lines: [...] }
496
265
  ```
497
266
 
498
- For more details see [bun shell](https://bun.sh/docs/runtime/shell) reference
499
-
500
- `shell` vs `exec`
267
+ For details see the [Bun shell](https://bun.sh/docs/runtime/shell) reference.
501
268
 
502
- | Command | Best For | Use Cases | Implementation | Compatibility |
503
- |---------|----------|-----------|----------------|---------------|
504
- | `exec` | Single command execution | single command | spawn process | NodeJS + Bun but platform dependent |
505
- | `shell` | Multiple cross-platform shell commands | exec + `pwd`, `ls`, `echo`, `cat`, basic file ops | bun shell | Bun only but Cross-platform |
269
+ **`shell` vs `exec`:**
506
270
 
507
- shell prints output from stdout and stderr. To disable output, [make tasks silent](#silent):
271
+ | Command | Best For | Implementation | Compatibility |
272
+ |---------|----------|----------------|---------------|
273
+ | `exec` | Single command execution | spawn process | Node.js + Bun, platform dependent |
274
+ | `shell` | Cross-platform shell commands | Bun shell | Bun only, cross-platform |
508
275
 
509
- ###$ `fetch`
276
+ ### `fetch`
510
277
 
511
- `fetch` task wraps fetch:
278
+ Wraps the fetch API as a task:
512
279
 
513
280
  ```javascript
514
- /**
515
- * Check service health
516
- */
517
281
  export async function healthCheck(url) {
518
282
  const response = await fetch(url);
519
283
 
520
284
  if (response.ok) {
521
285
  const data = await response.json();
522
- say(`βœ… Service healthy: ${data.status}`);
286
+ say(`Service healthy: ${data.status}`);
523
287
  } else {
524
- yell(`❌ Service down: ${response.status}`);
288
+ yell(`Service down: ${response.status}`);
525
289
  }
526
290
  }
527
-
528
- // Get JSON response data directly
529
- const apiResponse = await fetch('https://api.example.com/data');
530
- const jsonData = await apiResponse.json();
531
- // Calls response.json() method internally
532
291
  ```
533
292
 
534
293
  ### File Operations
@@ -536,9 +295,6 @@ const jsonData = await apiResponse.json();
536
295
  Template-based file writing and copying:
537
296
 
538
297
  ```javascript
539
- /**
540
- * Generate configuration file
541
- */
542
298
  export function generatePage(name, description = '') {
543
299
  writeToFile('index.mdx', (line) => {
544
300
  line`name": "${name}",`;
@@ -548,103 +304,62 @@ export function generatePage(name, description = '') {
548
304
  line`---`;
549
305
  });
550
306
 
551
- say('πŸ“ Page created');
307
+ copyFile('template.env', '.env');
552
308
  }
553
-
554
- // Copy files
555
- copyFile('template.env', '.env');
556
309
  ```
557
310
 
558
-
559
311
  ## Input/Output
560
312
 
561
- ### `say` - Normal Output
313
+ ### `say`
562
314
 
563
- Standard output with visual indicator:
315
+ Standard output:
564
316
 
565
317
  ```javascript
566
318
  say('Building project...');
567
- say('πŸ“¦ Dependencies installed');
568
319
  say(`Found ${count} files to process`);
569
320
  ```
570
321
 
571
- ### `ask` - User Input
322
+ ### `ask`
572
323
 
573
- Flexible user input with smart parameter detection:
324
+ User input with smart parameter detection:
574
325
 
575
326
  ```javascript
576
- // Text input with default
577
327
  const name = await ask('Project name:', 'my-app');
578
-
579
- // Boolean confirmation (auto-detects)
580
328
  const proceed = await ask('Continue?', true);
581
-
582
- // Single selection (auto-detects from array)
583
329
  const env = await ask('Select environment:', ['dev', 'staging', 'prod']);
584
-
585
- // Multiple selection
586
- const features = await ask('Select features:',
587
- ['TypeScript', 'ESLint', 'Tests'],
588
- { multiple: true }
589
- );
590
-
591
- // Password input
330
+ const features = await ask('Select features:', ['TypeScript', 'ESLint', 'Tests'], { multiple: true });
592
331
  const password = await ask('Enter password:', { type: 'password' });
593
-
594
- // Multiline editor input
595
332
  const description = await ask('Enter description:', { editor: true });
596
333
  ```
597
334
 
598
- | Parameter/Option | Type | Description | Example |
599
- |------------------|------|-------------|---------|
600
- | **Smart Detection** | | |
601
- | `defaultValue` | String/Number | Sets default value for text/number input | `'John'`, `3000` |
602
- | `defaultValue` | Boolean | Auto-detects as confirmation prompt | `true`, `false` |
603
- | `choices` | Array | Auto-detects as selection list | `['A', 'B', 'C']` |
604
- | **Options Object** | | |
605
- | `multiple` | Boolean | Enables multiple selections (requires `choices`) | `true` |
606
- | `multiline` | Boolean | Opens system editor for multi-line input | `true` |
607
- | `editor` | Boolean | Opens system editor for multi-line input (same as `multiline`) | `true` |
608
- | `default` | Any | Default value or content (when using options object) | `'default value'` |
609
- | `type` | String | Input type: `'input'`, `'confirm'`, `'password'`, `'number'` | `'password'` |
610
- | `validate` | Function | Custom validation function | `(input) => input.length > 0` |
611
-
612
-
613
335
  ### `yell`
614
336
 
615
- Emphasized Output
616
-
617
337
  ASCII art output for important messages:
618
338
 
619
339
  ```javascript
620
340
  yell('BUILD COMPLETE!');
621
- yell('DEPLOYMENT SUCCESSFUL!');
622
341
  ```
623
342
 
624
343
  ### `silent`
625
344
 
626
- Stop printing realtime output
345
+ Disable realtime output:
627
346
 
628
347
  ```javascript
629
- // Silence all task output
630
- task.silence();
348
+ task.silence(); // Silence all task output
631
349
  await shell`npm build`;
350
+ task.prints(); // Restore output
632
351
 
633
- // restore printing output
634
- task.prints();
635
-
636
- // Silent specific task
352
+ // Silence a specific task
637
353
  const labels = await task.silent(() => shell(`gh api repos/:org/:repo/labels`));
638
354
  ```
639
355
 
640
356
  ## Task Control
641
357
 
642
- ### Parallel Executions
358
+ ### Parallel Execution
643
359
 
644
- No magic here. Use `Promise.all()` to run tasks in parallel:
360
+ Use `Promise.all()` to run tasks in parallel:
645
361
 
646
362
  ```javascript
647
- // Parallel tasks
648
363
  const results = await Promise.all([
649
364
  exec`npm run build:frontend`,
650
365
  exec`npm run build:backend`,
@@ -654,61 +369,49 @@ const results = await Promise.all([
654
369
 
655
370
  ### Custom Tasks
656
371
 
657
- Name and group your tasks operations:
372
+ Name and group operations:
658
373
 
659
374
  ```js
660
- await task('Build', () => {
661
- await exec`npm run build:frontend`);
662
- await exec`npm run build:docs`);
375
+ await task('Build', async () => {
376
+ await exec`npm run build:frontend`;
377
+ await exec`npm run build:docs`;
663
378
  });
664
- ````
379
+ ```
665
380
 
666
381
  ### Stop on Failure
667
382
 
668
- By default bunosh executes all tasks event if they fail. To stop execution immediately on failure, use the `task.stopOnFailures()` method.
669
-
383
+ By default bunosh continues execution when tasks fail. To stop immediately on failure:
670
384
 
671
385
  ```javascript
672
- /**
673
- * Strict deployment - stop on any failure
674
- */
675
386
  export async function deployStrict() {
676
- task.stopOnFailures(); // Exit immediately on any task failure
387
+ task.stopOnFailures();
677
388
 
678
389
  await exec`npm test`;
679
390
  await exec`npm run build`;
680
391
  await exec`deploy-script`;
681
- // If any task fails, script exits immediately
682
392
  }
683
393
 
684
- /**
685
- * Cleanup - continue despite failures
686
- */
687
394
  export async function cleanup() {
688
- task.ignoreFailures(); // Continue even if tasks fail
395
+ task.ignoreFailures();
689
396
 
690
397
  await task('Remove temp files', () => shell`rm -rf tmp/*`);
691
398
  await task('Clear logs', () => shell`rm -f logs/*.log`);
692
399
  await task('Reset cache', () => shell`rm -rf .cache`);
693
- // All tasks run regardless of failures
694
400
  }
695
401
  ```
696
402
 
697
403
  ### Try Operations
698
404
 
699
- Gracefully handle operations that might fail:
405
+ Handle operations that might fail:
700
406
 
701
407
  ```javascript
702
- /**
703
- * Check service availability
704
- */
705
408
  export async function checkServices() {
706
409
  const dbConnected = await task.try(() => shell`nc -z localhost 5432`);
707
410
 
708
411
  if (dbConnected) {
709
- say('βœ… Database connected');
412
+ say('Database connected');
710
413
  } else {
711
- say('⚠️ Database unavailable, using fallback');
414
+ say('Database unavailable, using fallback');
712
415
  await useFallbackDatabase();
713
416
  }
714
417
 
@@ -720,189 +423,14 @@ export async function checkServices() {
720
423
  }
721
424
  ```
722
425
 
723
- ## πŸ’« AI Integration
724
-
725
- Built-in AI support for code generation, documentation, and automation.
726
- Automatically responds to structured JSON output.
727
-
728
- AI provider automatically detected, but you need to provide API key and model name.
729
- Use `.env` file with `AI_MODEL` and `OPENAI_API_KEY` variables.
730
- In case you use provider other than OpenAI, Anthropic, Groq, you may need to configure it manually in top of Bunoshfile
731
-
732
- ```bash
733
- # Choose your AI model
734
- export AI_MODEL=gpt-5 # or claude-4-sonnet, llama-3.3-70b, etc.
735
-
736
- # Set API key for your provider
737
- export OPENAI_API_KEY=your_key_here # For OpenAI
738
- # export ANTHROPIC_API_KEY=your_key_here # For Claude
739
- # export GROQ_API_KEY=your_key_here # For Groq
740
- ```
741
-
742
-
743
- Use the `ai` function to interact with the AI.
744
-
745
- ```js
746
- const resp = await ai(message, { field1: 'what should be there', field2: 'what should be there' })
747
- ```
748
-
749
- ### Usage
750
-
751
- ```javascript
752
- const { ai, writeToFile } = global.bunosh;
753
-
754
- /**
755
- * Generate commit message from staged changes
756
- */
757
- export async function commit() {
758
- const diff = await exec`git diff --staged`;
759
-
760
- if (!diff.output.trim()) {
761
- say('No staged changes');
762
- return;
763
- }
764
-
765
- const response = await ai(
766
- `Generate a conventional commit message for: ${diff.output}`,
767
- {
768
- type: 'Commit type (feat/fix/docs/chore)',
769
- scope: 'Commit scope (optional)',
770
- subject: 'Brief subject line (50 chars max)',
771
- body: 'Detailed explanation'
772
- }
773
- );
774
-
775
- const commit = await response.json();
776
-
777
- const message = commit.scope
778
- ? `${commit.type}(${commit.scope}): ${commit.subject}\n\n${commit.body}`
779
- : `${commit.type}: ${commit.subject}\n\n${commit.body}`;
780
-
781
- await exec`git commit -m "${message}"`;
782
- say('βœ… AI-generated commit created');
783
- }
784
- ```
785
-
786
- See more ai usage examples in [docs/examples.md](docs/examples.md)
787
-
788
-
789
- ## Execute JavaScript Code
790
-
791
- Bunosh supports executing JavaScript code directly using the `-e` flag, allowing for powerful one-liners and integration with shell scripts and CI/CD systems.
792
-
793
- ### Basic Usage
794
-
795
- ```bash
796
- # Execute inline JavaScript
797
- bunosh -e "say('Hello')"
798
-
799
- # Execute JavaScript from stdin
800
- echo "say('Hello')" | bunosh -e
801
- ```
802
-
803
- ### Heredoc Syntax
804
-
805
- For multi-line scripts, use heredoc syntax for clean, readable code:
806
-
807
- ```bash
808
- bunosh -e << 'EOF'
809
- say('πŸš€ Starting build process...')
810
- await task('Install Dependencies', () => shell`npm ci`)
811
- await task('Build', () => shell`npm run build`)
812
- await task('Test', () => shell`npm test`)
813
- say('βœ… All tasks completed successfully!')
814
- EOF
815
- ```
816
-
817
- ### With Environment Variables and Control Flow
818
-
819
- ```bash
820
- # Complex script with conditions
821
- bunosh -e << 'EOF'
822
- const env = process.env.NODE_ENV || 'development'
823
- say(`Building for ${env}...`)
824
-
825
- if (env === 'production') {
826
- await shell`npm run build:prod`
827
- await task('Deploy', () => shell`./deploy.sh`)
828
- } else {
829
- await shell`npm run build:dev`
830
- }
831
-
832
- yell('BUILD COMPLETE!')
833
- EOF
834
- ```
835
-
836
- ### Error Handling
837
-
838
- ```bash
839
- # Script with error handling
840
- bunosh -e << 'EOF'
841
- task.stopOnFailures()
842
-
843
- try {
844
- await shell`npm test`
845
- await shell`npm run build`
846
- say('βœ… Success!')
847
- } catch (error) {
848
- yell(`❌ Build failed: ${error.message}`)
849
- process.exit(1)
850
- }
851
- EOF
852
- ```
853
-
854
- ### JavaScript Execution in GitHub Actions
855
-
856
- Use JavaScript execution to run Bunosh scripts inside CI/CD workflows without creating separate files:
857
-
858
- ```yaml
859
- - name: Build and Deploy
860
- run: |
861
- bunosh -e << 'EOF'
862
- say('πŸš€ Starting deployment...')
863
-
864
- if (!process.env.NODE_ENV === 'production') return;
865
-
866
- shell`./deploy.sh`
867
-
868
- const response = await fetch('${{ secrets.DEPLOY_WEBHOOK }}', {
869
- method: 'POST',
870
- headers: { 'Authorization': 'Bearer ${{ secrets.API_TOKEN }}' }
871
- })
872
-
873
- if (response.ok) {
874
- yell('πŸš€ DEPLOYMENT COMPLETE!')
875
- } else {
876
- yell('❌ DEPLOYMENT FAILED!')
877
- process.exit(1)
878
- }
879
- EOF
880
- env:
881
- NODE_ENV: production
882
- ```
883
-
884
- ### Shell Integration
885
-
886
- ```bash
887
- bunosh -e << 'EOF'
888
- say('Running database migrations...')
889
- await shell`npm run migrate`
890
- say('Migrations completed')
891
- EOF
892
- ```
893
-
894
-
895
- ## Examples
896
-
897
- For comprehensive examples of Bunosh in action, see [docs/examples.md](docs/examples.md).
426
+ ## Documentation
898
427
 
899
- This includes:
900
- - Feature branch workflow with git worktrees
901
- - AI-powered release note generation
902
- - Container building and publishing
903
- - Kubernetes deployment and rollback
904
- - AWS infrastructure management
905
- - And more practical examples
428
+ - **[Examples](docs/examples.md)** β€” Real-world examples and workflows
429
+ - **[AI Integration](docs/ai.md)** β€” Built-in AI support
430
+ - **[MCP Integration](docs/mcp.md)** β€” Expose commands to AI assistants (Claude, Cursor, etc.)
431
+ - **[JavaScript Execution](docs/javascript-execution.md)** β€” Execute JavaScript directly via CLI
432
+ - **[Bash Migration Guide](docs/bash-migration-guide.md)** β€” Convert bash scripts to Bunosh
433
+ - **[Node.js Migration Guide](docs/nodejs-migration-guide.md)** β€” Migrate from Node.js scripts
906
434
 
907
435
  ## License
908
436
 
@@ -910,4 +438,4 @@ MIT License - see LICENSE file for details.
910
438
 
911
439
  ---
912
440
 
913
- Cooked with ❀️ from Ukraine πŸ‡ΊπŸ‡¦
441
+ Made in Ukraine