bunli

Build type-safe CLIs with Bun. Use when: (1) Creating a new CLI application with Bun, (2) Adding commands with defineCommand/option(), (3) Building a plugin system, (4) Using prompt/spinner APIs for interactive CLIs, (5) Building TUI components, (6) Publishing CLI to npm. For advanced TUI (custom components, animations, full layout control), use the 'opentui' skill. Covers: defineCommand, option() APIs, plugin architecture, bunli CLI commands (dev/build/generate/test/release/init/doctor), create-bunli scaffolding, and utilities.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "bunli" with this command: npx skills add aryalabshq/bunli/aryalabshq-bunli-bunli

Bunli Skill

Build type-safe CLIs with Bun. See references/ for detailed documentation.

Quick Start

# Create new CLI
bunli init my-cli

# Or manually:
mkdir my-cli && cd my-cli
npm init -y
bun add @bunli/core @bunli/utils @bunli/tui
bun add -d bunli typescript

Then create your entry point:

// cli.ts
import { createCLI } from "@bunli/core"
import { defineCommand, option } from "@bunli/core"
import { z } from "zod"

const hello = defineCommand({
  name: "hello",
  description: "Print a greeting",
  options: {
    name: option(z.string().default("World"), { short: "n", description: "Name to greet" }),
    count: option(z.coerce.number().default(1), { short: "c", description: "Number of times" })
  },
  handler: ({ flags, signal }) => {
    if (signal.aborted) return
    for (let i = 0; i < flags.count; i++) {
      console.log(`Hello, ${flags.name}!`)
    }
  }
})

const cli = await createCLI({
  name: "my-cli",
  version: "0.1.0",
})

cli.command(hello)
await cli.run()

Run with: bun run cli.ts

Package Versions

Find current versions:

npm view @bunli/core      # Latest version
npm view @bunli/utils    # Latest version
npm view @bunli/tui      # Latest version
npm view bunli           # CLI version

Quick Decision Trees

"I need to define a command"

Define Command?
├─ Basic command → defineCommand({ name: "mycmd", description: "...", handler: ({ flags }) => {...} })
├─ With options → Add options: { options: { debug: option(z.coerce.boolean(), { short: "d" }) } }
├─ Nested commands → Use defineGroup({ name: "group", description: "...", commands: [...] })
├─ With alias → Add alias: "m" for "mycmd"
└─ With TUI → Add render (optionally keep handler; render commands run without TUI flags)

"I need to add options"

Add Options?
├─ Boolean flag → option(z.coerce.boolean(), { short: "d", description: "Debug output" })
├─ String input → option(z.string(), { description: "Name" })
├─ Number input → option(z.coerce.number(), { description: "Port" })
├─ Enum/choice → option(z.enum(["dev", "prod"]), { description: "Environment" })
├─ With default → option(z.string().default("default"))
└─ Required → option(z.string().min(1))

Important: Use z.coerce.number() and z.coerce.boolean() for numeric and boolean flags because CLI args are strings. Enums should use z.enum(...).

-v is reserved globally for --version, so avoid short: "v" for command-local options.

"I need to create a plugin"

Create Plugin?
├─ Direct plugin → createPlugin({ name: "my-plugin", setup(ctx) {...} })
├─ Factory → createPlugin((options) => ({ name: "my-plugin", ... }))
├─ With store → Add store: { counter: 0 }, access via context.store
└─ Lifecycle hooks → setup, configResolved, beforeCommand, afterCommand

"I need to use prompts"

Use Prompt?
├─ Text input → prompt("Enter name")
├─ Yes/No → confirm("Continue?")
├─ Single choice → select("Select framework", { options: [...] })
├─ Multiple choice → multiselect("Select tools", { options: [...] })
└─ Password → password("Enter password")

"I keep hitting validation errors"

Validation Errors?
├─ Numbers not working → Use z.coerce.number() instead of z.number()
├─ Booleans not working → Use z.coerce.boolean(); pass --flag=true/false for explicit values
├─ Enums not working → Use z.enum([...]), not z.coerce.enum(...)
├─ createCLI returns Promise → Use await createCLI() or .then()
└─ Commands not registering → Use cli.command(cmd), not commands: [cmd]

"I need to build for production"

Build?
├─ Development → bunli dev (hot reload)
├─ Production build → bunli build
├─ Cross-compile → bunli build --targets darwin-arm64,linux-x64
├─ With bytecode → bunli build --bytecode
├─ Generate types → bunli generate
└─ Release → bunli release

"I need advanced TUI (beyond basic forms)"

Advanced TUI?
├─ Custom components beyond Bunli's built-in form/layout set → Use opentui skill
├─ Advanced animations (timeline, keyframes) → Use opentui skill
├─ Full Flexbox layout control → Use opentui skill
├─ Custom renderables → Use opentui skill
└─ Just need Bunli components/forms/charts → Use @bunli/tui (covered here)

"I need predictable TUI buffer behavior"

Buffer Mode?
├─ Global default policy → standard buffer mode
├─ Use fullscreen alternate buffer → set tui.renderer.bufferMode = "alternate" in defineConfig
├─ Per-command override → set command.tui.renderer.bufferMode
└─ Keep standard-buffer output behavior → set bufferMode = "standard" explicitly

Product Index

Core

TopicReference
Command definitionreferences/core/commands.md
Type safety patternsreferences/core/types.md

Plugin System

TopicReference
Plugin architecturereferences/plugin/system.md
Built-in pluginsreferences/plugin/built-ins.md

CLI Commands

TopicReference
CLI commandsreferences/cli/commands.md
Project scaffoldingreferences/cli/scaffold.md

Utilities

TopicReference
Promptsreferences/utils/prompts.md
Spinnersreferences/utils/spinner.md
Colorsreferences/utils/colors.md

TUI

TopicReference
Componentsreferences/tui/components.md
OpenTUI (advanced)Use opentui skill

OpenTUI Integration

TopicReference
When to use OpenTUISee "Relationship with OpenTUI" below

Core Concepts

CLI Structure

// my-cli/src/commands/hello.ts
import { defineCommand, option } from "@bunli/core"
import { z } from "zod"

export const hello = defineCommand({
  name: "hello",
  description: "Greet someone",
  options: {
    name: option(z.string().default("World"), {
      short: "n",
      description: "Name to greet"
    })
  },
  handler: ({ flags }) => {
    console.log(`Hello, ${flags.name}!`)
  }
})

Plugin Creation

import { createPlugin } from "@bunli/core/plugin"

const myPlugin = createPlugin({
  name: "my-plugin",
  store: { count: 0 },
  setup(context) {
    context.registerCommand(myCommand)
  },
  beforeCommand(ctx) {
    ctx.store.count++
  }
})

Using Prompts

handler: async ({ prompt }) => {
  const name = await prompt("What is your name?")
  const proceed = await prompt.confirm("Continue?")
  const framework = await prompt.select("Choose framework", {
    options: [
      { label: "React", value: "react" },
      { label: "Vue", value: "vue" },
      { label: "Svelte", value: "svelte" }
    ]
  })
}

Key Packages

PackagePurpose
@bunli/coreCLI framework (defineCommand, option, createCLI)
@bunli/utilsColors and validation utilities
@bunli/runtime/promptPrompt and spinner APIs
@bunli/tuiTerminal UI components
bunliCLI for building CLIs
create-bunliProject scaffolding
@bunli/generatorType generation from commands

Built-in Plugins

  • @bunli/plugin-ai-detect - Detects AI coding assistants
  • @bunli/plugin-completions - Shell completions (bash, zsh, fish)
  • @bunli/plugin-config - Config loading from multiple sources
  • @bunli/plugin-mcp - MCP tools to CLI commands

Relationship with OpenTUI

Bunli uses OpenTUI as its terminal rendering engine. Understanding when to use each:

Use Bunli (this skill) for:

  • Building CLI applications with commands and options
  • Plugin architecture (auth, config, completions)
  • Type-safe CLI with Zod validation
  • Interactive prompts via @bunli/runtime/prompt
  • Bunli TUI components (Form, SchemaForm, DataTable, ProgressBar, and more)
  • Publishing CLI to npm

Use OpenTUI skill when:

  • Building standalone terminal applications (not a CLI with subcommands)
  • Need advanced animation with timeline, keyframes, easing functions
  • Want full Flexbox/Yoga layout control
  • Creating custom renderable components
  • Need low-level buffer/terminal control
  • Building terminal games or complex interactive UIs

How They Connect

// Bunli TUI uses OpenTUI under the hood
import { Form, SchemaForm } from "@bunli/tui"      // Bunli's React components
// prompt is provided via handler args by Bunli         // Prompt + spinner runtime
import { useTimeline } from "@bunli/tui"          // Re-exported from opentui

// Drop down to OpenTUI for advanced control
import { h, Box, Text, instantiate } from "@opentui/core"
import { createCliRenderer } from "@opentui/core"

Package relationship:

  • @bunli/tui wraps @opentui/react
  • Bunli auto-wires the OpenTUI renderer runtime for render commands
  • @bunli/runtime/prompt provides prompt + spinner APIs used in handlers
  • Bunli TUI hooks (useKeyboard, useTimeline) are re-exported from OpenTUI
  • Renderer options map to OpenTUI renderer settings

When to combine:

  1. Start with Bunli for CLI structure
  2. Use @bunli/tui for common patterns (forms, wizards)
  3. Drop to OpenTUI when you need custom components, advanced animation, or full control

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Web3

Crypto Defi

DeFi收益计算器。APY计算、无常损失、流动性挖矿、质押收益、Gas费、协议对比。DeFi yield calculator with impermanent loss, staking. DeFi、加密货币、收益。

Registry SourceRecently Updated
Web3

Crypto Market Cli

Cryptocurrency market data tool with price checking, portfolio tracking, and market analysis. Use when you need crypto prices, market cap, 24h changes, portf...

Registry SourceRecently Updated
Web3

Hudle Skill

Interact with Hudle (hudle.io), the AI agent economy platform. TRIGGER when user mentions Hudle, gigs, javierai wallet, Axiom, claiming or delivering work, H...

Registry SourceRecently Updated
Web3

Binance Trade Hunter

Binance trading skill for coin analysis, pump detection, and one-click trading via Telegram. Use when the user wants to analyze crypto coins, check market tr...

Registry SourceRecently Updated
00Profile unavailable