bunosh 0.4.1 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,15 +20,6 @@ Bunosh is a modern task runner that turns your JavaScript functions into CLI com
20
20
 
21
21
  > *Named after **banosh**, a traditional Ukrainian dish from cornmeal cooked with various ingredients*
22
22
 
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
23
 
33
24
  ## Hello World
34
25
 
@@ -66,16 +57,24 @@ export async function helloWorld(name = 'person') {
66
57
  | **Ecosystem** | CLI tools | npm packages | Plugin dependent | ✅ Bash + npm |
67
58
  | **Composability** | Commands | Separate scripts | Task dependencies | ✅ Import any JS code |
68
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
+
69
67
  ## TOC
70
68
 
71
69
  - [Installation](#installation)
70
+ - [MCP Integration](#mcp-integration)
72
71
  - [Quickstart](#quickstart)
73
72
  - [Commands](#commands)
74
- - [Personal Commands (My Namespace)](#personal-commands-my-namespace)
75
73
  - [Tasks](#tasks)
76
74
  - [Input/Output](#inputoutput)
77
75
  - [Task Control](#task-control)
78
76
  - [AI Integration](#ai-integration)
77
+ - [MCP](#mcp)
79
78
  - [Examples](#examples)
80
79
 
81
80
  ## Installation
@@ -135,21 +134,33 @@ export async function build(env = 'production') {
135
134
  }
136
135
  ```
137
136
 
138
- That's it! Your function is now a CLI command.
137
+ ## Commands
138
+
139
+ By default, Bunosh loads commands from `Bunoshfile.js` in the current directory.
140
+
141
+ ```
142
+ # reads Bunoshfile form cwd and runs hello()
143
+ bunosh hello
144
+ ```
145
+
146
+ You can specify custom configuration file using CLI option:
139
147
 
140
- 3. **Run it:**
141
148
  ```bash
142
- # build for production
143
- bunosh build
149
+ # Load commands from a different file
150
+ bunosh --bunoshfile Bunoshfile.dev.js hello
151
+ ```
144
152
 
145
- # build for staging
146
- bunosh build staging
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
147
159
 
148
- # build for development
149
- bunosh build development
160
+ # One-time usage
161
+ BUNOSHFILE=Bunoshfile.prod.js bunosh deploy
150
162
  ```
151
163
 
152
- ## Commands
153
164
 
154
165
  ### Creating Commands
155
166
 
@@ -219,63 +230,173 @@ Functions are automatically converted to kebab-case commands:
219
230
  | `npmInstall` | `bunosh npm:install` |
220
231
  | `buildAndDeploy` | `bunosh build:and-deploy` |
221
232
 
222
- ### Personal Commands (My Namespace)
223
233
 
224
- Bunosh automatically loads commands from your home directory (`~/Bunoshfile.js`) and makes them available in any project with the `my:` namespace prefix.
225
234
 
226
- **Create your personal toolkit:**
227
235
 
236
+ ### Project Namespaces
237
+
238
+ Organize your project tasks by creating multiple Bunoshfiles with namespaces. This helps keep large projects organized and separates concerns.
239
+
240
+ **Create namespace files:**
241
+ ```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
253
+ ```
254
+
255
+ **Example structure:**
228
256
  ```javascript
229
- // ~/Bunoshfile.js - Your global commands available everywhere
257
+ // Bunoshfile.js - Core project tasks
258
+ export function build() {
259
+ console.log('Building project...');
260
+ }
230
261
 
231
- /**
232
- * Quick deployment to personal staging server
233
- */
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!');
262
+ export function test() {
263
+ console.log('Running tests...');
238
264
  }
239
265
 
240
- /**
241
- * Personal backup script
242
- */
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!');
266
+ // Bunoshfile.dev.js - Development tasks
267
+ export function start() {
268
+ console.log('Starting dev server...');
247
269
  }
248
270
 
249
- /**
250
- * Quick project setup
251
- */
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!`);
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...');
257
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
258
296
  ```
259
297
 
260
- **Available in any project:**
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
261
303
 
304
+ 1. **Start MCP server** in your project directory:
262
305
  ```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
306
+ # Uses Bunoshfile.js from current directory
307
+ bunosh -mcp
267
308
 
268
- # List all your personal commands
269
- bunosh --help # Shows "My Commands" section
309
+ # Or with custom Bunoshfile
310
+ bunosh --bunoshfile Bunoshfile.dev.js -mcp
270
311
  ```
271
312
 
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
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>
279
400
 
280
401
  ## Tasks
281
402
 
@@ -301,6 +422,9 @@ console.log(result.output); // Command output or result data
301
422
  console.log(result.hasFailed); // true if status is 'fail'
302
423
  console.log(result.hasSucceeded); // true if status is 'success'
303
424
  console.log(result.hasWarning); // true if status is 'warning'
425
+
426
+ // Get structured JSON data from any task (async method)
427
+ const json = await result.json();
304
428
  ```
305
429
 
306
430
  Now let's look into other tasks:
@@ -335,6 +459,11 @@ await exec`echo $NODE_ENV`.env({ NODE_ENV: 'production' });
335
459
 
336
460
  // In specific directory
337
461
  await exec`npm install`.cwd('/tmp/project');
462
+
463
+ // Get structured output with stdout, stderr, exit code and lines
464
+ const result = await exec`git status --porcelain`;
465
+ const data = await result.json();
466
+ // Returns: { stdout: "...", stderr: "...", exitCode: 0, lines: [...] }
338
467
  ```
339
468
 
340
469
  By default task prints live line-by-line output from stdout and stderr. To disable output, use `silent` method:
@@ -359,6 +488,11 @@ Optimized for simple, fast commands when running under Bun:
359
488
  await shell`pwd`;
360
489
  await shell`ls -la`;
361
490
  await shell`cat package.json`;
491
+
492
+ // Get structured output with stdout, stderr, exit code and lines
493
+ const result = await shell`ls -la`;
494
+ const data = await result.json();
495
+ // Returns: { stdout: "...", stderr: "...", exitCode: 0, lines: [...] }
362
496
  ```
363
497
 
364
498
  For more details see [bun shell](https://bun.sh/docs/runtime/shell) reference
@@ -390,6 +524,11 @@ export async function healthCheck(url) {
390
524
  yell(`❌ Service down: ${response.status}`);
391
525
  }
392
526
  }
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
393
532
  ```
394
533
 
395
534
  ### File Operations
@@ -564,7 +703,7 @@ Gracefully handle operations that might fail:
564
703
  * Check service availability
565
704
  */
566
705
  export async function checkServices() {
567
- const dbConnected = await task.try(shell`nc -z localhost 5432`);
706
+ const dbConnected = await task.try(() => shell`nc -z localhost 5432`);
568
707
 
569
708
  if (dbConnected) {
570
709
  say('✅ Database connected');
@@ -623,7 +762,7 @@ export async function commit() {
623
762
  return;
624
763
  }
625
764
 
626
- const commit = await ai(
765
+ const response = await ai(
627
766
  `Generate a conventional commit message for: ${diff.output}`,
628
767
  {
629
768
  type: 'Commit type (feat/fix/docs/chore)',
@@ -633,6 +772,8 @@ export async function commit() {
633
772
  }
634
773
  );
635
774
 
775
+ const commit = await response.json();
776
+
636
777
  const message = commit.scope
637
778
  ? `${commit.type}(${commit.scope}): ${commit.subject}\n\n${commit.body}`
638
779
  : `${commit.type}: ${commit.subject}\n\n${commit.body}`;