Crust: One TypeScript Command Definition, Three Delivery Targets
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 CLI framework whose package list includes generators for man pages, agent skills and MCP surfaces. The interesting claim is not the terminal UI, it is that a single command definition can be shipped to humans, to agents and to MCP hosts.
- Who is it for?
- Crust is worth evaluating if your team already builds on Bun, wants TypeScript types on command arguments, and needs the same command surface exposed to agents or MCP hosts without maintaining a second definition. It is the wrong choice if you need Node-only distribution, a large plugin ecosystem, or a framework whose routing and validation behaviour you can verify from published docs today.
- 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 1 day 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 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Crust targets: commands defined once, consumed by people and by agents
Most CLI frameworks assume the only consumer is a human at a terminal. Crust's package list says otherwise. Alongside @crustjs/core for command definition, argument parsing and routing, the repository ships @crustjs/skills, described as agent skill generation from Crust command definitions, and the project description states that it ships your commands as a CLI, agent skills, and MCP. That is the differentiator. If you have already written a command tree with typed arguments, the same definitions are the input for a man page generator (@crustjs/man) and for the agent-facing output. The intended user is a TypeScript developer on Bun who is building a tool that both people and automated agents will call, and who does not want to hand-maintain a separate tool schema for the agent side. The README names one production consumer, Nia CLI by Nozomio Labs, which is the only adoption evidence given.
The package split is the architecture: core, extensions, and output adapters
Crust is not a monolith with optional flags. The README lists thirteen packages, and the boundaries tell you how the framework is meant to be assembled. @crustjs/core holds command definition, argument parsing, routing, extensions and errors. @crustjs/extensions bundles the behaviour most CLIs need: help, version, shell completion, typo hints, color and update checks. Presentation is separate: @crustjs/style for terminal styling, @crustjs/progress for progress indicators, @crustjs/prompts for interactive prompts. State is separate too: @crustjs/store is described as typed persistence with config, data, state and cache kept in distinct locations, which is a more opinionated split than the usual single config file. Then there are the adapters that justify the project's existence: @crustjs/man, @crustjs/skills, and @crustjs/crust itself, which handles building and distributing standalone executables. The data flow implied by this layout is a command definition in @crustjs/core, consumed by whichever output package you install. What the material does not show is the shape of those definitions, so treat the single-definition claim as a design intent to verify rather than a demonstrated fact.
Getting a project running: the scaffold command and what it implies about Bun
The README gives exactly one getting-started sequence:
bun create crust my-cli cd my-cli bun run dev
There is no npm equivalent in the material, and the project describes itself as Bun-native, so the Bun runtime is a stated requirement rather than an optional preference. The scaffolding package is create-crust, which is at version 0.0.31, and there is a separate headless engine, @crustjs/create, for building your own create-xxx tools. Two things are worth noting about the versions. First, create-crust is still on a 0.0.x line, and the most recent releases listed are from June 2026. Second, the version numbers across the suite are uneven: @crustjs/validate is at 0.1.2 while @crustjs/utils sits at 0.0.3. Uneven 0.x versions across a package family mean you should pin exact versions in package.json rather than relying on caret ranges, because a minor bump in one package is not a signal that the others moved with it. The README does not document a config file format, so if you need to know what bun run dev actually executes, read the scaffolded template after running the create command.
Where Crust is the wrong tool
The Bun requirement is the first hard boundary. A team distributing a CLI to users who run Node, or to CI images built around Node, cannot adopt Crust without changing that constraint, and nothing in the material suggests a Node compatibility path. The second boundary is the Bun-native standalone executable story in @crustjs/crust. Compiling a binary ties you to Bun's build behaviour and to the platforms you build for, which is a different operational model from publishing an npm package and letting the user's runtime execute it. The third is documentation depth. The README is a package table and a three-line quickstart. It does not show a command definition, an argument schema, or a routing example, and it does not explain how @crustjs/skills decides what to emit or how the MCP surface is exposed. For a framework whose main claim is multi-target output, that is the gap that matters most. A team that needs to read the generator's rules before trusting them will have to go to the website or the source, and if the website is equally thin, the agent and MCP features should be treated as unverified.
How Crust differs from Commander and oclif
Commander is the comparison most TypeScript developers will reach for. It is runtime-agnostic, ships as a small dependency, and its argument parsing is documented in detail. Its model is a command tree you build at runtime, and its output is a CLI. It has no equivalent of @crustjs/skills or the MCP target, so if that is what you need, you would write the agent-facing schema yourself. oclif takes the other approach: a plugin architecture, a generator-driven project layout, and a framework that assumes a larger surface area and a longer-lived project. Crust sits between them. It is more opinionated than Commander about structure (separate packages for style, prompts, progress, store) and less opinionated than oclif about plugins, which do not appear in the package list at all. The real difference is the output target. Commander and oclif produce a CLI and stop. Crust's stated purpose is to produce a CLI plus agent skills plus MCP from the same definitions, and that is the only reason to accept a Bun-only runtime and a 0.x dependency set.
Maintenance cost, version pinning and the MIT licence
The repository is not archived, the last push is dated September 2026, and the most recent releases listed are from June 2026, so the project is active on the evidence available. The maintenance cost for an adopter comes from the package count. Every @crustjs package you install is a separate version to track, and the current numbers (0.0.3, 0.1.2, 0.0.31) show they do not move in lockstep. Budget for reading changelogs per package, not per release train. The licence is MIT, which permits commercial and closed-source use and requires that the copyright notice and permission notice be included in copies or substantial portions. That is a permissive arrangement with few obligations, but it is also a grant of no warranty, so the 0.x version numbers and the thin documentation are the practical risk, not the licence terms. This is a description of the licence text, not legal advice; if you redistribute Crust inside a product, have counsel confirm the notice requirements for your distribution method.
What to check before committing to Crust
Run bun create crust in a scratch directory and read the generated files before writing any real commands. Confirm which @crustjs packages the template installs and at which versions, since that tells you what the maintainers consider the default surface. Then look for a command definition in the template and check whether the argument types survive into the generated help text, because typed arguments are one of the framework's stated selling points. If agent skills or MCP are the reason you are here, find the generator's input and output format in the docs or source before you build on it; the README does not describe either. If your tool must run on Node, stop at this point, because the Bun-native framing appears throughout the material and there is no documented alternative. The one production reference given, Nia CLI, is worth reading as a worked example of how the packages are combined in practice.
Editorial conclusion
Crust is worth evaluating if your team already builds on Bun, wants TypeScript types on command arguments, and needs the same command surface exposed to agents or MCP hosts without maintaining a second definition. It is the wrong choice if you need Node-only distribution, a large plugin ecosystem, or a framework whose routing and validation behaviour you can verify from published docs today. Before adopting, run bun create crust in a throwaway directory, confirm which @crustjs packages the template actually installs, and check whether @crustjs/skills and the MCP path are documented well enough for your use case.
Community notes