Crust: a TypeScript and Bun CLI framework that also emits agent skills and MCP
A TypeScript CLI framework that ships your commands as a CLI, agent skills, and MCP.
At a glance
- What is it?
- Crust is a Bun-native TypeScript framework for building command line tools, with a modular package set covering routing, prompts, persistence, man pages and agent-facing output. It is a reasonable fit if your toolchain is already Bun; the README is thin on upgrades and on what happens if you are not.
- Who is it for?
- Adopt Crust if you are already on Bun and want one command definition to serve a human CLI, generated man pages and agent-facing output, and you accept that the README is the main documentation and does not describe rollback or version compatibility between the @crustjs packages. Do not adopt it if your runtime is Node only, or if you need a framework with a long published upgrade path.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Crust solves, and who it is actually for
Most CLI frameworks assume one consumer: a person typing a command. Crust is built around the observation that a command line tool now often has a second consumer, an agent that needs to discover and call the same operations. The README describes it as a TypeScript-first, Bun-native CLI framework with composable modules, and the package list makes the intent concrete. Alongside the usual pieces (core routing and argument parsing, prompts, progress indicators, terminal styling, typed persistence) there are two packages that have nothing to do with a human at a terminal: @crustjs/skills, described as agent skill generation from Crust command definitions, and @crustjs/man, which generates man pages from the same definitions. The pitch is that you define a command once and the framework can project it into several surfaces.
The audience is narrow and specific. The README states the framework is built specifically for TypeScript and Bun, and the quickstart uses bun create, so a Node-only shop is not the target. The repository's package.json pins packageManager to [email protected], which confirms the toolchain assumption rather than merely suggesting it. If your team already runs Bun and you are writing a tool that agents will call, the package split is worth reading. If you are writing a small utility with three flags, the module count is overhead you will not use.
How the module split maps onto a command definition
The repository is a Bun workspace with apps/, packages/ and tools/ as workspace roots, and the root package.json drives everything through turbo. The build scripts are explicit about the boundary: build:pkgs filters to ./packages/*, build:docs filters to ./apps/docs, and the test script runs across ./packages/* and ./tools. That layout tells you the packages are independently built and published rather than bundled into one artifact, which matches the npm table in the README where each capability has its own package and its own version badge.
Functionally, the flow the README implies is: you define commands using @crustjs/core, which owns command definition, argument parsing, routing, extensions and errors. Optional behaviour is layered on by adding packages rather than by configuring a monolith. @crustjs/extensions supplies the conventional surface (help, version, completion, typo hints, color, updates). @crustjs/store handles persistence with config, data, state and cache kept separate. @crustjs/testing provides a harness so commands can be exercised without spawning a process. Then the two projection packages read the same definitions: @crustjs/man emits man pages, @crustjs/skills emits agent skills. @crustjs/crust is the distribution side, described as CLI tooling for building and distributing standalone executables.
That is a coherent design, and it is also the main architectural risk. Because each concern is a separate published package, the compatibility surface is the set of versions you install, not one release number. The README's package table shows version badges but does not state which combinations are tested together.
Installing Crust and running a first command
The README gives a three-line quickstart. It scaffolds a project named my-cli, moves into it, and starts the dev loop. The scaffolding package is create-crust, whose most recent release listed in the repository is [email protected].
bun create crust my-cli
cd my-cli
bun run devAfter those commands you should be inside a generated project with a dev script running. The README does not describe what the generated command tree contains, so treat the first run as an inspection step rather than a known output.
If you are contributing to Crust itself rather than consuming it, the root package.json defines the workspace commands. The check script builds the packages and then runs lint and format through turbo:
bun run check
bun run test
bun run build:pkgsThe test script is scoped to ./packages/* and ./tools, and lint is oxlint with formatting handled by oxfmt. Those are the repository's own conventions, taken from package.json, not recommendations for your project.
One thing the README does not do is show a command definition in code. There is no example of registering a command, parsing an argument or attaching an extension. The website at crustjs.com is linked as the documentation home, so the README functions as a package index rather than a tutorial. Budget time for the docs site before you judge the API.
The agent-facing packages are the reason to look, and the least documented part
Two entries in the package table stand out. @crustjs/skills is described as agent skill generation from Crust command definitions, and the repository's topics include agent and agent-tooling. The premise is that a CLI's command tree is already a machine-readable description of what the tool can do, so generating an agent skill from it avoids maintaining a second description by hand. The same argument applies to @crustjs/man, which turns command definitions into man pages.
This is the part of Crust that a general-purpose CLI framework does not attempt, and it is also where the README stops. There is no example of the generated skill format, no statement of which agent runtimes consume it, and no description of how a skill is regenerated when commands change. The description in the package table is one line. If agent integration is your reason for choosing Crust, verify it against the docs site before you build on it, because the repository README alone does not let you evaluate the output.
Where Crust is the wrong choice
The Bun requirement is the first constraint and it is not negotiable in the README's framing: the framework is described as Bun-native, the quickstart uses bun create, and the root manifest pins [email protected]. If your distribution target is a Node runtime you do not control, or your CI images are Node-based, you are fighting the design rather than using it. @crustjs/crust exists to build standalone executables, which may sidestep the runtime question for end users, but the README does not say which platforms those executables target.
The second constraint is maturity. The packages are versioned in the 0.0.x and 0.1.x range, and the most recent releases listed in the repository are [email protected], @crustjs/[email protected] and @crustjs/[email protected], all dated 2026-06-05. The README does not document a deprecation policy, a migration guide or a rollback path. For a tool you intend to ship to users who will pin it, that absence matters more than any missing feature.
The third is scope. If your CLI is a handful of subcommands with no interactive prompts, no persistence and no agent consumer, the modular split buys you nothing and costs you a dependency graph to track. A single-file argument parser would be the smaller decision.
How Crust differs from Commander and oclif
Commander is the reference point most TypeScript developers already have. It is a parser and a command registry, distributed as a package that runs on Node, and it does not generate man pages or agent skills from your definitions; those are separate concerns you would wire up yourself. The difference is not feature count, it is the projection model. Crust treats the command definition as a source that multiple outputs are derived from, which is why man page and skill generation live in the same repository as the parser.
oclif is the closer comparison on scope. It is also a framework rather than a parser, with a plugin model, a scaffolding CLI and a testing story, and it is built around Node. The practical difference for a team choosing between them is the runtime and the ecosystem: oclif's plugin conventions are established and its documentation covers the lifecycle in detail, while Crust's advantage is that it targets Bun directly and ships the agent-facing packages. If you need published guidance on plugin versioning, oclif has it and Crust's README does not.
Maintenance, versioning and the MIT licence
The repository is not archived, and the most recent push to the default branch was on 2026-09-10. The latest releases named in the repository are dated 2026-06-05, so the commit activity and the published artifacts are not on the same cadence. The README does not describe a support window or a release schedule.
Upgrade cost is a real question here because the framework is split across many independently versioned packages. The repository uses changesets for release management, with scripts named changeset, packages:version and packages:publish in the root package.json, which is the standard mechanism for coordinating version bumps across a monorepo. What the README does not provide is a compatibility table stating which versions of @crustjs/core work with which versions of @crustjs/extensions or @crustjs/skills. Until that exists, pinning exact versions and reading each package's changelog is the only defensible approach.
The licence is MIT, per the README's licence badge and the LICENSE file at the repository root. MIT is permissive and imposes no source disclosure on your own code. That is a statement about the licence text, not advice about your situation; if you redistribute Crust inside a product, read the LICENSE file yourself.
Editorial conclusion
Adopt Crust if you are already on Bun and want one command definition to serve a human CLI, generated man pages and agent-facing output, and you accept that the README is the main documentation and does not describe rollback or version compatibility between the @crustjs packages. Do not adopt it if your runtime is Node only, or if you need a framework with a long published upgrade path. Before committing, run bun create crust my-cli and confirm that the generated project's dev loop, the version numbers of @crustjs/core and @crustjs/skills, and the build output for your target platform all behave as you expect; the README documents none of those in detail.
Frequently asked questions
Does Crust run on Node, or does it require Bun?
The README describes Crust as a TypeScript-first, Bun-native framework, the quickstart uses bun create crust, and the root package.json pins packageManager to [email protected]. There is no documented Node path in the README.
What is Crust?
It is a TypeScript CLI framework built for Bun, with composable modules covering command routing, argument parsing, prompts, persistence and terminal styling. Two of its packages generate man pages and agent skills from the same command definitions.
How do I install Crust and start a project?
The README's quickstart runs bun create crust my-cli, changes into the directory, and starts the dev loop with bun run dev. The scaffolding package is create-crust.
Can Crust generate agent skills or MCP output from my commands?
The package table lists @crustjs/skills as agent skill generation from Crust command definitions. The README does not document the generated format or which agent runtimes consume it, so the docs site is the place to confirm the details.
What licence does Crust use?
The README's licence badge and the LICENSE file at the repository root both indicate MIT. The README does not discuss any additional terms.
Which package do I need for argument parsing and routing?
@crustjs/core is described as the core package for command definition, argument parsing, routing, extensions and errors. The README's package table separates it from the optional packages such as @crustjs/prompts and @crustjs/store.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/chenxin-yan-crust)