Skip to content
Development
Skill

/bun-shell

Bun shell scripting with Bun.$, Bun.spawn, subprocess management. Use for shell commands, template literals, or command execution.

From plugin
claude-skills
241183 skills42 agents62 commands2 MCP

Claude Code

$ npx -y skills add secondsky/claude-skills --skill bun-shell --agent claude-code

SKILL.md

bun-shell.SKILL.md
name: bun-shell
description: Bun shell scripting with Bun.$, Bun.spawn, subprocess management. Use for shell commands, template literals, or command execution.
license: MIT

Bun Shell

Bun provides powerful shell scripting capabilities with template literals and spawn APIs.

Bun.$ (Shell Template)

Basic Usage

import { $ } from "bun";

// Run command
await $`echo "Hello World"`;

// Get output
const result = await $`ls -la`.text();
console.log(result);

// JSON output
const pkg = await $`cat package.json`.json();
console.log(pkg.name);

Variable Interpolation

import { $ } from "bun";

const name = "world";
const dir = "./src";

// Safe interpolation (escaped)
await $`echo "Hello ${name}"`;
await $`ls ${dir}`;

// Array expansion
const files = ["a.txt", "b.txt", "c.txt"];
await $`touch ${files}`;

Piping

import { $ } from "bun";

// Pipe commands
const result = await $`cat file.txt | grep "pattern" | wc -l`.text();

// Chain with JavaScript
const files = await $`ls -la`.text();
const lines = files.split("\n").filter(line => line.includes(".ts"));

Error Handling

import { $ } from "bun";

// Throws on non-zero exit
try {
  await $`exit 1`;
} catch (err) {
  console.log(err.exitCode); // 1
  console.log(err.stderr);
}

// Quiet mode (no throw)
const result = await $`exit 1`.quiet();
console.log(result.exitCode); // 1

// Check exit code
const { exitCode } = await $`grep pattern file.txt`.quiet();
if (exitCode !== 0) {
  console.log("Pattern not found");
}

Output Types

import { $ } from "bun";

// Text
const text = await $`echo hello`.text();

// JSON
const json = await $`cat data.json`.json();

// Lines
const lines = await $`ls`.lines();

// Blob
const blob = await $`cat image.png`.blob();

// ArrayBuffer
const buffer = await $`cat binary.dat`.arrayBuffer();

Environment Variables

import { $ } from "bun";

// Set env for command
await $`echo $MY_VAR`.env({ MY_VAR: "value" });

// Access current env
$.env.MY_VAR = "value";
await $`echo $MY_VAR`;

// Clear env
await $`env`.env({});

Working Directory

import { $ } from "bun";

// Change directory for command
await $`pwd`.cwd("/tmp");

// Or globally
$.cwd("/tmp");
await $`pwd`;

Bun.spawn

Basic Spawn

const proc = Bun.spawn(["echo", "Hello World"]);
const output = await new Response(proc.stdout).text();
console.log(output); // "Hello World\n"

With Options

const proc = Bun.spawn(["node", "script.js"], {
  cwd: "./project",
  env: {
    NODE_ENV: "production",
    ...process.env,
  },
  stdin: "pipe",
  stdout: "pipe",
  stderr: "pipe",
});

// Write to stdin
proc.stdin.write("input data\n");
proc.stdin.end();

// Read stdout
const output = await new Response(proc.stdout).text();
const errors = await new Response(proc.stderr).text();

// Wait for exit
const exitCode = await proc.exited;

Stdio Options

// Inherit (use parent's stdio)
Bun.spawn(["ls"], { stdio: ["inherit", "inherit", "inherit"] });

// Pipe (capture output)
Bun.spawn(["ls"], { stdin: "pipe", stdout: "pipe", stderr: "pipe" });

// Null (ignore)
Bun.spawn(["ls"], { stdout: null, stderr: null });

// File (redirect to file)
Bun.spawn(["ls"], {
  stdout: Bun.file("output.txt"),
  stderr: Bun.file("errors.txt"),
});

Streaming Output

const proc = Bun.spawn(["tail", "-f", "log.txt"], {
  stdout: "pipe",
});

const reader = proc.stdout.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  console.log(new TextDecoder().decode(value));
}

Bun.spawnSync

// Synchronous execution
const result = Bun.spawnSync(["ls", "-la"]);

console.log(result.exitCode);
console.log(result.stdout.toString());
console.log(result.stderr.toString());
console.log(result.success); // exitCode === 0

Shell Scripts

Shebang Scripts

#!/usr/bin/env bun
import { $ } from "bun";

// Script logic
const branch = await $`git branch --show-current`.text();
console.log(`Current branch: ${branch.trim()}`);

await $`npm test`;
await $`npm run build`;
chmod +x script.ts
./script.ts

Complex Script

#!/usr/bin/env bun
import { $ } from "bun";

async function deploy() {
  console.log("🚀 Starting deployment...");

  // Check for uncommitted changes
  const status = await $`git status --porcelain`.text();
  if (status.trim()) {
    console.error("❌ Uncommitted changes found!");
    process.exit(1);
  }

  // Run tests
  console.log("🧪 Running tests...");
  await $`bun test`;

  // Build
  console.log("🏗️ Building...");
  await $`bun run build`;

  // Deploy
  console.log("📦 Deploying...");
  await $`rsync -avz ./dist/ server:/app/`;

  console.log("✅ Deployment complete!");
}

deploy().catch((err) => {
  console.error("❌ Deployment failed:", err);
  process.exit(1);
});

Parallel Commands

import { $ } from "bun";

// Run in parallel
await Promise.all([
  $`npm run lint`,
  $`npm run typecheck`,
  $`npm run test`,
]);

// Or with spawn
const procs = [
  Bun.spawn(["npm", "run", "lint"]),
  Bun.spawn(["npm", "run", "typecheck"]),
  Bun.spawn(["npm", "run", "test"]),
];

await Promise.all(procs.map(p => p.exited));

Interactive Commands

import { $ } from "bun";

// Pass through stdin
const proc = Bun.spawn(["node"], {
  stdin: "inherit",
  stdout: "inherit",
  stderr: "inherit",
});

await proc.exited;

Process Management

const proc = Bun.spawn(["long-running-process"]);

// Kill process
proc.kill(); // SIGTERM
proc.kill("SIGKILL"); // Force kill

// Check if running
console.log(proc.killed);

// Get PID
console.log(proc.pid);

// Wait with timeout
const timeout = setTimeout(() => proc.kill(), 5000);
await proc.exited;
clearTimeout(timeout);

Common Patterns

Run npm/bu

Read more
@secondsky
Ships withclaude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

241183 skills42 agents2 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
241
Star history of secondsky/claude-skills on GitHub, a chart by star-history.com

Other skills on claude-skills.

aceternity-ui

aceternity-ui

100+ animated React components (Aceternity UI) for Next.js with Tailwind. Use for hero sections, parallax, 3D effects, or…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about bun-shell.

Which coding agents can use bun-shell?
bun-shell installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.