bunli
CLI toolchain for developing, building, testing, and distributing Bunli applications
Installation
bash bun add -g bunli
bash npm install -g bunli
bash pnpm add -g bunli
Features
- ๐ Development Mode - Hot reload with Bun's
--hotflag - ๐๏ธ Build System - Create standalone executables or traditional JS builds
- ๐งช Test Runner - Integrated testing with coverage support
- ๐ฆ Release Automation - Version bumping, git tags, and npm publishing
- ๐ฏ Multi-Platform - Build for macOS, Linux, and Windows from any platform
- โ๏ธ Configuration - Flexible
bunli.config.tssystem - ๐ Debugging - Built-in debugger support
- ๐ Workspace Support - Monorepo-friendly commands
- ๐ Shell UI - Terminal components for scripts and workflows
- ๐ง Diagnostics - Built-in doctor command for troubleshooting
Commands
bunli init
Initialize a new Bunli CLI project. This is an alias for create-bunli.
bunli init my-cli
cd my-cliOptions:
--name, -n- Project name--template, -t- Project template (basic,advanced,monorepo)--dir, -d- Directory to create project in--git, -g- Initialize git repository (default: true)--install- Install dependencies (default: true)--package-manager, -p- Package manager to use (bun,pnpm,yarn,npm)
bunli dev
Run your CLI in development mode with hot reload.
bunli dev
# alias: bunli dOptions:
--entry, -e- Entry file (defaults to auto-detect)--generate- Enable codegen (default: true)--clearScreen- Clear screen on reload (default: true)--watch, -w- Watch for changes (default: true)--inspect, -i- Enable debugger--port, -p- Debugger port (default: 9229)
Features:
- Automatic hot reload with Bun's
--hotflag - Automatic type generation when code changes
- Debugger support for breakpoint debugging
- Auto-detection of entry point from package.json or common patterns
- Pass-through arguments to your CLI
Example:
# Run with debugger
bunli dev --inspect
# Run with custom entry and arguments
bunli dev --entry src/cli.ts -- --verbose
# Disable watch mode
bunli dev --watch false
# Disable codegen
bunli dev --generate falsebunli build
Build your CLI for production, either as standalone executables or traditional JavaScript.
bunli build
# alias: bunli bOptions:
--entry, -e- Entry file (defaults to auto-detect)--outdir, -o- Output directory (default:./dist)--outfile- Output filename (for single executable)--targets, -t- Target platforms for compilation (comma-separated)--minify, -m- Minify output--sourcemap, -s- Generate sourcemaps--bytecode- Enable bytecode compilation (experimental)--runtime, -r- Runtime target (bun,node)--watch, -w- Watch for changes
Target Platforms:
native- Current platform onlydarwin-arm64- macOS Apple Silicondarwin-x64- macOS Intellinux-arm64- Linux ARM64linux-x64- Linux x64windows-x64- Windows x64all- All supported platforms
Examples:
# Build traditional JS (requires Bun runtime)
bunli build
# Build standalone executable for current platform
bunli build --targets native
# Build for specific platforms
bunli build --targets darwin-arm64,linux-x64
# Build for all platforms
bunli build --targets all
# Custom output directory
bunli build --outdir ./bin
# Watch mode
bunli build --watchbunli generate
Generate TypeScript type definitions for your commands.
bunli generate
# alias: bunli genOptions:
--entry, -e- CLI entry file used for command discovery--directory- Optional fallback command source directory--output, -o- Output file (default:./.bunli/commands.gen.ts)--watch, -w- Watch for changes and regenerate
Examples:
# Generate types once
bunli generate
# Generate with custom output location
bunli generate --output ./types/commands.ts
# Watch for changes
bunli generate --watch
# Use explicit entry
bunli generate --entry ./src/cli.ts
# Optional fallback directory
bunli generate --directory ./src/commandsType generation is automatically run during bunli dev and bunli build. You typically only need
to run this manually for one-off generation or when using watch mode.
bunli test
Run tests for your CLI using Bun's native test runner.
bunli test
# alias: bunli tOptions:
--pattern, -p- Test file patterns (default:**/*.test.ts); can be specified multiple times--watch, -w- Watch for changes--coverage, -c- Generate coverage report--bail, -b- Stop on first failure--timeout- Test timeout in milliseconds--all- Run tests in all packages (workspace mode)
Examples:
# Run all tests
bunli test
# Run with coverage
bunli test --coverage
# Run specific test files
bunli test --pattern "src/**/*.test.ts"
# Run tests in all workspace packages
bunli test --all
# Watch mode for TDD
bunli test --watchbunli release
Create a release of your CLI with automated version bumping, git tagging, and publishing.
bunli release
# alias: bunli rOptions:
--version, -V- Version to release (patch,minor,major, orx.y.z)--tag, -t- Git tag format (default:v{{version}})--npm- Publish to npm--github- Create GitHub release--resume- Resume from unfinished release state (default: true)--dry, -d- Dry run - show what would be done without making changes
Features:
- Interactive version selection
- Automated version bumping following semver
- Git tag creation and pushing
- npm publishing with proper build step
- GitHub release creation (notes only; no build artifacts)
- Resume support for interrupted releases
- Dry run mode for testing
Examples:
# Interactive release
bunli release
# Specific version bump
bunli release --version patch
# Major version with GitHub release
bunli release --version major --github
# Dry run to preview changes
bunli release --dry
# Skip npm publish
bunli release --npm=false
# Skip GitHub release
bunli release --github=false
# Don't resume from previous state
bunli release --resume=falseUse --npm=false (not --no-npm) to disable npm publishing. Boolean options work as --flag
(true) or --flag=false (false).
bunli doctor
Run diagnostics for Bunli projects to identify and fix common issues.
bunli doctorSubcommands:
bunli doctor completions
Check shell completion setup and fix issues.
bunli doctor completionsOptions:
--shell- Target shell (bash,zsh,fish,powershell)
Examples:
# Check all shell completions
bunli doctor completions
# Fix zsh completions
bunli doctor completions --shell zsh
# Fix fish completions
bunli doctor completions --shell fishbunli shell
Shell UI helpers for scripts and terminal workflows. A group of 12 commands for building interactive terminal experiences.
bunli shell <subcommand>bunli shell confirm
Ask a yes/no question.
bunli shell confirm "Continue with deployment?"Options:
--default- Default value (default: false)--affirmative- Affirmative label (default: "Yes")--negative- Negative label (default: "No")--timeout, -t- Timeout in seconds
bunli shell choose
Choose from a list of options.
bunli shell choose Option1 Option2 Option3
# Or pipe via stdin:
echo -e "Option1\nOption2\nOption3" | bunli shell chooseOptions:
--multiple- Allow multiple selections--limit- Max selections--height- Visible items (default: 10)--ordered- Maintain selection order
bunli shell input
Prompt for single-line text input.
bunli shell input "Enter your name:"Options:
--placeholder- Placeholder text--prompt- Prompt message--value- Default value--char-limit- Character limit
bunli shell spin
Run a command with a spinner.
bunli shell spin "Building..." -- bun run buildOptions:
--title- Spinner title (default: "Loading...")
bunli shell pager
View content in a scrollable pager.
bunli shell pager --file README.md
# Or pipe via stdin:
cat README.md | bunli shell pagerOptions:
--file, -f- File to display
bunli shell filter
Filter lines from stdin.
echo -e "foo\nbar\nbaz" | bunli shell filter "b*"bunli shell file
Interactive file picker.
bunli shell filebunli shell style
Apply ANSI styling to text.
bunli shell style --bold "Important text"bunli shell join
Join lines with a delimiter.
echo -e "a\nb\nc" | bunli shell join ", "
# Output: a, b, cbunli shell write
Write stdin to a file.
echo "content" | bunli shell write output.txtbunli shell format
Format JSON or plain text.
echo '{"a":1}' | bunli shell format jsonbunli shell log
Structured logging output.
bunli shell log --level info "Server started"Configuration
Create a bunli.config.ts file in your project root to configure the CLI behavior:
import { defineConfig } from "@bunli/core";
export default defineConfig({
name: "my-cli",
version: "1.0.0",
description: "My awesome CLI",
// Command configuration
commands: {
entry: "./src/cli.ts",
directory: "./src/commands",
},
// Build configuration
build: {
entry: "./src/cli.ts",
outdir: "./dist",
targets: ["darwin-arm64", "linux-x64", "windows-x64"],
compress: true,
external: ["@aws-sdk/*"],
minify: true,
sourcemap: false,
},
// Development configuration
dev: {
watch: true,
inspect: false,
port: 9229,
},
// Test configuration
test: {
pattern: ["**/*.test.ts", "**/*.spec.ts"],
coverage: false,
watch: false,
},
// Release configuration
release: {
npm: true,
github: true,
tagFormat: "v{{version}}",
conventionalCommits: true,
binary: {
packageNameFormat: "{{name}}-{{platform}}",
shimPath: "bin/run.mjs",
},
},
// Workspace configuration (monorepos)
workspace: {
packages: ["packages/*"],
versionStrategy: "independent",
},
});Entry Point Detection
The CLI automatically detects your entry point in this order:
--entryflagbuild.entryin bunli.config.tsbinfield in package.json- Common patterns:
src/cli.tssrc/index.tssrc/main.tscli.tsindex.tsmain.ts
Standalone Executables
Build standalone executables that bundle your CLI with the Bun runtime:
# Build for current platform
bunli build --targets native
# Build for all platforms
bunli build --targets all
# Build for specific platforms
bunli build --targets darwin-arm64,linux-x64,windows-x64Output structure:
dist/
โโโ darwin-arm64/
โ โโโ my-cli
โโโ darwin-x64/
โ โโโ my-cli
โโโ linux-x64/
โ โโโ my-cli
โโโ windows-x64/
โโโ my-cli.exeWith compression enabled:
dist/
โโโ darwin-arm64.tar.gz
โโโ darwin-x64.tar.gz
โโโ linux-x64.tar.gz
โโโ windows-x64.tar.gzWorkspace Support
For monorepos, the CLI supports workspace-aware commands:
# Run tests in all packages
bunli test --all
# Build for all platforms (single package)
bunli build --targets all
# Workspace release mode is currently not implemented
# bunli release --all
# Run dev in specific package
cd packages/my-package && bunli devEnvironment Variables
The CLI sets these environment variables:
NODE_ENV- Set todevelopmentin dev mode,testin test mode,productionin build modeBUNLI_VERSION- The version of the bunli CLI- Standard Bun environment variables
Advanced Usage
Debug Mode
Enable debugging for your CLI during development:
# Start with debugger
bunli dev --inspect
# Custom debugger port
bunli dev --inspect --port 9230Then attach your debugger (VS Code, Chrome DevTools, etc.) to the specified port.
Custom Build Pipeline
Extend the build process with pre/post hooks:
// bunli.config.ts
export default defineConfig({
build: {
onBeforeBuild: async () => {
// Generate types, clean directories, etc.
},
onAfterBuild: async (result) => {
// Copy additional files, generate docs, etc.
},
},
});Cross-Platform Considerations
When building for multiple platforms:
// bunli.config.ts
export default defineConfig({
build: {
targets: ["darwin-arm64", "linux-x64", "windows-x64"],
external: process.platform === "win32" ? ["node-pty"] : ["windows-specific-module"],
},
});Continuous Integration
Example GitHub Actions workflows:
CI (build + test):
name: Build and Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- name: Install dependencies
run: bun install
- name: Run tests
run: bunli test --coverage
- name: Build for all platforms
run: bunli build --targets allbunli build can optionally compress multi-target builds into dist/<target>.tar.gz. For
stable, release-ready archives and checksums, use bunli-releaser.
Release (binaries + checksums + Homebrew via bunli-releaser):
name: Release
on:
push:
tags:
- "v*.*.*"
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: AryaLabsHQ/bunli-releaser@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# Optional Homebrew update:
# brew-tap: <owner>/<homebrew-tap>
# brew-token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
# brew-pr: "true"
# existing-assets: "fail" # or "skip"If you're using bunli-releaser, keep build.compress disabled in bunli.config.ts.
Troubleshooting
Command not found: If bunli is not found after installation, ensure your global bin
directory is in PATH. Alternatively, use bunx bunli to run without global installation.
Common Issues
Build fails with module errors:
- Check that all dependencies are installed
- Verify entry point exists
- Use
--externalfor native modules - Check TypeScript configuration
Hot reload not working:
- Ensure you're using
bunli dev - Check that Bun version supports
--hot - Some file changes may require manual restart
Tests not found:
- Verify test file pattern matches your test files
- Default pattern is
**/*.test.ts - Use
--patternto specify custom patterns
Shell completions not working:
- Run
bunli doctor completionsto diagnose - Ensure your shell is configured to source completion scripts
- Restart your shell after installing completions
API Reference
CLI Options
All commands support these global options:
--help, -h- Show help for command--version, -v- Show CLI version--config, -c- Path to config file (default: ./bunli.config.ts)--verbose- Enable verbose logging--quiet, -q- Suppress non-error output
Configuration Schema
The configuration is validated using Zod. See the Configuration guide for the complete schema.
See Also
- Getting Started - Quick start guide
- Configuration - Detailed configuration options
- Distribution Guide - Publishing and distribution strategies
- @bunli/test - Testing utilities for CLI applications