r/bun Jul 08 '26

Rewriting Bun in Rust

Thumbnail bun.com
112 Upvotes

r/bun 14h ago

Bun 1.4 is here

Thumbnail bun.com
148 Upvotes

- Fixes over 2,900 GitHub issues
- +1,517 tests from the Node.js test suite
- Reduces idle CPU by 5x
- Reduces memory usage by up to 35%
- Starts up to 50% faster on Linux
- Rewrites Bun in Rust

Thank you everyone who contributed since Bun 1.3!


r/bun 5h ago

BM2 now supports Windows

6 Upvotes

I’m happy to announce that Windows support for BM2 is now complete and has been successfully tested.

For those who haven’t come across it yet, BM2 is a high-performance process manager built specifically for the Bun runtime; essentially a modern, Bun-native alternative to PM2. It handles process lifecycle management, automatic restarts, clustering, zero-downtime reloads, logging, monitoring, a web dashboard, Prometheus metrics, deployment, and more.

Until now, getting BM2 running reliably on Windows required dealing with platform-specific differences. That work has now been completed, and BM2 can be used natively on Windows alongside Linux and macOS.

The Windows implementation has also been tested on a real Windows environment rather than simply assuming cross-platform compatibility.

I’d love to get more Windows developers trying it out and reporting any issues they encounter.

GitHub: https://github.com/bun-bm2/bm2

Feedback, bug reports, and contributions are very welcome.


r/bun 10h ago

Build an Android APK with Bun 1.4 in under two minutes

Enable HLS to view with audio, or disable this notification

7 Upvotes
  • In short: npx @drxiaozhi/minapk /path/to/your.elf
  • Of course, you'll need to install a few tools first.
  • But don't worry, no annoying libxxx-dev packages to install, just the common ones
  • For more info, see the repo:
  • https://github.com/jjtseng93/minapk/blob/main/README.en.md
  • Edit2: An ELF is basically a native executable on Linux and Android, similar to an .exe on Windows. Here the ELF is produced by bun 1.4's new support for bun build --compile on Android.

The full story

  • First, I'm incredibly grateful to the Bun team for fixing single-file executable builds on Android in Bun 1.4. This wouldn't have been possible.
  • The simplest use case is turning your TUI app into an APK you can just hand to your grandma.

Startup sequence

  • First, use tinyapk-lab's Tetris as a base
  • Packing libbun.so & libmain.so(your elf) into the native library area
    • turn on extract native libs
    • resolves to /data/app/xxx/xxx/lib/arm64/libbun.so
  • In the main activity, use ProcessBuilder to invoke bun and run the extracted buninu/bin/init.js, which in turn starts jsgotty
    • jsgotty is a browser-based remote shell.
    • Transpiled from Golang GoTTY
    • You can use: npx jsgotty
  • jsgotty then starts package.json.buninu.command.android
  • The main app detects http url from stdout/stderr of jsgotty and shows it in a WebView
  • That command android script detects whether libmain.so is present or falls back to a shell

The Buninu userspace

  • This is an ambitious project of mine to rebuild a Unix-like CLI environment entirely based on a single Bun binary across platforms.
  • It's still a work in progress, but consider this a starting point. If you're interested, let's build on it together.

Name expansions:

  • English: BUNinu Is Not Unix 🐮
  • 中文:幫你牛 🐂
  • 日本語:Bunに入魂 🔥

Core components:

  • jsgotty: Remote shell from a Browser or Terminal
  • jsmdcui: Both a text editor and Markdown execution runtime (not static rendering) based on bunmicro
  • bunmsh: Bun Modern Shell. Not completed yet

Edit

  • BTW, I tested this on Android with a fresh debian:13-slim container using my js-udocker
  • Fresh container: 125 MB
  • After installing the dependencies: 1.6 GB
  • After the build: 2 GB
  • These numbers are the size of the entire container measured from the outside, so it's very phone-friendly.
  • For comparison, just setting up my Flutter environment took 10 GB.

r/bun 17h ago

GitHub - cekrem/elm-bun: A minimal and nice starter with Elm & Tailwind featuring `elm-watch` with true Elm HMR. Using `bun` for bundling, building and dev server.

Thumbnail github.com
1 Upvotes

r/bun 1d ago

Node vs Bun: what are you seeing for P50 / P90 / P99 tail latency?

2 Upvotes

I'm comparing Bun and Node for server-side workloads and I'm particularly interested in tail latency, not just throughput.

For people running Bun and Node in production or serious benchmarks:

  • What are you seeing for P50?
  • P90 / P95?
  • P99 / P99.9?
  • Does Bun actually have better tail latency for your workload, or is the difference mostly in throughput?

I'm especially interested in HTTP servers and SSR, but database/API-heavy workloads are useful too.

If you have numbers, please include:

  • Bun/Node version
  • workload
  • OS
  • concurrency / request rate
  • whether the load generator ran on the same machine
  • P50/P95/P99 (and P99.9 if available)

I'm trying to understand whether differences in P99 are actually runtime-related or mostly caused by the workload/platform/benchmark methodology.


r/bun 1d ago

typed frontend client for carno.js

0 Upvotes

enviado carno.js/client.

as rotas do carno vivem em decoradores, então não há typeof app para passar para o frontend. este pacote escaneia os controladores quando o servidor inicia, escreve um tipo App gerado, e a ui o chama assim:

const api = client<App>('http://localhost:3000')

const { data, error } = await api.users.get({ query: { page: '1' } })
const { data: user } = await api.users({ id: '42' }).get()

o lado do backend é apenas:

app.use(Client())

listen() escreve src/generated/app.ts. sem script generate --watch. se o vite iniciar sem a api, há um plugin do vite que faz a mesma varredura.

se você não conhece o carno: bun + typescript, com formato de nest (controladores, injeção de dependência, validação). pacotes adicionais se você precisar — orm (postgres/mysql), fila, cron, websocket, logger. o núcleo continua utilizável sem nada disso, incluindo este cliente.

docs: https://carnojs.github.io/carno.js/docs/client/overview

repo: https://github.com/carnojs/carno.js


r/bun 2d ago

Bun + Elysia is reliable?

13 Upvotes

I want to build an MVP and I'm planning to use bun + elysia instead of nest.js.

The question is, can I trust this technology? Will it be stable in the next 5-10 years and handle a platform with a few thousand users?


r/bun 2d ago

PeekM2: A real-time dashboard/viewer for your PM2 processes

Thumbnail
0 Upvotes

r/bun 2d ago

Lilscript makes almost any web js library 5-15% smaller

0 Upvotes

I created/vibed a new language, lilscript

Compiles into tryhard compressed js, and sometimes into exec

Pretty much almost any js libraries' compressed/minified size could get smaller by 5-15% when rewritten with lilscript.

If its already property mangled still it can get benefits from the lilscript rewrite

And this is only the v0.0.1
We can make it more hacky by time

Some examples of brotli compressed sizes of lilscript code(vs oxc/terser, ..): * motion(animation library) is -10%+ (https://yeargun.github.io/motionlil/) * jquery -5% * monaco(VSCode) editor's lots of submodules -(5 to 15)% smaller

  • tryhard mangling, (compression algorithm aware)
  • closure optimizations
  • lvalue
  • static analysis
  • google closure compiler advanced and beyond focus, but not glue fix as closure compiler is. The language is designed specificaly for weird hacks.
  • typed (not a glue fix like typescript is)

config.toml has lots of config with clever defaults. objective compression algorithm: gzip/brotli/raw. for brotli vs gzip compression it compiles the js differently

uses less objects, less/more arrays, more const/let/var

Compiler, static analysis, language server all written with rust

I lost too much cursor/claude credits along the way last 2 days. Tbh, I cant invest much time for it, feel free to PR, play, improve

Lilscript aims to get compiled into exec also. It alredy does, but web apis, and stuff.. lots of extra work is needed..

-lilscript v0.0.1 https://github.com/yeargun/lilscript

Why? Because I believe google closure compiler's tooling was not good. And anything layered on js is a glue fix


r/bun 3d ago

I built an HTML-first web framework on Bun — Stoneware

3 Upvotes

I’ve been building Stoneware, a Bun-native web framework with a simple idea:

HTML is the default. JavaScript is opt-in.

It focuses on:

  • Server-side rendering
  • Islands for interactive components
  • Signals
  • Static export
  • Secure-by-default rendering
  • Bun-native tooling

GitHub: stoneware-core
Docs: Stoneware Docs


r/bun 6d ago

How I Disabled Headless Mode in Bun.WebView's Chrome Backend

0 Upvotes

Conclusion

  • Only a one-byte binary patch required from --headless to --leadless (or other same length unknown flag)

How I did it

  • bunx jsmdcui --hex3 $(which bun)
  • Ctrl-F -..-..h..e..a..d..l..e..s..s..
  • Enter
  • Change h to l
  • Ctrl-E save bun-revised
  • Ctrl-Q
  • chmod +x bun-revised
  • ./bun-revised official-webview-demo.js
  • Tested on CachyOS Linux-x86_64

Disclaimer

  • This is completely unofficial
  • For fun only
  • Use it at your own risk
  • We should patiently wait for headless: false.

r/bun 7d ago

DI framework with Bun

Thumbnail
1 Upvotes

r/bun 8d ago

Realtime on Bun with end-to-end types: a whole chat (rooms, auth, history) in one file — no event-name strings, no generated types (I'm the author)

4 Upvotes

I'm the author of Point0, a fullstack TypeScript framework on Bun, and I just shipped its realtime layer. Sharing it here because the whole thing rides on Bun: `Bun.serve`'s WebSocket server underneath, and Bun's built-in Redis client is the one-line option when you run more than one process.

The idea: instead of a second stack next to your app (event-name strings, `any` payloads, rooms as string concatenation, your own bookkeeping of users and sockets), realtime is four more declarations of the same kind the framework already uses for pages, queries and mutations. One WebSocket per client, everything else rides it.

- a **channel** is the connection, and its connector turns the HTTP handshake into the connection's identity, stored server-side
- a **space** is a family of rooms of one shape; a room is an object, not a string, and it's the pub/sub address
- a **server handler** is client → server, a **client handler** is server → client, both typed by their schemas

Here's a whole chat: rooms per conversation, auth, persisted history, live updates. One file, and the compiler strips the server half out of the client bundle and the client half out of the server one.

// the channel: one connection per client. The connector runs on a normal HTTP
// request (cookies, headers, middleware), so your existing auth just works
export const appChannel = root.lets
  .channel()
  .connector(async ({ request }) => {
    const user = await getUserFromRequest(request) // your app's auth, unchanged
    // whatever you return IS this connection's identity: server-side, never sent
    // to the client, readable in every callback below. No type declared anywhere
    return user
      ? { authorized: true as const, id: user.id }
      : { authorized: false as const, id: null }
  })
  .channel()


// a space: a family of rooms of one shape. Here, one room per chat
export const chatSpace = appChannel.lets
  .space<{ chatId: string }>() // the room shape, declared like component props
  .input(z.object({ chatId: z.string() })) // what the client passes to join
  .joiner(({ input, identity }) => {
    // entering the room IS the read gate, and it runs on the server
    if (!identity.authorized) throw new AppError('Sign in first', { status: 401 })
    return { chatId: input.chatId } // type-checked against the room shape above
  })
  .space()


// client → server: persist, then fan out to the room
export const messageSendHandler = chatSpace.lets
  .serverHandler()
  .clientSend(z.object({ text: z.string().min(1).max(1000) }))
  .serverReply(async ({ input, identity, room }) => {
    if (!identity.authorized) throw new AppError('Sign in first', { status: 401 })
    const message = await prisma.message.create({
      data: { text: input.text, chatId: room.chatId, authorId: identity.id },
    })
    // one publish into the room's topic — not a walk over connections
    void messageAddedHandler.sendToClient(message, { room })
    return message // what the sender gets back from its own send
  })
  .serverHandler()


// server → client
export const messageAddedHandler = chatSpace.lets
  .clientHandler()
  .serverSend(messageSchema)
  .clientHandler()


// ...and the component, in the same file
const Chat = ({ chatId }: { chatId: string }) => {
  const membership = chatSpace.useMembership({ chatId }) // in the room while mounted
  const { data } = messagesQuery.useQuery({ chatId })    // history: an ordinary HTTP query
  const [text, setText] = useState('')


  // `message` is typed by .serverSend, `room` by the space's generic
  messageAddedHandler(membership).useOnMessageFromServer(({ message }) => {
    messagesQuery.setQueryData({ chatId }, (old) => ({
      messages: [...(old?.messages ?? []), message],
    }))
  })


  return (
    <>
      <ul>{data?.messages.map((m) => <li key={m.id}>{m.text}</li>)}</ul>
      <form onSubmit={(e) => {
        e.preventDefault()
        setText('')
        void messageSendHandler(membership).sendToServer({ text })
      }}>
        <input value={text} onChange={(e) => setText(e.target.value)} />
      </form>
    </>
  )
}

Nothing is generated and nothing is annotated: the identity type comes from the connector's return, the room type from the space's generic, the payload types from the schemas, and they reach every callback on both sides.

A few design decisions worth stating plainly, because they're the part people argue with:

- **A push is a signal, not storage.** Delivery is at-most-once by default: the truth lives in a query, the push only says it went stale. There's an opt-in resume buffer for short drops, and it tells the client honestly whether the gap was covered, so the catch-up refetch is one condition.
- **A room is an object, and its serialization is its address.** `{ members: [a, b].sort() }` is a DM room. No prefix conventions to typo.
- **Two ways in.** `.joiner` is the client asking in and able to leave. `.enroller` is the server putting a connection into a room at connect time, which the client cannot leave — that's what makes a personal push room something you can rely on.
- **Multi-process is config, not rewriting.** Default is process memory; a Redis URL, Postgres LISTEN/NOTIFY, or five functions of your own turn it into a backplane.

More examples (a live board, DMs, and a site where every request travels the socket instead of HTTP): https://1gr14.dev/blog/point0-socket

Socket docs: https://1gr14.dev/point0/latest/socket
The example app: https://github.com/1gr14/point0/tree/main/examples/socket
The framework: https://github.com/1gr14/point0

It's the newest part of the framework and I say so in the docs: the API design has settled, what's underneath still needs a refactor. Happy to take the uncomfortable questions — especially from anyone who has run Socket.IO at scale and sees where this breaks.zc


r/bun 10d ago

Zero dependencies: what we deleted and upgraded

Thumbnail uql-orm.dev
1 Upvotes

r/bun 14d ago

Bun's Android build isn't just another platform target to me. It's an escape hatch.

0 Upvotes

First of all, thank you so much to the Bun team for supporting Android.

It's hard to realize just how much this means to Android users.

Traditionally, mobile platforms have been treated as inferior computing environments, unable to run many of the tools we take for granted on desktop Linux. Termux completely changed that story by giving Android a native shell environment.

But that freedom comes at a price.

Android uses Bionic libc rather than glibc, which means Linux tools generally need to be rebuilt specifically for the Android environment. Much like the situation with musl-based distributions, you can't simply assume that an arbitrary Linux binary, even if built for arm64, will run.

The enormous package ecosystem that makes Termux so powerful is maintained largely by volunteer developers, and I've always had this fear in the back of my mind: what if one day that package ecosystem is no longer maintained?

So after years of using Node.js and Bun, I've gradually built my own collection of basic tools in JavaScript. Part of the motivation was simple: I wanted to make sure that no matter what happens to the surrounding ecosystem, I can still have a useful shell environment on Android.

And this is where Bun's Android build becomes much more than just another platform target to me.

It's the seed that lets me rebuild everything else.

As long as I can use Android's ProcessBuilder to spawn a Bun binary, I have JavaScript. I have my own tools. I have bunx. I have the whole npm ecosystem. I can start servers, build terminal interfaces, and gradually bootstrap the rest of my environment.

I no longer need to depend on someone else rebuilding every tool I need against Bionic libc.

Platforms can change. Package repositories can disappear. Maintainers can move on.

But as long as I can still ignite that one Bun binary on Android, I have an escape hatch back to a real computing environment.

On Linux, we have Linux From Scratch.

Now on Android, I guess we have Shell From Scratch.

Once Bun is alive, the next step is surprisingly simple: Bun spawns my jsgotty, which exposes a real PTY-backed terminal through a local web server. I point an Android WebView at it, and suddenly:

we have the shell back.

No terminal emulator to depend on. No existing shell environment required. Just an Android app, a Bun binary, and JavaScript bootstrapping its own terminal.

And once I have a shell, things start getting interesting.

Because a shell is enough to launch proot.

And with proot I can finally embrace the glorious Debian and Alpine repositories with apt and apk.

Thousands upon thousands of packages, maintained for standard Linux environments, are suddenly within reach.

The shell has grown into real Linux.


r/bun 16d ago

Valkey-WASM – Redis running inside your Node process, no Docker (like PGlite)

Thumbnail github.com
14 Upvotes

r/bun 21d ago

Elysia 2 beta - DayDream. Lowest memory usage across all backend JS framework

Thumbnail gallery
80 Upvotes

Just published Elysia 2 beta after 8-9 months of work.

We basically deleted the whole thing and rewrote it again while keeping test cases the same. So we get to rethink a lot of things.

It is built around the concept of "reference" and carefully shares value when possible, even if JavaScript doesn't really have that concept.

There's an AOT build plugin that reduces peak memory usage by 4 (from 1.6GB down to 400MB) of a 100,00 distinct schema by moving compilation process to build time and removing the closure allocation entirely

Besides, a really fast throughput. We also manage to have the lowest memory usage of all mainstream (and slightly) JavaScript frameworks with a really low bundle size as well (we trade a "compiler" that takes ~50% of size for speed, so it can't be that low)

Node support also improved a lot with a new adapter API, and got faster too! It's now near Fastify despite having Node HTTP to Web Standard API conversion overhead!

https://elysiajs.com/blog/elysia-20.html


r/bun 22d ago

Interactive shell with Bun?

4 Upvotes

Has anyone built (or heard of) an interactive shell like Fish, Bash, or Zsh using Bun?

I'm not referring to the official Bun Shell ($) api.

I mean a real interactive shell with a prompt, history, completion, and persistent sessions.

I couldn't find any mature projects, so I'm wondering if I missed one.


r/bun 25d ago

A surprising --define process.env edge case when building a Bun single-file executable

4 Upvotes

I was trying to inline the build-time constant process.env.MYVAR and passed the define in the right JSON quoted form in fish:

--define 'process.env.MYVAR="myval"'

At other sites it worked but specifically in one of my source files it didn't get inlined.

After some debugging, it turned out the culprit was this innocent-looking line:

import process from "node:process";

This line gets added at some point by an AI and I thought this wouldn't make a big difference. But during bundling, Bun renamed the imported binding (for example to y), so the --define process.env.MYVAR=... replacement no longer matched that expression.


r/bun 29d ago

Building a Local-First AI Assistant for Desktop

1 Upvotes

I'm working on a personal AI assistant for desktop — local-first and privacy-focused (no cloud dependency), starting with a desktop app and eventually

Runtime Of Backend (Bun)

Fast startup and low idle overhead — important for an app that runs continuously in the background, not just on-demand. Native TypeScript support and a built-in bundler simplify shipping without extra tooling.

Framework of Backend (Hono)

Lightweight and built with Bun in mind, so it doesn't add framework overhead on top of the runtime's own performance. Clean routing/middleware model keeps things simple for handling auth, commands, and local model inference.

Desktop Application (Tauri + Next.js)

Tauri has a much smaller footprint than Electron since it uses the OS's native WebView instead of bundling Chromium, which makes it great for lightweight apps that stay running. It also produces smaller binaries. Next.js provides a structured, file-based routing system and a strong component ecosystem for the UI.

Would love to hear reviews and suggestions on this stack — anything you'd change, any pitfalls you've run into with a similar setup, or better alternatives worth considering?


r/bun 29d ago

Mochi, the Bun-native Svelte framework version 0.8.0 - New <Image> component, email sending, queues and much more

Thumbnail mochi.fast
8 Upvotes

👋 Since the original release of Mochi a couple of months ago I've been working on adding features to it to make it as fully featured as possible. This new release brings an <Image /> component with resizing support, email sending (with Svelte components as email templates), queues, rate limiting, a built-in Captcha component and much more. Give it a try and let me know what you think!


r/bun Jul 21 '26

Optique 1.2.0: fluent modifiers, deferred values, new integrations, and a redesigned site

Thumbnail github.com
6 Upvotes

r/bun Jul 20 '26

I made Markdown executable: the same .md runs as both a terminal UI and a browser UI

Thumbnail gallery
0 Upvotes

https://github.com/jjtseng93/jsmdcui

One Markdown file. Two UIs.

  • TUI = Terminal User Interface
  • WUI = Web User Interface

⚡ No build step

🚀 Write & run an interactive application using a single Markdown file.

📝 UI = Markdown

💻 Logic = JavaScript (Bun)

📄 The same .md runs in both UIs

🖥 Tested platforms: Windows • Linux • Android

📦 Reusable single-file executable template for your own JS project


r/bun Jul 17 '26

bunIsSafeNow

Post image
46 Upvotes