bunosh 0.3.1 β†’ 0.4.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,27 +1,88 @@
1
1
  # 🍲 Bunosh
2
2
 
3
- > *Named after **banosh**, a traditional Ukrainian dish from cornmeal cooked with various ingredients such as mushrooms, cheese, sour cream*
4
-
5
3
  <p align="center">
6
4
  <img src="assets/logo.png" alt="Logo" width="150">
7
5
  </p>
8
6
 
7
+ <p align="center">
8
+ <strong>Your exceptional task runner</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ Transform JavaScript functions into CLI commands.
13
+ </p>
14
+
15
+ ---
16
+
9
17
  ## What is Bunosh?
10
18
 
11
- Bunosh is a modern task runner that transforms JavaScript functions into CLI commands. Write your build, deploy, and automation tasks in JavaScript and run them directly from the command line.
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
+ > *Named after **banosh**, a traditional Ukrainian dish from cornmeal cooked with various ingredients*
12
22
 
13
- **Why Bunosh?**
14
- - ✨ **Zero Configuration**: Write functions, get CLI commands
15
- - πŸš€ **Fast Execution**: Built for speed with beautiful terminal output
16
- - 🎨 **Rich Output**: Colored formatting with progress indicators
17
- - πŸ“¦ **Built-in Tasks**: Shell execution, HTTP requests, file operations
18
- - πŸ”§ **Cross-Platform**: Works on macOS, Linux, and Windows
23
+ ### ✨ Key Features
24
+
25
+ - **πŸš€ Zero Configuration** - Write functions, get CLI commands automatically
26
+ - **🎨 Pure JavaScript** - write commands as JavaScript functions
27
+ - **🏠 Personal Commands** - Global commands from `~/Bunoshfile.js` available everywhere with `my:` namespace
28
+ - **πŸ“¦ Built-in Tasks** - Shell execution, HTTP requests, file operations
29
+ - **πŸ€– AI-Powered** - integrate LLM calls into your daily tasks
30
+ - **πŸ”§ Cross-Platform** - Works seamlessly on macOS, Linux, and Windows. Via bun, npm, or as single executable.
31
+ - **🎯 Smart CLI** - Auto-completion, help generation, and intuitive argument handling
32
+
33
+ ## Hello World
34
+
35
+ No nore words, just code:
36
+
37
+ ```js
38
+ // this is a command in Bunoshfile.js
39
+ // bunosh hello:world
40
+
41
+ export async function helloWorld(name = 'person') {
42
+ name = await ask("What's your name?", name);
43
+ say(`πŸ‘‹ Hello, ${name}!`);
44
+ const city = await ask('Which city do you live in?')
45
+ const result = await fetch(`https://wttr.in/${city}?format=3`)
46
+ say(`Weather in your city ${result.output}`)
47
+
48
+ const toCleanup = await ask('Do you want me to cleanup tmp for you?', true);
49
+
50
+ if (!toCleanup) {
51
+ say('Bye, then!');
52
+ return;
53
+ }
54
+
55
+ await shell`rm -rf ${require('os').tmpdir()}/*`;
56
+ say('🧹 Cleaned up! Have a great day!');
57
+ }
58
+ ````
59
+
60
+ ## Why Choose Bunosh?
61
+
62
+ | Comparison | 🐚 Bash Scripts | πŸ“¦ npm scripts | πŸ› οΈ Task Runners | 🍲 **Bunosh** |
63
+ |------------|-----------------|----------------|------------------------------|----------------|
64
+ | **Syntax** | bash/zsh | Simple commands | Custom DSL | βœ… JavaScript |
65
+ | **Cross-platform** | No | Yes | Yes | βœ… Yes |
66
+ | **Ecosystem** | CLI tools | npm packages | Plugin dependent | βœ… Bash + npm |
67
+ | **Composability** | Commands | Separate scripts | Task dependencies | βœ… Import any JS code |
68
+
69
+ ## TOC
70
+
71
+ - [Installation](#installation)
72
+ - [Quickstart](#quickstart)
73
+ - [Commands](#commands)
74
+ - [Personal Commands (My Namespace)](#personal-commands-my-namespace)
75
+ - [Tasks](#tasks)
76
+ - [Input/Output](#inputoutput)
77
+ - [Task Control](#task-control)
78
+ - [AI Integration](#ai-integration)
79
+ - [Examples](#examples)
19
80
 
20
81
  ## Installation
21
82
 
22
83
  ### Option 1: Single Executable (Recommended)
23
84
 
24
- Download and install the standalone executable - no Node.js or Bun required. Includes built-in upgrade functionality:
85
+ Download the standalone executable - no Node.js or Bun required:
25
86
 
26
87
  **macOS:**
27
88
  ```bash
@@ -40,553 +101,361 @@ sudo mv bunosh-linux-x64 /usr/local/bin/bunosh
40
101
  Invoke-WebRequest -Uri "https://github.com/davertmik/bunosh/releases/latest/download/bunosh-windows-x64.exe.zip" -OutFile "bunosh.zip"
41
102
  Expand-Archive -Path "bunosh.zip" -DestinationPath .
42
103
  Move-Item "bunosh-windows-x64.exe" "bunosh.exe"
43
- # Add bunosh.exe to your PATH
44
104
  ```
45
105
 
46
- ### Option 2: Bun Package Manager
106
+ ### Option 2: Package Managers
47
107
 
48
108
  ```bash
109
+ # Using Bun
49
110
  bun add -g bunosh
50
- ```
51
-
52
- ### Option 3: NPM Package
53
111
 
54
- ```bash
112
+ # Using npm
55
113
  npm install -g bunosh
56
114
  ```
57
115
 
116
+ ## Quickstart
58
117
 
118
+ 1. **Initialize your Bunoshfile:**
59
119
  ```bash
60
- # Initialize a new Bunoshfile
61
120
  bunosh init
62
-
63
- # This creates Bunoshfile.js with sample tasks
64
121
  ```
65
122
 
66
- ### Example: Web Development Tasks
67
-
68
- Create a `Bunoshfile.js`:
69
-
123
+ 2. **Write your first command:**
70
124
  ```javascript
71
- // Import Bunosh functions from global object
72
- const { exec, fetch, writeToFile, say, ask, yell } = global.bunosh;
125
+ // Bunoshfile.js
126
+ const { exec, say } = global.bunosh;
73
127
 
74
128
  /**
75
- * Installs project dependencies
129
+ * Builds the project for production
76
130
  */
77
- export async function install() {
78
- await exec`npm install`;
79
- say('πŸ“¦ Dependencies installed!');
131
+ export async function build(env = 'production') {
132
+ say(`πŸ”¨ Building for ${env}...`);
133
+ await exec`npm run build`.env({ NODE_ENV: env });
134
+ say('βœ… Build complete!');
80
135
  }
136
+ ```
81
137
 
82
- /**
83
- * Starts development server
84
- */
85
- export async function dev() {
86
- say('πŸš€ Starting development server...');
87
- await exec`npm run dev`;
88
- }
138
+ That's it! Your function is now a CLI command.
89
139
 
90
- /**
91
- * Builds project for production
92
- */
93
- export async function build(target = 'production') {
94
- say(`πŸ”¨ Building for ${target}...`);
95
- await exec`npm run build`;
140
+ 3. **Run it:**
141
+ ```bash
142
+ # build for production
143
+ bunosh build
96
144
 
97
- if (target === 'production') {
98
- await exec`npm run optimize`;
99
- yell('BUILD COMPLETE!');
100
- }
101
- }
145
+ # build for staging
146
+ bunosh build staging
102
147
 
103
- /**
104
- * Deploys to specified environment
105
- */
106
- export async function deploy(env = 'staging', options = { skipTests: false }) {
107
- if (!options.skipTests) {
108
- say('πŸ§ͺ Running tests...');
109
- await exec`npm test`;
110
- }
148
+ # build for development
149
+ bunosh build development
150
+ ```
111
151
 
112
- say(`πŸš€ Deploying to ${env}...`);
113
- await build('production');
114
- await exec`docker build -t myapp:${env} .`;
115
- await exec`docker push myapp:${env}`;
152
+ ## Commands
116
153
 
117
- yell(`DEPLOYED TO ${env.toUpperCase()}!`);
118
- }
154
+ ### Creating Commands
119
155
 
120
- /**
121
- * Cleans up temporary files
122
- */
123
- export async function clean() {
124
- await exec`rm -rf dist node_modules/.cache tmp`;
125
- say('✨ All clean!');
126
- }
156
+ Every exported function in `Bunoshfile.js` becomes a CLI command:
127
157
 
128
- /**
129
- * Setup new project environment
130
- */
131
- export async function setup() {
132
- const projectName = await ask('What is your project name?');
133
- const useTypescript = await ask('Use TypeScript? (y/n)') === 'y';
134
-
135
- say('πŸ—οΈ Setting up project...');
136
-
137
- // Create package.json
138
- writeToFile('package.json', (line) => {
139
- line`{`;
140
- line` "name": "${projectName}",`;
141
- line` "version": "1.0.0",`;
142
- line` "type": "module"`;
143
- if (useTypescript) {
144
- line`, "devDependencies": {`;
145
- line` "typescript": "^5.0.0"`;
146
- line` }`;
147
- }
148
- line`}`;
149
- });
158
+ ```javascript
159
+ // Simple command
160
+ export function hello() {
161
+ console.log('Hello, World!');
162
+ }
150
163
 
151
- if (useTypescript) {
152
- await exec`npm install typescript --save-dev`;
153
- }
164
+ // Command with parameters
165
+ export function greet(name = 'friend') {
166
+ console.log(`Hello, ${name}!`);
167
+ }
154
168
 
155
- yell('PROJECT READY!');
169
+ // Command with options
170
+ export function deploy(env = 'staging', options = { force: false, verbose: false }) {
171
+ if (options.verbose) console.log('Verbose mode enabled');
172
+ console.log(`Deploying to ${env}${options.force ? ' (forced)' : ''}`);
156
173
  }
157
174
  ```
158
175
 
159
- ### Run Your Tasks
160
-
176
+ **CLI Usage:**
161
177
  ```bash
162
- # List all available commands
163
- bunosh
164
-
165
- # Run individual tasks
166
- bunosh install
167
- bunosh dev
168
- bunosh build
169
- bunosh build staging
170
- bunosh deploy production --skip-tests
171
- bunosh clean
172
- bunosh setup
178
+ bunosh hello
179
+ bunosh greet John
180
+ bunosh deploy production --force --verbose
173
181
  ```
174
182
 
175
- **Bunosh will display your tasks like this:**
183
+ ### Arguments and Options
176
184
 
177
- ```
178
- 🍲 Your exceptional task runner
185
+ Bunosh automatically maps function parameters to CLI arguments:
179
186
 
180
- Usage: bunosh <command> <args> [options]
187
+ ```javascript
188
+ /**
189
+ * Create a new feature branch
190
+ * @param {string} name - Feature name (required)
191
+ * @param {string} base - Base branch (optional, defaults to 'main')
192
+ * @param {object} options - CLI options
193
+ * @param {boolean} options.push - Push to remote after creation
194
+ */
195
+ export async function feature(name, base = 'main', options = { push: false }) {
196
+ await exec`git checkout -b feature/${name} ${base}`;
181
197
 
182
- Commands are loaded from exported functions in Bunoshfile.js
198
+ if (options.push) {
199
+ await exec`git push -u origin feature/${name}`;
200
+ }
201
+ }
202
+ ```
183
203
 
184
- Commands:
185
- build Builds project for production
186
- bunosh build [target]
187
- clean Cleans up temporary files
188
- deploy Deploys to specified environment
189
- bunosh deploy [env] --skip-tests
190
- dev Starts development server
191
- install Installs project dependencies
192
- setup Setup new project environment
204
+ **Generated CLI:**
205
+ ```bash
206
+ bunosh feature my-feature # Creates from main
207
+ bunosh feature my-feature develop # Creates from develop
208
+ bunosh feature my-feature --push # Creates and pushes
193
209
  ```
194
210
 
195
- ## Example: DevOps Tasks
211
+ ### Command Naming
196
212
 
197
- ```javascript
198
- const { exec, fetch, writeToFile, say, task } = global.bunosh;
213
+ Functions are automatically converted to kebab-case commands:
199
214
 
200
- /**
201
- * Checks service health across environments
202
- */
203
- export async function healthCheck(env = 'production') {
204
- const services = ['api', 'web', 'database'];
205
-
206
- for (const service of services) {
207
- const url = `https://${service}.${env}.example.com/health`;
208
- await task(`Checking ${service}`, async () => {
209
- const response = await fetch(url);
210
- if (!response.ok) throw new Error(`${service} is down!`);
211
- });
212
- }
215
+ | Function Name | CLI Command |
216
+ |--------------|-------------|
217
+ | `build` | `bunosh build` |
218
+ | `gitPush` | `bunosh git:push` |
219
+ | `npmInstall` | `bunosh npm:install` |
220
+ | `buildAndDeploy` | `bunosh build:and-deploy` |
213
221
 
214
- say('βœ… All services healthy!');
215
- }
222
+ ### Personal Commands (My Namespace)
216
223
 
217
- /**
218
- * Backup database with compression
219
- */
220
- export async function backup(database = 'main') {
221
- const timestamp = new Date().toISOString().split('T')[0];
222
- const filename = `backup-${database}-${timestamp}.sql.gz`;
224
+ Bunosh automatically loads commands from your home directory (`~/Bunoshfile.js`) and makes them available in any project with the `my:` namespace prefix.
223
225
 
224
- await exec`pg_dump ${database} | gzip > ${filename}`;
225
- await exec`aws s3 cp ${filename} s3://backups/${filename}`;
226
- await exec`rm ${filename}`;
226
+ **Create your personal toolkit:**
227
227
 
228
- say(`πŸ“¦ Backup saved: ${filename}`);
229
- }
228
+ ```javascript
229
+ // ~/Bunoshfile.js - Your global commands available everywhere
230
230
 
231
231
  /**
232
- * Updates SSL certificates
232
+ * Quick deployment to personal staging server
233
233
  */
234
- export async function updateCerts() {
235
- await exec`certbot renew`;
236
- await exec`nginx -s reload`;
237
- say('πŸ”’ Certificates updated!');
234
+ export function deploy(app, env = 'staging') {
235
+ say(`πŸš€ Deploying ${app} to personal ${env} environment...`);
236
+ await exec`ssh deploy@myserver.com "deploy.sh ${app} ${env}"`;
237
+ say('βœ… Deployment complete!');
238
238
  }
239
239
 
240
240
  /**
241
- * Deploys application with health checks
241
+ * Personal backup script
242
242
  */
243
- export async function deployWithChecks(env = 'staging') {
244
- await exec`kubectl apply -f k8s/${env}/`;
245
- await exec`kubectl rollout status deployment/myapp`;
246
- await healthCheck(env);
247
- say(`πŸš€ Successfully deployed to ${env}!`);
243
+ export function backup(target = 'documents') {
244
+ say(`πŸ’Ύ Creating backup of ${target}...`);
245
+ await exec`rsync -av ~/${target}/ ~/Backups/${target}-$(date +%Y%m%d)/`;
246
+ say('πŸ“¦ Backup completed!');
248
247
  }
249
248
 
250
249
  /**
251
- * Scales application instances
250
+ * Quick project setup
252
251
  */
253
- export async function scale(replicas = 3, service = 'myapp') {
254
- await exec`kubectl scale deployment/${service} --replicas=${replicas}`;
255
- say(`βš–οΈ Scaled ${service} to ${replicas} replicas`);
252
+ export function newProject(name, template = 'basic') {
253
+ say(`πŸ—οΈ Creating new project: ${name}`);
254
+ await exec`git clone https://github.com/my-templates/${template}.git ${name}`;
255
+ await exec`cd ${name} && npm install`;
256
+ say(`βœ… Project ${name} ready!`);
256
257
  }
257
258
  ```
258
259
 
259
- **Bunosh displays these as:**
260
+ **Available in any project:**
260
261
 
262
+ ```bash
263
+ # From any directory, these commands work:
264
+ bunosh my:deploy my-app production
265
+ bunosh my:backup projects
266
+ bunosh my:new-project awesome-app react
267
+
268
+ # List all your personal commands
269
+ bunosh --help # Shows "My Commands" section
261
270
  ```
262
- Usage: bunosh <command> <args> [options]
263
271
 
264
- Commands are loaded from exported functions in Bunoshfile.js
272
+ **Key Features:**
273
+ - 🏠 **Global availability** - Access your personal commands from any project directory
274
+ - 🏷️ **Namespaced** - `my:` prefix prevents conflicts with project commands
275
+ - πŸ“ **Same syntax** - Uses identical JavaScript function syntax as project commands
276
+ - πŸ”§ **Parameters & options** - Full support for arguments and CLI options
277
+ - πŸ“š **Help integration** - Shows in help output with descriptions
278
+ - 🚫 **Graceful fallback** - Works seamlessly when no home Bunoshfile exists
265
279
 
266
- Commands:
267
- backup Backup database with compression
268
- bunosh backup [database]
269
- deploy:with-checks Deploys application with health checks
270
- bunosh deploy:with-checks [env]
271
- health:check Checks service health across environments
272
- bunosh health:check [env]
273
- scale Scales application instances
274
- bunosh scale [replicas] [service]
275
- update:certs Updates SSL certificates
280
+ ## Tasks
276
281
 
277
- ```
278
-
279
- ## Example: Content Management
282
+ Bunosh provides built-in tasks which are available via `global.bunosh`:
280
283
 
281
284
  ```javascript
282
- const { exec, writeToFile, ask, say } = global.bunosh;
285
+ const { exec, shell, fetch, writeToFile, copyFile, task } = global.bunosh;
286
+ ```
283
287
 
284
- /**
285
- * Creates new blog post template
286
- */
287
- export async function newPost() {
288
- const title = await ask('Post title:');
289
- const slug = title.toLowerCase().replace(/\s+/g, '-');
290
- const date = new Date().toISOString().split('T')[0];
288
+ > We use global variables instead of imports to ensure you can use it with bunosh single-executable on any platform.
291
289
 
292
- writeToFile(`posts/${date}-${slug}.md`, (line) => {
293
- line`---`;
294
- line`title: "${title}"`;
295
- line`date: ${date}`;
296
- line`draft: true`;
297
- line`---`;
298
- line``;
299
- line`# ${title}`;
300
- line``;
301
- line`Your content here...`;
302
- });
303
290
 
304
- say(`πŸ“ Created: posts/${date}-${slug}.md`);
305
- }
291
+ * Async tasks: `exec`, `shell`, `fetch`
292
+ * Sync tasks: `writeToFile`, `copyFile`
293
+ * Task wrapper: `task`
306
294
 
307
- /**
308
- * Optimizes and compresses images
309
- */
310
- export async function optimizeImages() {
311
- await exec`find ./images -name "*.jpg" -exec jpegoptim --max=80 {} \\;`;
312
- await exec`find ./images -name "*.png" -exec optipng -o2 {} \\;`;
313
- say('πŸ–ΌοΈ Images optimized!');
314
- }
295
+ Each executed task returns `TaskResult` object which can be analyzed and used in next steps:
315
296
 
316
- /**
317
- * Creates new page template
318
- */
319
- export async function newPage(name) {
320
- const slug = name.toLowerCase().replace(/\s+/g, '-');
297
+ ```js
298
+ const result = await shell`echo "Hello"`;
299
+ console.log(result.status); // 'success', 'fail', or 'warning'
300
+ console.log(result.output); // Command output or result data
301
+ console.log(result.hasFailed); // true if status is 'fail'
302
+ console.log(result.hasSucceeded); // true if status is 'success'
303
+ console.log(result.hasWarning); // true if status is 'warning'
304
+ ```
321
305
 
322
- writeToFile(`content/pages/${slug}.md`, (line) => {
323
- line`---`;
324
- line`title: "${name}"`;
325
- line`type: "page"`;
326
- line`---`;
327
- line``;
328
- line`# ${name}`;
329
- line``;
330
- line`Page content here...`;
331
- });
306
+ Now let's look into other tasks:
332
307
 
333
- say(`πŸ“„ Created: content/pages/${slug}.md`);
334
- }
308
+ #### `task`
335
309
 
336
- /**
337
- * Generates site and deploys
338
- */
339
- export async function publish() {
340
- await exec`hugo --minify`;
341
- await exec`rsync -avz public/ user@server:/var/www/site/`;
342
- say('🌐 Site published!');
343
- }
344
-
345
- /**
346
- * Builds and serves development site
347
- */
348
- export async function serve(port = 1313) {
349
- await exec`hugo server --port ${port} --buildDrafts`;
350
- }
351
- ```
352
-
353
- **Bunosh displays these as:**
310
+ General method that transforms a function into a task. Adds it to tasks registry and prints task information:
354
311
 
312
+ ```js
313
+ // register operation as a task
314
+ const result = task('Fetch Readme file', () => {
315
+ const content = fs.readFileSync('README.md', 'utf8');
316
+ console.log(content);
317
+ return content;
318
+ });
355
319
  ```
356
- Usage: bunosh <command> <args> [options]
357
320
 
358
- Commands are loaded from exported functions in Bunoshfile.js
321
+ If a another task is executed inside a task function, its description will be appended to all child tasks.
359
322
 
360
- Commands:
361
- new:page Creates new page template
362
- bunosh new:page <name>
363
- new:post Creates new blog post template
364
- optimize:images Optimizes and compresses images
365
- publish Generates site and deploys
366
- serve Builds and serves development site
367
- bunosh serve [port]
323
+ #### `exec`
368
324
 
369
- ```
325
+ Run single command using [child process `spawn`](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options)
370
326
 
371
- ## Built-in Functions
327
+ ```javascript
328
+ // Complex commands with pipes and streaming output
329
+ await exec`npm install --verbose`;
330
+ await exec`docker build . | tee build.log`;
331
+ await exec`find . -name "*.js" | grep -v node_modules | wc -l`;
372
332
 
373
- All Bunosh functions are available via `global.bunosh`:
333
+ // With environment variables
334
+ await exec`echo $NODE_ENV`.env({ NODE_ENV: 'production' });
374
335
 
375
- ```javascript
376
- const { exec, shell, fetch, writeToFile, copyFile, say, ask, yell, task } = global.bunosh;
336
+ // In specific directory
337
+ await exec`npm install`.cwd('/tmp/project');
377
338
  ```
378
339
 
379
- ### Shell Execution
340
+ By default task prints live line-by-line output from stdout and stderr. To disable output, use `silent` method:
380
341
 
381
- Bunosh provides two ways to execute shell commands:
382
-
383
- #### `exec` - Universal Shell Execution
342
+ ```javascript
384
343
 
385
- Best for complex commands, cross-platform compatibility, and when you need real-time streaming output.
344
+ // disable printing output
345
+ await task.silent(() => exec`npm install`);
386
346
 
387
- ```javascript
388
- // Complex shell commands with pipes and redirections
389
- await exec`find . -name "*.js" | grep -v node_modules | wc -l`;
390
- await exec`npm install --verbose`; // Shows progress in real-time
391
- await exec`docker build . | tee build.log`;
347
+ // disable output for all commands
348
+ await task.silence();
392
349
  ```
393
350
 
394
- #### `shell` - Native Bun Shell (with Node.js fallback)
351
+ See more [#silent](#silent)
395
352
 
396
- Best for simple commands when running under Bun for maximum performance.
353
+ #### `shell` - Fast Native Execution
354
+
355
+ Optimized for simple, fast commands when running under Bun:
397
356
 
398
357
  ```javascript
399
358
  // Simple, fast commands
400
359
  await shell`pwd`;
401
- await shell`echo "Hello World"`;
402
360
  await shell`ls -la`;
403
361
  await shell`cat package.json`;
404
362
  ```
405
363
 
406
- #### When to Use Which?
364
+ For more details see [bun shell](https://bun.sh/docs/runtime/shell) reference
407
365
 
408
- **Use `shell` when:**
409
- - βœ… Running under Bun for optimal performance
410
- - βœ… Executing simple commands (`pwd`, `ls`, `echo`, `cat`)
411
- - βœ… Want fastest possible execution
412
- - βœ… Working with basic file operations
366
+ `shell` vs `exec`
413
367
 
414
- **Use `exec` when:**
415
- - βœ… Need cross-platform compatibility (Node.js + Bun)
416
- - βœ… Using complex shell features (pipes, redirections, command chaining)
417
- - βœ… Want real-time streaming output for long-running commands
418
- - βœ… Running package managers (`npm install`, `docker build`)
368
+ | Command | Best For | Use Cases | Implementation | Compatibility |
369
+ |---------|----------|-----------|----------------|---------------|
370
+ | `exec` | Single command execution | single command | spawn process | NodeJS + Bun but platform dependent |
371
+ | `shell` | Multiple cross-platform shell commands | exec + `pwd`, `ls`, `echo`, `cat`, basic file ops | bun shell | Bun only but Cross-platform |
419
372
 
420
- Both support the same API and return the same `TaskResult` object:
373
+ shell prints output from stdout and stderr. To disable output, [make tasks silent](#silent):
421
374
 
422
- ```javascript
423
- // Both tasks support environment variables
424
- await shell`echo $NODE_ENV`.env({ NODE_ENV: 'production' });
425
- await exec`echo $NODE_ENV`.env({ NODE_ENV: 'production' });
375
+ ###$ `fetch`
426
376
 
427
- // Both support working directory changes
428
- await shell`pwd`.cwd('/tmp');
429
- await exec`ls -la`.cwd('/tmp');
377
+ `fetch` task wraps fetch:
430
378
 
431
- // Choose based on complexity and performance needs
432
- await shell`cat package.json`; // Simple, fast
433
- await exec`npm install --verbose`; // Complex, streaming
379
+ ```javascript
380
+ /**
381
+ * Check service health
382
+ */
383
+ export async function healthCheck(url) {
384
+ const response = await fetch(url);
385
+
386
+ if (response.ok) {
387
+ const data = await response.json();
388
+ say(`βœ… Service healthy: ${data.status}`);
389
+ } else {
390
+ yell(`❌ Service down: ${response.status}`);
391
+ }
392
+ }
434
393
  ```
435
394
 
436
- #### TaskResult Object
395
+ ### File Operations
437
396
 
438
- Both `exec` and `shell` return a `TaskResult` object with the following properties and methods:
397
+ Template-based file writing and copying:
439
398
 
440
399
  ```javascript
441
- const result = await exec`ls -la`;
442
- // or
443
- const result = await shell`ls -la`;
444
-
445
- // Properties
446
- result.status // 'success' or 'fail'
447
- result.output // Combined stdout/stderr as string
448
-
449
- // Getters (boolean)
450
- result.hasFailed // true if command failed (non-zero exit code)
451
- result.hasSucceeded // true if command succeeded (exit code 0)
452
- ```
453
-
454
- #### Error Handling Examples
400
+ /**
401
+ * Generate configuration file
402
+ */
403
+ export function generatePage(name, description = '') {
404
+ writeToFile('index.mdx', (line) => {
405
+ line`name": "${name}",`;
406
+ if (description) {
407
+ line`description: "${description}"`;
408
+ }
409
+ line`---`;
410
+ });
455
411
 
456
- ```javascript
457
- // Check command success
458
- const result = await exec`npm test`;
459
- if (result.hasSucceeded) {
460
- say('βœ… Tests passed!');
461
- } else {
462
- yell('❌ Tests failed!');
463
- console.log(result.output); // Show error details
412
+ say('πŸ“ Page created');
464
413
  }
465
414
 
466
- // Get command output
467
- const result = await exec`git rev-parse HEAD`;
468
- if (result.hasSucceeded) {
469
- const commitHash = result.output.trim();
470
- say(`Current commit: ${commitHash}`);
471
- }
415
+ // Copy files
416
+ copyFile('template.env', '.env');
417
+ ```
472
418
 
473
- // Handle failures gracefully
474
- const result = await exec`optional-command-that-might-fail`;
475
- if (result.hasFailed) {
476
- say('Command failed, but continuing...');
477
- console.log('Error output:', result.output);
478
- }
479
419
 
480
- // Old vs New style comparison
481
- // ❌ Old: Commands throw on failure
482
- try {
483
- await someOtherTaskRunner('failing-command');
484
- } catch (error) {
485
- // Handle error
486
- }
420
+ ## Input/Output
487
421
 
488
- // βœ… New: Explicit success/failure handling
489
- const result = await exec`failing-command`;
490
- if (result.hasFailed) {
491
- // Handle failure explicitly
492
- }
493
- ```
422
+ ### `say` - Normal Output
494
423
 
495
- ### HTTP Requests (`fetch`)
496
- ```javascript
497
- // GET request with progress indicator
498
- const response = await fetch('https://api.github.com/repos/user/repo');
499
- const data = await response.json();
500
- ```
424
+ Standard output with visual indicator:
501
425
 
502
- ### File Operations
503
426
  ```javascript
504
- // Write file with template builder
505
- writeToFile('config.json', (line) => {
506
- line`{`;
507
- line` "name": "myapp",`;
508
- line` "version": "1.0.0"`;
509
- line`}`;
510
- });
511
-
512
- // Copy files
513
- copyFile('template.js', 'output.js');
427
+ say('Building project...');
428
+ say('πŸ“¦ Dependencies installed');
429
+ say(`Found ${count} files to process`);
514
430
  ```
515
431
 
516
- ### User Interaction
432
+ ### `ask` - User Input
517
433
 
518
- #### `ask()` - Interactive User Input
519
-
520
- The `ask()` function provides flexible ways to get user input with smart parameter detection and multiple modes:
434
+ Flexible user input with smart parameter detection:
521
435
 
522
436
  ```javascript
523
- // === SIMPLE SYNTAX WITH SMART DETECTION ===
524
-
525
- // Basic text input
526
- const name = await ask('What is your name?');
527
-
528
- // Text input with default value
529
- const projectName = await ask('Project name:', 'my-awesome-app');
530
-
531
- // Boolean confirmation (auto-detects confirm type)
532
- const shouldContinue = await ask('Continue with deployment?', true);
533
- const forceUpdate = await ask('Force update?', false);
534
-
535
- // Number input with default
536
- const port = await ask('Enter port number:', 3000);
437
+ // Text input with default
438
+ const name = await ask('Project name:', 'my-app');
537
439
 
538
- // Single choice selection (auto-detects from array)
539
- const framework = await ask('Choose your framework:', [
540
- 'React', 'Vue', 'Angular', 'Svelte'
541
- ]);
542
-
543
- // Multiple choice selection (array + options)
544
- const features = await ask('Select features to include:', [
545
- 'TypeScript', 'ESLint', 'Prettier', 'Tests', 'CI/CD'
546
- ], { multiple: true });
440
+ // Boolean confirmation (auto-detects)
441
+ const proceed = await ask('Continue?', true);
547
442
 
548
- // === ADVANCED OPTIONS SYNTAX ===
443
+ // Single selection (auto-detects from array)
444
+ const env = await ask('Select environment:', ['dev', 'staging', 'prod']);
549
445
 
550
- // Multiline text input (opens system editor)
551
- const description = await ask('Enter project description:', {
552
- multiline: true // Same as editor: true
553
- });
554
-
555
- // Editor input with default content
556
- const config = await ask('Edit configuration:', {
557
- editor: true,
558
- default: 'Initial content here...'
559
- });
446
+ // Multiple selection
447
+ const features = await ask('Select features:',
448
+ ['TypeScript', 'ESLint', 'Tests'],
449
+ { multiple: true }
450
+ );
560
451
 
561
- // Password input (hidden)
562
- const password = await ask('Enter password:', {
563
- type: 'password'
564
- });
452
+ // Password input
453
+ const password = await ask('Enter password:', { type: 'password' });
565
454
 
566
- // Mixed: default value + additional options
567
- const email = await ask('Email address:', 'user@example.com', {
568
- validate: (input) => input.includes('@') || 'Please enter valid email'
569
- });
455
+ // Multiline editor input
456
+ const description = await ask('Enter description:', { editor: true });
570
457
  ```
571
458
 
572
- #### Ask Function Signatures
573
-
574
- ```javascript
575
- // Smart detection syntax
576
- ask(question, defaultValue, options?)
577
- ask(question, choices[], options?)
578
- ask(question, options)
579
-
580
- // Examples:
581
- ask('Name?', 'John') // String default
582
- ask('Continue?', true) // Boolean -> confirm type
583
- ask('Port?', 3000) // Number default
584
- ask('Color?', ['red', 'blue']) // Array -> choices
585
- ask('Colors?', ['red', 'blue'], { multiple: true }) // Array + options
586
- ```
587
-
588
- #### Ask Options Reference
589
-
590
459
  | Parameter/Option | Type | Description | Example |
591
460
  |------------------|------|-------------|---------|
592
461
  | **Smart Detection** | | |
@@ -601,493 +470,298 @@ ask('Colors?', ['red', 'blue'], { multiple: true }) // Array + options
601
470
  | `type` | String | Input type: `'input'`, `'confirm'`, `'password'`, `'number'` | `'password'` |
602
471
  | `validate` | Function | Custom validation function | `(input) => input.length > 0` |
603
472
 
604
- #### Advanced Ask Examples
605
473
 
606
- ```javascript
607
- /**
608
- * Interactive project setup with smart syntax
609
- */
610
- export async function setupProject() {
611
- // Simple syntax with smart detection
612
- const projectName = await ask('Project name:', 'my-awesome-project');
613
-
614
- const projectType = await ask('Project type:', [
615
- 'Web App', 'API', 'CLI Tool', 'Library'
616
- ]);
617
-
618
- const dependencies = await ask('Select dependencies:', [
619
- 'express', 'lodash', 'axios', 'moment', 'uuid'
620
- ], { multiple: true });
621
-
622
- const useTypescript = await ask('Use TypeScript?', false);
623
-
624
- // Editor input for complex configuration
625
- const packageJson = await ask('Customize package.json:', {
626
- editor: true,
627
- default: JSON.stringify({
628
- name: projectName,
629
- version: '1.0.0',
630
- description: '',
631
- dependencies: {}
632
- }, null, 2)
633
- });
634
-
635
- say(`Creating ${projectType}: ${projectName}`);
636
- say(`Dependencies: ${dependencies.join(', ')}`);
637
- say(`TypeScript: ${useTypescript ? 'Yes' : 'No'}`);
638
-
639
- writeToFile('package.json', packageJson);
640
- }
474
+ ### `yell`
641
475
 
642
- /**
643
- * Git commit with editor input
644
- */
645
- export async function interactiveCommit() {
646
- const message = await ask('Enter commit message:', {
647
- editor: true,
648
- default: 'feat: \n\n# Write your commit message above\n# First line: brief summary (50 chars max)\n# Blank line, then detailed explanation'
649
- });
650
-
651
- await exec`git commit -m "${message}"`;
652
- say('βœ… Committed successfully!');
653
- }
476
+ Emphasized Output
654
477
 
655
- /**
656
- * Database migration with smart syntax
657
- */
658
- export async function migrate() {
659
- // Smart array detection for choices
660
- const action = await ask('Migration action:', [
661
- 'Run pending migrations',
662
- 'Rollback last migration',
663
- 'Reset database',
664
- 'Create new migration'
665
- ]);
666
-
667
- if (action === 'Reset database') {
668
- // Smart boolean detection for confirmation
669
- const confirmed = await ask('⚠️ This will DELETE ALL DATA. Are you sure?', false);
670
-
671
- if (!confirmed) {
672
- say('Migration cancelled');
673
- return;
674
- }
675
- }
676
-
677
- // Execute migration based on selection...
678
- }
679
-
680
- /**
681
- * Server configuration with mixed smart syntax
682
- */
683
- export async function configureServer() {
684
- // Simple defaults
685
- const serverName = await ask('Server name:', 'my-server');
686
- const port = await ask('Port number:', 8080);
687
- const enableHTTPS = await ask('Enable HTTPS?', true);
688
-
689
- // Array with additional options
690
- const databases = await ask('Select databases to connect:', [
691
- 'PostgreSQL', 'MongoDB', 'Redis', 'MySQL'
692
- ], { multiple: true });
693
-
694
- // Mix of default + validation
695
- const adminEmail = await ask('Admin email:', 'admin@example.com', {
696
- validate: (email) => email.includes('@') || 'Please enter a valid email'
697
- });
698
-
699
- say(`Configuring ${serverName} on port ${port}`);
700
- say(`HTTPS: ${enableHTTPS ? 'Enabled' : 'Disabled'}`);
701
- say(`Databases: ${databases.join(', ')}`);
702
- say(`Admin: ${adminEmail}`);
703
- }
704
- ```
705
-
706
- #### Output Functions
478
+ ASCII art output for important messages:
707
479
 
708
480
  ```javascript
709
- // Output messages
710
- say('Building project...'); // Normal output with !
711
- yell('BUILD COMPLETE!'); // Emphasized ASCII art output
712
-
713
- // Wrap long operations with progress
714
- await task('Installing dependencies', async () => {
715
- await exec`npm install`;
716
- });
481
+ yell('BUILD COMPLETE!');
482
+ yell('DEPLOYMENT SUCCESSFUL!');
717
483
  ```
718
484
 
719
- ## πŸ€– AI-Powered Tasks
485
+ ### `silent`
720
486
 
721
- Bunosh now supports AI integration with structured outputs! Connect to popular AI providers and generate content, analyze data, or automate text processing with simple function calls.
487
+ Stop printing realtime output
722
488
 
723
- ### Quick Setup
489
+ ```javascript
490
+ // Silence all task output
491
+ task.silence();
492
+ await shell`npm build`;
724
493
 
725
- Set your AI provider credentials:
726
- ```bash
727
- # Required: Choose your model
728
- export AI_MODEL=gpt-4o # or claude-3-5-sonnet-20241022, llama-3.3-70b-versatile, etc.
494
+ // restore printing output
495
+ task.prints();
729
496
 
730
- # Required: Set API key for your chosen provider
731
- export OPENAI_API_KEY=your_key_here # for OpenAI models
732
- # export ANTHROPIC_API_KEY=your_key_here # for Claude models
733
- # export GROQ_API_KEY=your_key_here # for Groq models
497
+ // Silent specific task
498
+ const labels = await task.silent(() => shell(`gh api repos/:org/:repo/labels`));
734
499
  ```
735
500
 
736
- ### Built-in AI Providers
737
-
738
- - **OpenAI** - GPT-4o, GPT-4o-mini, GPT-3.5-turbo (via `OPENAI_API_KEY`)
739
- - **Anthropic** - Claude 3.5 Sonnet, Claude 3 Haiku (via `ANTHROPIC_API_KEY`)
740
- - **Groq** - Llama 3.3, Mixtral, Gemma models (via `GROQ_API_KEY` or `GROQ_KEY`)
501
+ ## Task Control
741
502
 
742
- ### Custom AI Providers
503
+ ### Parallel Executions
743
504
 
744
- For enterprise and custom setups, you can import and register any AI provider manually:
505
+ No magic here. Use `Promise.all()` to run tasks in parallel:
745
506
 
746
507
  ```javascript
747
- const { ai } = global.bunosh;
748
-
749
- // Method 1: Direct model configuration (most flexible)
750
- import { bedrock } from '@ai-sdk/amazon-bedrock';
751
- const bedrockModel = bedrock('anthropic.claude-3-sonnet-20240229-v1:0', {
752
- region: 'us-east-1',
753
- credentials: {
754
- accessKeyId: 'your-access-key',
755
- secretAccessKey: 'your-secret-key'
756
- }
757
- });
758
-
759
- ai.configure({ model: bedrockModel });
508
+ // Parallel tasks
509
+ const results = await Promise.all([
510
+ exec`npm run build:frontend`,
511
+ exec`npm run build:backend`,
512
+ exec`npm run build:docs`
513
+ ]);
514
+ ```
760
515
 
761
- // Method 2: Register custom provider with environment variable
762
- import { xai } from '@ai-sdk/xai';
763
- ai.configure({
764
- registerProvider: {
765
- envVar: 'XAI_API_KEY',
766
- provider: {
767
- createInstance: (modelName) => xai(modelName)
768
- }
769
- }
770
- });
516
+ ### Custom Tasks
771
517
 
772
- // Method 3: Register any custom provider (Azure OpenAI, OpenRouter, etc.)
773
- import { openrouter } from '@openrouter/ai-sdk-provider';
774
- ai.configure({
775
- registerProvider: {
776
- envVar: 'OPENROUTER_API_KEY',
777
- provider: {
778
- createInstance: (modelName) => openrouter(modelName)
779
- }
780
- }
781
- });
518
+ Name and group your tasks operations:
782
519
 
783
- // Method 4: Register completely custom provider
784
- ai.configure({
785
- registerProvider: {
786
- envVar: 'CUSTOM_AI_API_KEY',
787
- provider: {
788
- createInstance: (modelName) => {
789
- // Your custom provider logic
790
- return customAIProvider(modelName, {
791
- apiKey: process.env.CUSTOM_AI_API_KEY,
792
- endpoint: 'https://custom-ai.company.com/v1'
793
- });
794
- }
795
- }
796
- }
520
+ ```js
521
+ await task('Build', () => {
522
+ await exec`npm run build:frontend`);
523
+ await exec`npm run build:docs`);
797
524
  });
525
+ ````
798
526
 
799
- // Reset to environment variable configuration
800
- ai.reset();
527
+ ### Stop on Failure
801
528
 
802
- // Check current configuration
803
- const config = ai.getConfig();
804
- console.log('Current AI config:', config);
805
- ```
529
+ By default bunosh executes all tasks event if they fail. To stop execution immediately on failure, use the `task.stopOnFailures()` method.
806
530
 
807
- ### AI Task Examples
808
531
 
809
532
  ```javascript
810
- const { ai, writeToFile, say } = global.bunosh;
811
-
812
533
  /**
813
- * Generate project documentation with AI
534
+ * Strict deployment - stop on any failure
814
535
  */
815
- export async function generateDocs() {
816
- const codebase = fs.readFileSync('src/index.js', 'utf8');
817
-
818
- const result = await ai(
819
- `Generate documentation for this code: ${codebase}`,
820
- {
821
- overview: 'Brief project overview',
822
- apiReference: 'API documentation',
823
- examples: 'Usage examples',
824
- installation: 'Installation instructions'
825
- }
826
- );
827
-
828
- writeToFile('README.md', (line) => {
829
- line`# ${result.overview}`;
830
- line``;
831
- line`## Installation`;
832
- line`${result.installation}`;
833
- line``;
834
- line`## API Reference`;
835
- line`${result.apiReference}`;
836
- line``;
837
- line`## Examples`;
838
- line`${result.examples}`;
839
- });
840
-
841
- say('πŸ“š Documentation generated!');
536
+ export async function deployStrict() {
537
+ task.stopOnFailures(); // Exit immediately on any task failure
538
+
539
+ await exec`npm test`;
540
+ await exec`npm run build`;
541
+ await exec`deploy-script`;
542
+ // If any task fails, script exits immediately
842
543
  }
843
544
 
844
545
  /**
845
- * Analyze and optimize code with AI suggestions
546
+ * Cleanup - continue despite failures
846
547
  */
847
- export async function codeReview(filename) {
848
- const code = fs.readFileSync(filename, 'utf8');
849
-
850
- const analysis = await ai(
851
- `Review this code for improvements: ${code}`,
852
- {
853
- issues: 'List of potential issues',
854
- suggestions: 'Specific improvement suggestions',
855
- security: 'Security considerations',
856
- performance: 'Performance optimization tips',
857
- rating: 'Overall code quality rating (1-10)'
858
- }
859
- );
860
-
861
- say(`πŸ” Code Review for ${filename}:`);
862
- console.log(`Rating: ${analysis.rating}/10`);
863
- console.log(`Issues: ${analysis.issues}`);
864
- console.log(`Suggestions: ${analysis.suggestions}`);
865
- console.log(`Security: ${analysis.security}`);
866
- console.log(`Performance: ${analysis.performance}`);
548
+ export async function cleanup() {
549
+ task.ignoreFailures(); // Continue even if tasks fail
550
+
551
+ await task('Remove temp files', () => shell`rm -rf tmp/*`);
552
+ await task('Clear logs', () => shell`rm -f logs/*.log`);
553
+ await task('Reset cache', () => shell`rm -rf .cache`);
554
+ // All tasks run regardless of failures
867
555
  }
556
+ ```
557
+
558
+ ### Try Operations
868
559
 
560
+ Gracefully handle operations that might fail:
561
+
562
+ ```javascript
869
563
  /**
870
- * Generate test cases from code
564
+ * Check service availability
871
565
  */
872
- export async function generateTests(sourceFile) {
873
- const code = fs.readFileSync(sourceFile, 'utf8');
874
-
875
- const tests = await ai(
876
- `Generate comprehensive unit tests for this code: ${code}`,
877
- {
878
- testSuite: 'Complete test suite code',
879
- edgeCases: 'List of edge cases covered',
880
- mockSetup: 'Required mocks and setup code'
881
- }
882
- );
883
-
884
- const testFile = sourceFile.replace('.js', '.test.js');
885
- writeToFile(testFile, (line) => {
886
- line`${tests.mockSetup}`;
887
- line``;
888
- line`${tests.testSuite}`;
889
- });
890
-
891
- say(`πŸ§ͺ Tests generated: ${testFile}`);
892
- say(`Edge cases: ${tests.edgeCases}`);
566
+ export async function checkServices() {
567
+ const dbConnected = await task.try(shell`nc -z localhost 5432`);
568
+
569
+ if (dbConnected) {
570
+ say('βœ… Database connected');
571
+ } else {
572
+ say('⚠️ Database unavailable, using fallback');
573
+ await useFallbackDatabase();
574
+ }
575
+
576
+ const apiHealthy = await task.try(() => fetch('http://localhost:3000/health'));
577
+
578
+ if (!apiHealthy) {
579
+ yell('API IS DOWN!');
580
+ }
893
581
  }
582
+ ```
583
+
584
+ ## πŸ’« AI Integration
585
+
586
+ Built-in AI support for code generation, documentation, and automation.
587
+ Automatically responds to structured JSON output.
588
+
589
+ AI provider automatically detected, but you need to provide API key and model name.
590
+ Use `.env` file with `AI_MODEL` and `OPENAI_API_KEY` variables.
591
+ In case you use provider other than OpenAI, Anthropic, Groq, you may need to configure it manually in top of Bunoshfile
592
+
593
+ ```bash
594
+ # Choose your AI model
595
+ export AI_MODEL=gpt-5 # or claude-4-sonnet, llama-3.3-70b, etc.
596
+
597
+ # Set API key for your provider
598
+ export OPENAI_API_KEY=your_key_here # For OpenAI
599
+ # export ANTHROPIC_API_KEY=your_key_here # For Claude
600
+ # export GROQ_API_KEY=your_key_here # For Groq
601
+ ```
602
+
603
+
604
+ Use the `ai` function to interact with the AI.
605
+
606
+ ```js
607
+ const resp = await ai(message, { field1: 'what should be there', field2: 'what should be there' })
608
+ ```
609
+
610
+ ### Usage
611
+
612
+ ```javascript
613
+ const { ai, writeToFile } = global.bunosh;
894
614
 
895
615
  /**
896
- * Create commit messages from git diff
616
+ * Generate commit message from staged changes
897
617
  */
898
- export async function smartCommit() {
618
+ export async function commit() {
899
619
  const diff = await exec`git diff --staged`;
900
-
901
- if (diff.hasFailed || !diff.output.trim()) {
902
- say('No staged changes found');
620
+
621
+ if (!diff.output.trim()) {
622
+ say('No staged changes');
903
623
  return;
904
624
  }
905
-
625
+
906
626
  const commit = await ai(
907
- `Generate a commit message for these changes: ${diff.output}`,
627
+ `Generate a conventional commit message for: ${diff.output}`,
908
628
  {
909
- title: 'Concise commit title (50 chars max)',
910
- body: 'Detailed commit body explaining what and why',
911
- type: 'Commit type (feat/fix/docs/refactor/test/chore)'
629
+ type: 'Commit type (feat/fix/docs/chore)',
630
+ scope: 'Commit scope (optional)',
631
+ subject: 'Brief subject line (50 chars max)',
632
+ body: 'Detailed explanation'
912
633
  }
913
634
  );
914
-
915
- const message = `${commit.type}: ${commit.title}\n\n${commit.body}`;
916
- await exec`git commit -m "${message}"`;
917
-
918
- say(`βœ… Committed with AI-generated message:`);
919
- console.log(message);
920
- }
921
635
 
922
- /**
923
- * Enterprise AI setup with custom provider
924
- */
925
- export async function setupEnterpriseAI() {
926
- // Import your enterprise AI provider
927
- import { bedrock } from '@ai-sdk/amazon-bedrock';
928
-
929
- // Configure for enterprise use
930
- const enterpriseModel = bedrock('anthropic.claude-3-sonnet-20240229-v1:0', {
931
- region: 'us-east-1'
932
- // Uses AWS credentials from environment/profile
933
- });
934
-
935
- ai.configure({ model: enterpriseModel });
936
-
937
- const analysis = await ai(
938
- 'Analyze our company performance from this quarterly report: [data]',
939
- {
940
- summary: 'Executive summary of performance',
941
- risks: 'Identified business risks',
942
- opportunities: 'Growth opportunities',
943
- recommendations: 'Strategic recommendations'
944
- }
945
- );
946
-
947
- say('πŸ“Š Enterprise AI analysis complete');
948
- console.log(analysis);
636
+ const message = commit.scope
637
+ ? `${commit.type}(${commit.scope}): ${commit.subject}\n\n${commit.body}`
638
+ : `${commit.type}: ${commit.subject}\n\n${commit.body}`;
639
+
640
+ await exec`git commit -m "${message}"`;
641
+ say('βœ… AI-generated commit created');
949
642
  }
950
643
  ```
951
644
 
952
- ### Simple Text Generation
645
+ See more ai usage examples in [docs/examples.md](docs/examples.md)
953
646
 
954
- For quick text generation without structured output:
955
647
 
956
- ```javascript
957
- /**
958
- * Generate marketing copy
959
- */
960
- export async function generateCopy(product) {
961
- const copy = await ai(`Write compelling marketing copy for: ${product}`);
962
- say('πŸ“ Generated copy:');
963
- console.log(copy);
964
- }
648
+ ## Execute JavaScript Code
965
649
 
966
- /**
967
- * Translate content
968
- */
969
- export async function translate(text, language = 'Spanish') {
970
- const translation = await ai(`Translate to ${language}: ${text}`);
971
- say(`🌐 Translation to ${language}:`);
972
- console.log(translation);
973
- }
974
- ```
650
+ Bunosh supports executing JavaScript code directly using the `-e` flag, allowing for powerful one-liners and integration with shell scripts and CI/CD systems.
975
651
 
976
- ### Progressive Enhancement
652
+ ### Basic Usage
977
653
 
978
- The AI task features:
979
- - **🎭 Animated Progress**: Braille spinner animation during generation
980
- - **πŸ“Š Token Tracking**: Shows token usage for cost monitoring
981
- - **⚑ Fast Inference**: Optimized for speed with Groq and other providers
982
- - **πŸ”§ Structured Output**: Get JSON responses with defined schemas
983
- - **🎯 Provider Auto-Detection**: Automatically detects available API keys
984
- - **πŸ’ͺ Error Handling**: Graceful handling of API errors and rate limits
654
+ ```bash
655
+ # Execute inline JavaScript
656
+ bunosh -e "say('Hello')"
985
657
 
986
- Transform your development workflow with AI-powered automation! Generate documentation, analyze code, create tests, write commit messages, and much more.
658
+ # Execute JavaScript from stdin
659
+ echo "say('Hello')" | bunosh -e
660
+ ```
987
661
 
988
- ## Command Features
662
+ ### Heredoc Syntax
989
663
 
990
- ### Automatic CLI Generation
991
- - `functionName` β†’ `bunosh function:name`
992
- - Function parameters become command arguments
993
- - Last object parameter becomes CLI options
994
- - JSDoc comments become help descriptions
664
+ For multi-line scripts, use heredoc syntax for clean, readable code:
995
665
 
996
- ### Smart Argument Handling
997
- ```javascript
998
- // Function definition
999
- export function deploy(env = 'staging', options = { force: false, verbose: false }) {
1000
- // ...
1001
- }
1002
-
1003
- // CLI usage
1004
- bunosh deploy production --force --verbose
666
+ ```bash
667
+ bunosh -e << 'EOF'
668
+ say('πŸš€ Starting build process...')
669
+ await task('Install Dependencies', () => shell`npm ci`)
670
+ await task('Build', () => shell`npm run build`)
671
+ await task('Test', () => shell`npm test`)
672
+ say('βœ… All tasks completed successfully!')
673
+ EOF
1005
674
  ```
1006
675
 
1007
- ### Help and Documentation
676
+ ### With Environment Variables and Control Flow
677
+
1008
678
  ```bash
1009
- # List all commands
1010
- bunosh
679
+ # Complex script with conditions
680
+ bunosh -e << 'EOF'
681
+ const env = process.env.NODE_ENV || 'development'
682
+ say(`Building for ${env}...`)
683
+
684
+ if (env === 'production') {
685
+ await shell`npm run build:prod`
686
+ await task('Deploy', () => shell`./deploy.sh`)
687
+ } else {
688
+ await shell`npm run build:dev`
689
+ }
1011
690
 
1012
- # Get help for specific command
1013
- bunosh deploy --help
691
+ yell('BUILD COMPLETE!')
692
+ EOF
1014
693
  ```
1015
694
 
1016
- ### Shell Auto-Completion
1017
- Enable tab completion for faster command typing:
695
+ ### Error Handling
1018
696
 
1019
697
  ```bash
1020
- # πŸš€ Auto-setup (recommended) - detects your shell and installs completion
1021
- bunosh setup-completion
1022
-
1023
- # Manual setup if needed
1024
- bunosh completion bash > ~/.bunosh-completion.bash
1025
- echo "source ~/.bunosh-completion.bash" >> ~/.bashrc
1026
- source ~/.bashrc
698
+ # Script with error handling
699
+ bunosh -e << 'EOF'
700
+ task.stopOnFailures()
1027
701
 
1028
- # Now use tab completion
1029
- bunosh dep<TAB> # Completes to 'deploy'
1030
- bunosh <TAB><TAB> # Shows all available commands
702
+ try {
703
+ await shell`npm test`
704
+ await shell`npm run build`
705
+ say('βœ… Success!')
706
+ } catch (error) {
707
+ yell(`❌ Build failed: ${error.message}`)
708
+ process.exit(1)
709
+ }
710
+ EOF
1031
711
  ```
1032
712
 
1033
- **Supported shells:** bash, zsh, fish. The `setup-completion` command automatically detects your shell and handles installation. See [COMPLETION.md](COMPLETION.md) for detailed setup.
713
+ ### JavaScript Execution in GitHub Actions
1034
714
 
1035
- ### Staying Up to Date
1036
-
1037
- **Single Executable:**
1038
- ```bash
1039
- # Check for updates
1040
- bunosh upgrade --check
715
+ Use JavaScript execution to run Bunosh scripts inside CI/CD workflows without creating separate files:
1041
716
 
1042
- # Upgrade to latest version
1043
- bunosh upgrade
717
+ ```yaml
718
+ - name: Build and Deploy
719
+ run: |
720
+ bunosh -e << 'EOF'
721
+ say('πŸš€ Starting deployment...')
1044
722
 
1045
- # Force reinstall current version
1046
- bunosh upgrade --force
1047
- ```
723
+ if (!process.env.NODE_ENV === 'production') return;
1048
724
 
1049
- **NPM Installation:**
1050
- ```bash
1051
- npm update -g bunosh
1052
- ```
725
+ shell`./deploy.sh`
1053
726
 
1054
- ## Advanced Usage
727
+ const response = await fetch('${{ secrets.DEPLOY_WEBHOOK }}', {
728
+ method: 'POST',
729
+ headers: { 'Authorization': 'Bearer ${{ secrets.API_TOKEN }}' }
730
+ })
1055
731
 
1056
- ### Parallel Task Execution
1057
- ```javascript
1058
- const results = await Promise.all([
1059
- task('Task 1', () => exec`sleep 2 && echo "Done 1"`),
1060
- task('Task 2', () => exec`sleep 2 && echo "Done 2"`),
1061
- task('Task 3', () => exec`sleep 2 && echo "Done 3"`)
1062
- ]);
732
+ if (response.ok) {
733
+ yell('πŸš€ DEPLOYMENT COMPLETE!')
734
+ } else {
735
+ yell('❌ DEPLOYMENT FAILED!')
736
+ process.exit(1)
737
+ }
738
+ EOF
739
+ env:
740
+ NODE_ENV: production
1063
741
  ```
1064
742
 
1065
- ### Error Handling
1066
- ```javascript
1067
- export async function deployWithRollback(env) {
1068
- try {
1069
- await deploy(env);
1070
- } catch (error) {
1071
- say('❌ Deployment failed, rolling back...');
1072
- await exec`kubectl rollout undo deployment/myapp`;
1073
- throw error;
1074
- }
1075
- }
1076
- ```
743
+ ### Shell Integration
1077
744
 
1078
- ### NPM Scripts Integration
1079
- Bunosh automatically includes your package.json scripts:
1080
745
  ```bash
1081
- bunosh npm:test # runs npm run test
1082
- bunosh npm:build # runs npm run build
746
+ bunosh -e << 'EOF'
747
+ say('Running database migrations...')
748
+ await shell`npm run migrate`
749
+ say('Migrations completed')
750
+ EOF
1083
751
  ```
1084
752
 
1085
- ## Contributing
1086
753
 
1087
- 1. Fork the repository
1088
- 2. Create a feature branch
1089
- 3. Write tests for new functionality
1090
- 4. Submit a pull request
754
+ ## Examples
755
+
756
+ For comprehensive examples of Bunosh in action, see [docs/examples.md](docs/examples.md).
757
+
758
+ This includes:
759
+ - Feature branch workflow with git worktrees
760
+ - AI-powered release note generation
761
+ - Container building and publishing
762
+ - Kubernetes deployment and rollback
763
+ - AWS infrastructure management
764
+ - And more practical examples
1091
765
 
1092
766
  ## License
1093
767
 
@@ -1095,4 +769,4 @@ MIT License - see LICENSE file for details.
1095
769
 
1096
770
  ---
1097
771
 
1098
- Built with ❀️ for modern JavaScript development
772
+ Cooked with ❀️ from Ukraine πŸ‡ΊπŸ‡¦