{"id":49157546,"url":"https://github.com/bdombro/bun-argsbarg","last_synced_at":"2026-07-05T01:01:53.191Z","repository":{"id":353053970,"uuid":"1217397863","full_name":"bdombro/bun-argsbarg","owner":"bdombro","description":"Build beautiful, well-behaved CLI apps with Bun","archived":false,"fork":false,"pushed_at":"2026-07-04T16:43:40.000Z","size":830,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-04T17:13:20.046Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bdombro.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-21T21:03:18.000Z","updated_at":"2026-07-04T16:43:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bdombro/bun-argsbarg","commit_stats":null,"previous_names":["bdombro/bun-argsbarg"],"tags_count":56,"template":false,"template_full_name":null,"purl":"pkg:github/bdombro/bun-argsbarg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdombro%2Fbun-argsbarg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdombro%2Fbun-argsbarg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdombro%2Fbun-argsbarg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdombro%2Fbun-argsbarg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bdombro","download_url":"https://codeload.github.com/bdombro/bun-argsbarg/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdombro%2Fbun-argsbarg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35140189,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-22T10:04:55.935Z","updated_at":"2026-07-05T01:01:53.147Z","avatar_url":"https://github.com/bdombro.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Logo\n\n\n\n[GitHub](https://github.com/bdombro/bun-argsbarg)\n[License: MIT](LICENSE)\n[npm version](https://www.npmjs.com/package/argsbarg)\n[Bun](https://bun.sh)\n\nBuild beautiful, well-behaved CLI+MCP apps with Bun — **no third-party runtime dependencies**. \n\nWhy another CLI parser?\n\n*Schema-first* — define your entire CLI’s structure, commands, options, and help in a single, explicit data model, making the command-line interface auto-validated, centralized, clear, and self-describing upfront.\n\n*AI Friendly* — Generate and install rich skills, mcp server, docs based on the schema.\n\n*Beautiful* `-h` *screens* — scoped help at any routing depth, rendered in rounded UTF-8 boxes with tables, terminal-width wrapping, and color when stdout is a TTY. Errors print in red with contextual help on stderr.\n\n*Shell completions* — `completion bash`, `completion zsh`, and `completion fish` built-ins generate scripts consumed by Homebrew during formula `install` (`generate_completions_from_executable`). See [docs/distribution-homebrew.md](docs/distribution-homebrew.md).\n\n*Bun-optimized* — built from the ground up for Bun and TypeScript, leveraging Bun’s performance and modern JavaScript features without any extra dependencies.\n\nAlso checkout ArgsBarg for [cpp](https://github.com/bdombro/cpp-argsbarg), [nim](https://github.com/bdombro/nim-argsbarg), and [swift](https://github.com/bdombro/swift-argsbarg)!\n\nHalps! --\u003e\nhelp-preview.png\n\nSub-level Halps! --\u003e\nhelp-l2-preview.png\n\nShell completions! --\u003e\ncompletions-preview.png\n\n## Usage\n\n```typescript\nimport { Cli, type CliProgram, CliOptionKind } from \"argsbarg\";\n\nconst program = {\n  key: \"helloapp\",\n  version: \"1.0.0\",\n  description: \"Tiny demo.\",\n  positionals: [\n    {\n      name: \"name\",\n      description: \"Who to greet.\",\n      kind: CliOptionKind.String,\n      argMin: 0,\n      argMax: 1,\n    },\n  ],\n  options: [\n    {\n      name: \"verbose\",\n      description: \"Enable extra logging.\",\n      kind: CliOptionKind.Presence,\n      shortName: \"v\",\n    },\n  ],\n  handler: async (ctx) =\u003e {\n    const name = ctx.args[0] ?? \"world\";\n    if (ctx.hasFlag(\"verbose\")) { \n      console.log(\"verbose mode\"); \n    }\n    console.log(`hello ${name}`);\n  },\n} satisfies CliProgram;\n\nconst cli = new Cli(program);\nawait cli.run();\n```\n\n`Cli.run()` parses `process.argv`, prints help or errors, dispatches the leaf handler, and **exits the process**.\n\n## What is it?\n\nEverything you need for a first-class CLI:\n\n- **Nested subcommands** (router nodes with `commands`, leaf nodes with `handler`)\n- **POSIX-style options** (`-x`, `--long`, `--long=value`) — kinds: presence, string, number, **enum** (`choices` array)\n- **Bundled presence flags** (`-abc`)\n- **Positional arguments and varargs tails** (`CliPositional` objects on `positionals`)\n- **Scoped help** at any routing depth (`-h` / `--help`)\n- **Default-command fallback** (`CliFallbackMode`)\n- **Option separator** (`--` to stop option parsing)\n- **Rich help**: rounded UTF-8 boxes, tables, terminal width detection (`process.stdout.columns`), colors when stdout/stderr is a TTY\n- **TypeScript-native**: Typed option accessors (`ctx.typedOpt\u003cT\u003e`) and `async/await` handler support.\n\n\n\n## Built-ins\n\nEvery app gets:\n\n- `-h` / `--help` at any routing depth (scoped help).\n- `completion bash` **/** `completion zsh` **/** `completion fish` — print shell completion scripts to stdout (injected by `Cli.run()`).\n- `version` — print `CliProgram.version` (`myapp version`).\n- `mcp` — when `mcpServer.enabled` is `true`, run as an MCP stdio server (`myapp mcp`).\n- `docs` — when `docs.enabled` is `true`, print bundled markdown topics, schema JSON, API markdown, and generated skill content (`myapp docs`, `myapp docs readme`, `myapp docs schema`, `myapp docs api`, `myapp docs skill`, …). See [docs/bundled-docs.md](docs/bundled-docs.md).\n- `configure` — manage agent skills, MCP config, and app config (`myapp configure --sync --yes` after Homebrew install). See [docs/configure.md](docs/configure.md).\n\nDo not declare a top-level command named `completion`, `version`, or `configure` — they are reserved.\nWhen `mcpServer.enabled` is `true`, do not declare a top-level command named `mcp` — it is reserved for the MCP built-in.\nWhen `docs.enabled` is `true`, do not declare a top-level command named `docs` — it is reserved for the docs built-in.\n\n### MCP (AI agents)\n\nOpt in on the program root with `mcpServer: { enabled: true }`, then run `myapp mcp` for a stdio MCP server. Each leaf command becomes a tool; the CLI tree is available as resource `\u003csanitized-key\u003e://schema` (same as `myapp docs schema`). Handlers can read `ctx.invocation`; use `cli.invoke(argv)` for headless testing.\n\nSee **[docs/mcp.md](docs/mcp.md)** for configuration, env bootstrapping, custom resources, Cursor setup, and protocol details. See **[docs/cli-program.md](docs/cli-program.md)** for schema authoring (consumer apps: run `bunx argsbarg create` or refresh with `bun scripts/merge-cli-program-rule.ts .` from the argsbarg package).\n\n### Configure CLI\n\nShip via **Homebrew** (tap-from-repo). The formula installs the binary and shell completions; `post_install` runs agent artifact refresh. Private taps need `HOMEBREW_GITHUB_API_TOKEN` on install — see [docs/distribution-homebrew.md](docs/distribution-homebrew.md#end-user-install).\n\n```bash\nbrew tap \u003corg\u003e/\u003crepo\u003e git@github.com:\u003corg\u003e/\u003crepo\u003e.git\nHOMEBREW_GITHUB_API_TOKEN=\"$(gh auth token)\" brew install \u003ctap\u003e/myapp\nmyapp configure    # interactive per-target setup; opt-in app config wizard\n```\n\nSee **[docs/distribution-homebrew.md](docs/distribution-homebrew.md)** for formula patterns and `bunx argsbarg create`. See **[docs/configure.md](docs/configure.md)** for `configure`, `--sync`, `--remove-all`, and `--status`.\n\n### Shell completions\n\nHomebrew installs completion scripts during `brew install` via `generate_completions_from_executable`. The CLI still exposes generation for formula authors:\n\n```bash\nmyapp completion bash\nmyapp completion zsh\nmyapp completion fish\n```\n\nUsers configure their shell per [Homebrew Shell Completion](https://docs.brew.sh/Shell-Completion).\n\n## Quick Start\n\n```bash\nbun add argsbarg\n```\n\n\n\n### Cursor / AI agents\n\nArgsbarg ships authoring docs in `node_modules/argsbarg/docs/`. Agents do not load them unless your repo points there — copy the thin Cursor rule after install (it tells agents to **read** `cli-program.md`, not duplicate it):\n\n```bash\nmkdir -p .cursor/rules\nmkdir -p .cursor/rules\nbun scripts/merge-cli-program-rule.ts . \\\n  node_modules/argsbarg/examples/full-example/.cursor/rules/cli-program.mdc\n```\n\nAdd app-specific conventions in a second rule if needed. Copy the rule from the template, then add a `**\u003cyour-app\u003e conventions:**` block at the bottom (see **Cursor rule** in [docs/cli-program.md](docs/cli-program.md)). Documentation map: **[docs/README.md](docs/README.md)**.\n\n## How it works\n\n1. Build a **program root** with `satisfies CliProgram` (or `: CliProgram`): `key` is the app name, `commands` are top-level subcommands, `options` are global flags. A router root must not set `handler` or declare `positionals` (validated at startup). A leaf root may set `handler` and `positionals` directly. Use `fallbackCommand` / `fallbackMode` on any **routing node** for default subcommand routing (not root-only).\n2. Call `await new Cli(program).run()` — validates, parses argv, renders help or errors, invokes the leaf handler, and `process.exit`s with status **0** on success, **1** on implicit help or error (explicit `--help` → **0**).\n3. From a handler, `cliErrWithHelp(ctx, \"message\")` prints a red error line plus contextual help on stderr and exits **1**.\n\n\n\n### Fallback modes (`CliFallbackMode`)\n\n\n| Mode               | Empty argv         | Unknown first token                                  |\n| ------------------ | ------------------ | ---------------------------------------------------- |\n| `MissingOnly`      | Default command    | Error                                                |\n| `MissingOrUnknown` | Default command    | Default command (token becomes argv for the default) |\n| `UnknownOnly`      | Root help (exit 1) | Default command                                      |\n\n\nWith `MissingOrUnknown` / `UnknownOnly`, unrecognized flags at the **current routing node** stop option consumption and the remainder is passed to the default command.\n\nSet `fallbackCommand` / `fallbackMode` on nested routers too — e.g. `docs` with `fallbackCommand: \"guide\"` routes `myapp docs` to the guide leaf without requiring a root-level default.\n\n### Positionals (help labels)\n\nAdd `CliPositional` entries to the command’s `positionals` list (separate from `CliOption` flags). With `argMax: 0`, the tail accepts at least `argMin` tokens and has no upper bound unless you set `argMax` \u003e 0.\n\n\n| Fields                                                           | Label    |\n| ---------------------------------------------------------------- | -------- |\n| omit `argMin` / `argMax` (defaults `1` / `1`, one required word) | `\u003cn\u003e`    |\n| `argMin: 0`, `argMax: 1`                                         | `[n]`    |\n| `argMin: 0`, `argMax: 0`                                         | `[n...]` |\n| `argMin: 1`, `argMax: 0`                                         | `\u003cn...\u003e` |\n\n\n\n\n### Reading values (`CliContext`)\n\n- `ctx.flag(\"verbose\")` / `ctx.hasFlag(\"verbose\")` — presence options (`boolean`).\n- `ctx.stringOpt(\"name\")` / `ctx.numberOpt(\"count\")` — `string | undefined` / `number | null`.\n- `ctx.durationOpt(\"timeout\")` — duration options (`format: CliValueFormat.Duration`) as milliseconds.\n- `ctx.commaListOpt(\"services\")` — comma-list options as `string[] | undefined`.\n- `ctx.dateOpt(\"on\")` / `ctx.dateTimeOpt(\"since\")` — ISO date / date-time options.\n- `ctx.readLeafInputs()` — coerced option and positional values for the current leaf (schema-driven).\n- `ctx.typedOpt\u003cT\u003e(\"custom\", parseFn)` — custom parsing for type-safe option resolution.\n- `ctx.args` — positional words in order as `string[]`.\n- `ctx.positional(\"name\")` — named positional lookup; varargs slots return `string[]`, single slots return `string | undefined`.\n- `ctx.program` — program root (`CliProgram`) for contextual help.\n\n\n\n### Capabilities (built-ins)\n\n`completion`, `version`, `install`, and `mcp` are not part of your schema — they are injected at runtime from program-level config (`mcpServer`, `install`, `docs`). Reserved command names: `completion` and `version` always; `install` unless `install.enabled: false`; `mcp` when `mcpServer.enabled` is `true`; `docs` when `docs.enabled` is `true`.\n\n## Examples\n\nCheck the `examples/` directory for full working scripts:\n\n\n| Example               | File                     | Shows                                                                                    |\n| --------------------- | ------------------------ | ---------------------------------------------------------------------------------------- |\n| `ArgsBargMinimal`     | `examples/minimal.ts`    | String + presence flags, `MissingOrUnknown` fallback.                                    |\n| `ArgsBargNested`      | `examples/nested.ts`     | Nested command tree, positional tails, async handlers.                                   |\n| `ArgsBargFormats`     | `examples/formats.ts`    | `CliValueFormat`, `default`, `readLeafInputs()`.                                         |\n| `ArgsBargFullExample` | `examples/full-example/` | **Copy template:** all builtins, schemagen, Homebrew justfile, `outputSchema`, `from \"argsbarg\"`. |\n\n\nExamples ship in the npm package under `node_modules/argsbarg/examples/`.\n\n## Bootstrap a new CLI\n\nCopy the shipped `examples/full-example` template into a new directory:\n\nInteractive (TTY):\n\n```bash\nbunx argsbarg create my-cli\n```\n\nNon-interactive:\n\n```bash\nbunx argsbarg create my-cli \\\n  --key my-cli --release-repo org/my-cli --yes\n```\n\nEdit `scripts/create-identity.ts` in the new repo to set `desc` (used by `program.description` and the Homebrew formula).\n\n`create` copies the template (including `.cursor/rules/cli-program.mdc`), substitutes `{key}` / `{tap}` / `{releaseRepo}` placeholders in `README.md` and other files, runs `bun install`, schemagen, `bun test`, and `git init` + Initial commit when appropriate.\n\n**Git bootstrap:** skipped when the target already has a `.git` directory, or when the target sits inside an existing git work tree (monorepo subfolder). Standalone new directories get an `Initial commit`.\n\nVerify an existing tree: `bunx argsbarg create --check .`\n\nTo refresh the Cursor rule in an existing consumer: `bun scripts/merge-cli-program-rule.ts .` from an argsbarg checkout (or pass the npm package path to the template).\n\n### What the full-example template includes\n\n| Area | Files / wiring |\n| --- | --- |\n| All builtins | `completion`, `version`, `configure`, `docs`, `mcp`, `configure get`/`set` |\n| `program.appConfig` | `src/types.ts` (`AppConfig`) → `schemas/configSchemas.ts` |\n| `outputSchema` | `src/commands/status/types.ts` → `schemas/outputSchemas.ts` |\n| Schemagen | `scripts/schemagen.ts` + `scripts/schemagen/discover-schema-roots.ts` |\n| Command layout | `src/commands/\u003cname\u003e/command.ts`; registration in `src/program.ts` |\n| MCP doc topics | `docs.topics` auto-exposed as `\u003ckey\u003e://docs/\u003ctopic\u003e` resources when docs + MCP enabled |\n| Package import | `from \"argsbarg\"` (not relative to argsbarg `src/`) |\n| Homebrew distribution | `scripts/formula-shared.ts`, `scripts/gen-dev-formula.ts`, `Formula/`, `justfile` |\n| Dev tooling | Biome (`just format` / `just lint`), TypeScript, colocated tests |\n| Cursor rules | `.cursor/rules/cli-program.mdc`, `.cursor/rules/code.mdc` |\n\nWhen changing builtins or the template, run `just check-full-example` from the argsbarg repo root.\n\n```bash\nexport PATH=\"$PATH:$(pwd)/examples\"\n\neval \"$(minimal.ts completion zsh)\"\nminimal.ts --help\nminimal.ts hello --name world\n\neval \"$(nested.ts completion zsh)\"\nnested.ts stat owner lookup -u alice ./README.md\nnested.ts read ./README.md\n\nbun ./examples/formats.ts run --tags demo,docs --on 2026-06-22\n\ncd examples/full-example \u0026\u0026 just setup \u0026\u0026 just schemagen\njust run status --json\n```\n\n\n\n## Public API overview\n\nThe package root (`argsbarg` / `src/index.ts`) exports the types and runtime you need to define a schema and run it. Parsing, completion script generation, help rendering, and schema pre-validation live in other modules under `src/` for tests and advanced integrations.\n\n\n| Symbol                                                            | Role                                                                                                                                           |\n| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| `CliProgram`, `CliOption`, `CliPositional`, `CliHandler`          | Schema and handler types.                                                                                                                      |\n| `CliOptionKind`, `CliValueFormat`, `CliFallbackMode`              | Option kinds, value formats (`duration`, `comma-list`, `date`, `date-time`), and root fallback behavior.                                       |\n| `CliSchemaValidationError`                                        | Thrown when the static command tree violates schema rules.                                                                                     |\n| `CliContext`                                                      | Handler context (`ctx.hasFlag`, `ctx.stringOpt`, `ctx.durationOpt`, `ctx.readLeafInputs`, `ctx.invocation`, …).                                |\n| `CliLeafInputs`                                                   | Record type returned by `readLeafInputs()` — coerced option/positional values keyed by schema name.                                            |\n| `Cli`                                                             | Runtime: validate + freeze program, `run()`, `invoke()`, `serveMcp()`, `appConfig` getter, `exportCommandSchema()`, `exportAppConfigSchema()`. |\n| `CliInvokeResult`, `CliInvokeKind`                                | Result types from `cli.invoke()`.                                                                                                              |\n| `CliAppConfig`, `CliAppConfigEntry`                               | App config block on the program root (`entries` metadata overlay + optional `jsonSchema`).                                                     |\n| `cliErrWithHelp(ctx, msg)`                                        | Print error + scoped help on stderr, exit 1.                                                                                                   |\n| `parseDurationMs`, `parseCommaList`, `parseDate`, `parseDateTime` | Optional format parsers for use outside handlers.                                                                                              |\n\n\nReserved identifiers (validated at startup): root commands `completion`, `version`, `install`, `docs` (when `docs.enabled` is `true`), and `mcp` (when `mcpServer.enabled` is `true`).\n\n---\n\n\n\n## License\n\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdombro%2Fbun-argsbarg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbdombro%2Fbun-argsbarg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdombro%2Fbun-argsbarg/lists"}