The Bunli CLI toolchain for developing, building, and distributing CLI applications.
bun add -g bunliRun your CLI in development mode with hot reloading and automatic type generation:
bunli dev
# With custom entry file
bunli dev --entry src/mycli.ts
# Enable debugging
bunli dev --inspect
# Custom debug port
bunli dev --inspect --port 9230
# Pass arguments to your CLI
bunli dev -- --helpDevelopment options:
--entry, -e- Entry file (defaults to auto-detect)--watch, -w- Watch for changes (default: true)--inspect, -i- Enable debugger--port, -p- Debugger port (default: 9229)--generate- Enable/disable code generation (default: true)--clearScreen- Clear screen on reload (default: true)
Note: Development mode automatically generates TypeScript definitions from your commands when codegen is enabled in your config.
Build your CLI for production with automatic type generation:
# Traditional build (requires Bun runtime)
bunli build
# Build standalone executables for specific platforms
bunli build --targets darwin-arm64,linux-x64
# Build for the current platform only
bunli build --targets native
# Build for all supported platforms
bunli build --targets allNote: The build process automatically generates TypeScript definitions from your commands before building when codegen is enabled in your config.
Generate TypeScript definitions from your CLI commands for enhanced developer experience:
# Generate types once
bunli generate
# Generate types and watch for changes
bunli generate --watch
# Explicit command discovery entry
bunli generate --entry ./src/cli.ts
# Optional fallback directory
bunli generate --directory ./src/commands
# Custom output file
bunli generate --output ./types/commands.gen.tsGenerate options:
--entry, -e- CLI entry file used for command discovery--directory- Optional fallback command source directory--output, -o- Output file path (default: ./.bunli/commands.gen.ts)--watch, -w- Watch for changes and regenerate
The generator creates type-safe command definitions with:
- Autocomplete for command names and options
- Type safety at compile time
- IntelliSense for command metadata
- Helper functions for command discovery
bunli init- Initialize a new Bunli CLI projectbunli dev- Run CLI in development mode with hot reloadingbunli build- Build your CLI for productionbunli generate- Generate TypeScript definitions from commandsbunli doctor completions- Validate generated completion metadatabunli test- Run tests with Bun test runnerbunli release- Release your CLI package
Create a new Bunli CLI project:
# Interactive setup
bunli init
# With project name
bunli init my-cli
# Advanced template
bunli init my-cli --template advanced
# Specify directory
bunli init --name my-cli --dir ./projects
# Skip git/install
bunli init --git false --install falseInit options:
--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)
Run tests for your CLI:
# Run all tests
bunli test
# Watch mode
bunli test --watch
# Generate coverage
bunli test --coverage
# Run tests in all workspace packages
bunli test --allTest options:
--pattern, -p- Test file patterns--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)
Create a release of your CLI:
# Interactive release
bunli release
# Specific version bump
bunli release --version patch
bunli release --version minor
bunli release --version major
bunli release --version 2.0.0
# Dry run
bunli release --dry
# Ignore unfinished release state and start fresh
bunli release --resume=false
# Disable npm publish explicitly
bunli release --npm=false
# Create GitHub release entry
bunli release --github=trueRelease options:
--version, -v- Version to release (patch/minor/major/x.y.z)--tag, -t- Git tag format--npm- Publish to npm (--npm=falseto disable)--github- Create GitHub release (--github=trueto enable)--resume- Resume unfinished release state (--resume=falseto start fresh)--dry, -d- Dry run (runs npm publish with--dry-runwhen npm publish is enabled)--all- Workspace release mode (currently not implemented; exits with error)
Note: bunli release supports npm package release flows, including binary package distribution via release.binary
(optionalDependencies + shim launcher). For standalone GitHub release assets, checksums, and Homebrew automation,
use the bunli-releaser GitHub Action.
Resume behavior notes:
- On failed non-dry runs, Bunli writes checkpoint state to
.bunli/release-state.json. - Next
bunli releaseauto-resumes from that state (with an interactive prompt in TTY shells). - Side-effectful steps (git tag/push, npm publish, GitHub release) are probed and skipped when already complete.
- Successful release clears
.bunli/release-state.json. --no-resumeis unsupported; use--resume=false.
The build command supports several options:
--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 (default: true)--sourcemap, -s- Generate sourcemaps--bytecode- Enable bytecode compilation (experimental)--runtime, -r- Runtime target for non-compiled builds (bun/node)--watch, -w- Watch for changes
Bunli creates standalone executables when you specify target platforms. This bundles your CLI application with the Bun runtime into a single binary that can run without requiring Bun to be installed.
# Build for specific platforms
bunli build --targets darwin-arm64,linux-x64,windows-x64
# Build for current platform only
bunli build --targets native
# Build for all platforms
bunli build --targets allSupported platforms:
darwin-arm64- macOS Apple Silicondarwin-x64- macOS Intellinux-arm64- Linux ARM64linux-x64- Linux x64windows-x64- Windows x64
Create a bunli.config.ts file in your project root:
import { defineConfig } from "bunli";
export default defineConfig({
name: "my-cli",
version: "1.0.0",
commands: {
entry: "./src/cli.ts",
directory: "./src/commands", // optional fallback hint
},
build: {
entry: "./src/cli.ts",
outdir: "./dist",
targets: ["darwin-arm64", "linux-x64"], // Compile for these platforms
compress: true, // Compress multi-platform builds
minify: true,
external: ["some-native-module"],
},
dev: {
watch: true,
inspect: false,
},
tui: {
renderer: {
bufferMode: "alternate", // or 'standard'
},
},
});Default tui.renderer.bufferMode policy:
'standard'by default- set
'alternate'explicitly for fullscreen/blocking terminal flows
The build system works as follows:
-
No targets specified → Traditional JavaScript build
- Creates bundled
.jsfiles with shebangs - Requires Bun (or Node.js) runtime to execute
- Supports multiple entry points
- Creates bundled
-
Targets specified → Standalone executables
- Creates native binaries with embedded Bun runtime
- No runtime dependencies required
- Single entry point only
- Platform-specific subdirectories for multiple targets
To work on Bunli itself:
# Install dependencies
bun install
# Run in development
bun run dev
# Build
bun run build
# Run tests
bun testMIT