[HN Gopher] Show HN: Crust - A CLI framework for TypeScript and Bun
       ___________________________________________________________________
        
       Show HN: Crust - A CLI framework for TypeScript and Bun
        
       We've been building Crust (https://crustjs.com/), a TypeScript-
       first, Bun-native CLI framework with zero dependencies. It's been
       powering our core product internally for a while, and we're now
       open-sourcing it.  The problem we kept running into: existing CLI
       frameworks in the JS ecosystem are either minimal arg parsers where
       you wire everything yourself, or heavyweight frameworks with large
       dependency trees and Node-era assumptions. We wanted something in
       between.  What Crust does differently:  - Full type inference from
       definitions -- args and flags are inferred automatically. No manual
       type annotations, no generics to wrangle. You define a flag as
       type: "string" and it flows through to your handler.  - Compile-
       time validation -- catches flag alias collisions and variadic arg
       mistakes before your code runs, not at runtime.  - Zero runtime
       dependencies -- @crustjs/core is ~3.6kB gzipped (21kB install). For
       comparison: yargs is 509kB, oclif is 411kB.  - Composable modules
       -- core, plugins, prompts, styling, validation, and build tooling
       are all separate packages. Install only what you need.  - Plugin
       system -- middleware-based with lifecycle hooks (preRun/postRun).
       Official plugins for help, version, and shell autocompletion.  -
       Built for Bun -- no Node compatibility layers, no legacy baggage.
       Quick example:                 import { Crust } from
       "@crustjs/core";       import { helpPlugin, versionPlugin } from
       "@crustjs/plugins";            const main = new Crust("greet")
       .args([{ name: "name", type: "string", default: "world" }])
       .flags({ shout: { type: "boolean", short: "s" } })
       .use(helpPlugin())         .use(versionPlugin("1.0.0"))
       .run(({ args, flags }) => {           const msg = `Hello,
       ${args.name}!`;           console.log(flags.shout ?
       msg.toUpperCase() : msg);         });            await
       main.execute();       Scaffold a new project:                 bun
       create crust my-cli       Site: https://crustjs.com GitHub:
       https://github.com/chenxin-yan/crust  Happy to answer any questions
       about the design decisions or internals.
        
       Author : jellyotsiro
       Score  : 59 points
       Date   : 2026-03-17 04:43 UTC (18 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | landl0rd wrote:
       | Is there an examples section? Would be helpful to see a demo
        
         | jellyotsiro wrote:
         | one of the examples would be trynia.ai (search and index api
         | for ai agents)
         | 
         | here is github: github.com/nozomio-labs/nia-cli
        
       | matt_kantor wrote:
       | > Versions before 1.0 do not strictly follow semantic versioning.
       | 
       | Sorry for being nitpicky, but yes they do. Semantic versioning[0]
       | allows arbitrary changes while the major version is 0:
       | 
       | > Major version zero (0.y.z) is for initial development. Anything
       | MAY change at any time. The public API SHOULD NOT be considered
       | stable.
       | 
       | [0]: https://semver.org/
        
         | jellyotsiro wrote:
         | thanks for the catch, what we meant is that we're not
         | committing to strict stability guarantees yet, so APIs may
         | still change as we iterate toward 1.0.
        
           | matt_kantor wrote:
           | I understand, but that's already implied by a 0.y.z version
           | number.
        
             | olivia-banks wrote:
             | I will say that this doesn't seem to be how semver is used
             | in the wild, which I would argue is more important. I
             | personally didn't know about this rule. Tons of Rust
             | projects follow semver don't follow it either, and just
             | stay on 0.x.y forever.
        
         | chenxin-yan wrote:
         | Hi, the comment I left in README.md is just to warn user that
         | do expect breaking changes before 1.0 for THIS PROJECT
         | specifically. there is no implication that semver as a standard
         | is promoting arbitrary changes/version before 1.0.
        
       | bennettpompi1 wrote:
       | this is cool! i'd recommend fleshing out the README. Clicked on
       | the link before the discussion and was a tad confused.
        
         | jellyotsiro wrote:
         | will fix in the next hour!
        
         | chenxin-yan wrote:
         | Hi, I will update the README.md to make it more informative.
         | The reason I left it kinda empty is because curst has a website
         | that have more details about this project at crustjs.com. I
         | just had the link in README.md for now
        
       | dnlzro wrote:
       | Psst, the GitHub link in your post is broken (it should be
       | https://github.com/chenxin-yan/crust).
        
         | jellyotsiro wrote:
         | thanks for flagging! the post itself works, just the link at
         | the bottom
        
         | dang wrote:
         | Fixed above. Thanks for the heads-up!
        
       | camkego wrote:
       | This looks useful. But, it's interesting how the backend-world
       | and front-end world keep diverging. I must admit, I had no idea
       | what this was from the title. "CLI framework"? But in backend-
       | land, these would typically be called "argument parsers" or
       | "command line argument parsers". But maybe I am missing some of
       | the functionality.
        
         | jellyotsiro wrote:
         | good point.
         | 
         | we're using "framework" intentionally because it goes beyond
         | argument parsing. crust handles parsing, but also:
         | 
         | type inference across args + flags end to end compile-time
         | validation (so mistakes fail before runtime) plugin system with
         | lifecycle hooks (help, version, autocomplete, etc.) composable
         | modules (prompts, styling, validation, build tooling) auto-
         | generates agent skills and modules from the CLI definitions
         | 
         | so it sits a layer above a traditional arg parser like yargs or
         | commander, closer to something like oclif, but much lighter and
         | bun-native.
        
         | embedding-shape wrote:
         | Both in the frontend and the backend, I've usually used "If it
         | calls your code, it's a framework, if you call its code, it's a
         | library", and would seem to fit here too. An argument parser
         | you'd call from your main method, then do stuff with what it
         | returns. In Crust, it seems you instead setup the command +
         | what will happen when it's called, then let the framework call
         | your code.
        
           | codybontecou wrote:
           | That's... actually a great definition. I'm going to try to
           | retain that.
        
         | chenxin-yan wrote:
         | Hi, I called it "CLI framework" because it is more of a
         | ecosystem of modules that contains everything you need to build
         | a CLI, argument parsing is just part of it. The @crustjs/core
         | module is the argument parser, and there are more modules such
         | as @crustjs/skills that would derive agent skills from your
         | command definition, @crustjs/store that state persistent and so
         | on
        
       | rgbrgb wrote:
       | nice, congrats on launch. To get an idea... what's the size of a
       | standalone hello world cli binary?
        
         | jellyotsiro wrote:
         | tens of KBs (v small)
        
           | rgbrgb wrote:
           | Isn't a standalone Bun binary like 50MB because it has to
           | bundle the runtime? How could this get smaller?
        
             | chenxin-yan wrote:
             | Hi, the creator of crust here, the binary size varies
             | between platforms. With the hello world cli, the smallest,
             | on darwin-arm64 it is 58.1M, the largest on windows-x64 is
             | 109M. hope this helps!
        
       | nullstyle wrote:
       | I've been using the jsr:@cliffy/* packages from deno to solve the
       | same problem.
        
       ___________________________________________________________________
       (page generated 2026-03-17 23:00 UTC)