Skip to content
Development
Skill

/bun-hot-reloading

Use when implementing hot reloading with Bun (--hot, --watch), HMR, or automatic code reloading during development. Covers watch mode, hot mode, and HTTP server reload.

From plugin
secondsky-claude-skills
219183 skills42 agents62 commands2 MCP
Install
$ npx -y skills add secondsky/claude-skills --skill bun-hot-reloading --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/bun-hot-reloading

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when implementing hot reloading with Bun (--hot, --watch), HMR, or automatic code reloading during development. Covers watch mode, hot mode, and HTTP server reload.

SKILL.md

bun-hot-reloading.SKILL.md
name: bun-hot-reloading
description: Use when implementing hot reloading with Bun (--hot, --watch), HMR, or automatic code reloading during development. Covers watch mode, hot mode, and HTTP server reload.
metadata:
  version: "1.0.0"
license: MIT

Bun Hot Reloading

Bun provides built-in hot reloading for faster development cycles.

Watch Mode vs Hot Mode

| Feature | `--watch` | `--hot` | |---------|-----------|---------| | Behavior | Restart process | Reload modules | | State | Lost on reload | Preserved | | Speed | ~20ms restart | Instant reload | | Use case | Any file type | Bun.serve HTTP |

Watch Mode (--watch)

Restarts the entire process when files change.

# Basic watch mode
bun --watch run src/index.ts

# Watch specific script
bun --watch run dev

# Watch with test runner
bun --watch test

package.json Scripts

{
  "scripts": {
    "dev": "bun --watch run src/index.ts",
    "dev:server": "bun --watch run src/server.ts",
    "test:watch": "bun --watch test"
  }
}

Watch Behavior

  • Watches imported files automatically
  • Triggers on any `.ts`, `.tsx`, `.js`, `.jsx` change
  • Also watches `.json` imports
  • Restarts with fresh state

Hot Mode (--hot)

Reloads modules in-place without restarting the process.

bun --hot run src/server.ts

HTTP Server Hot Reload

// src/server.ts
let counter = 0; // State preserved across hot reloads

export default {
  port: 3000,
  fetch(req: Request) {
    counter++;
    return new Response(`Request #${counter}`);
  },
};
bun --hot run src/server.ts

When you modify `server.ts`, the module reloads instantly while `counter` keeps its value.

Bun.serve with Hot Reload

// src/server.ts
const server = Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response("Hello!");
  },
});

// Hot reload handler
if (import.meta.hot) {
  import.meta.hot.accept(() => {
    console.log("Hot reload!");
  });
}

console.log(`Server running on port ${server.port}`);

import.meta.hot API

// Check if hot reload is available
if (import.meta.hot) {
  // Accept updates to this module
  import.meta.hot.accept();

  // Accept with callback
  import.meta.hot.accept((newModule) => {
    console.log("Module updated:", newModule);
  });

  // Cleanup before reload
  import.meta.hot.dispose(() => {
    // Close connections, clear intervals, etc.
    clearInterval(myInterval);
  });

  // Decline hot reload (force full restart)
  import.meta.hot.decline();

  // Invalidate this module (trigger parent reload)
  import.meta.hot.invalidate();
}

HTTP Server Patterns

Express-like Pattern

// src/server.ts
import { createApp } from "./app";

const app = createApp();

const server = Bun.serve({
  port: 3000,
  fetch: app.fetch,
});

// Hot reload: recreate app
if (import.meta.hot) {
  import.meta.hot.accept((newModule) => {
    // Reload with new fetch handler
    server.reload({
      fetch: newModule.default.fetch,
    });
  });
}

Stateful Server

// src/server.ts
// Store in globalThis to survive reloads
globalThis.connections ??= new Set();

const server = Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response(`Connections: ${globalThis.connections.size}`);
  },
  websocket: {
    open(ws) {
      globalThis.connections.add(ws);
    },
    close(ws) {
      globalThis.connections.delete(ws);
    },
  },
});

if (import.meta.hot) {
  import.meta.hot.accept();
}

Custom Watch Implementation

// dev-server.ts
import { watch } from "fs";

const srcDir = "./src";
let server: ReturnType<typeof Bun.serve> | null = null;

async function startServer() {
  // Dynamic import with cache busting
  const module = await import(`./src/server.ts?t=${Date.now()}`);

  if (server) {
    // Bun 1.2+: server.stop() returns a Promise — await it so the old
    // socket is fully torn down before we rebind the same port.
    await server.stop();
  }

  server = Bun.serve(module.default);
  console.log(`Server started on port ${server.port}`);
}

// Initial start
await startServer();

// Watch for changes
watch(srcDir, { recursive: true }, async (event, filename) => {
  if (filename?.endsWith(".ts") || filename?.endsWith(".tsx")) {
    console.log(`\n[${event}] ${filename}`);
    await startServer();
  }
});

console.log("Watching for changes...");

WebSocket Live Reload

Server

// src/dev-server.ts
const clients = new Set<ServerWebSocket>();

const server = Bun.serve({
  port: 3000,
  fetch(req, server) {
    if (req.headers.get("upgrade") === "websocket") {
      server.upgrade(req);
      return;
    }

    // Inject reload script in dev
    const html = `
      <!DOCTYPE html>
      <html>
        <body>
          <h1>Hello!</h1>
          <script>
            const ws = new WebSocket('ws://localhost:3000');
            ws.onmessage = (e) => {
              if (e.data === 'reload') location.reload();
            };
          </script>
        </body>
      </html>
    `;
    return new Response(html, {
      headers: { "Content-Type": "text/html" },
    });
  },
  websocket: {
    open(ws) {
      clients.add(ws);
    },
    close(ws) {
      clients.delete(ws);
    },
  },
});

// Notify clients on file change
watch("./src", { recursive: true }, () => {
  clients.forEach((ws) => ws.send("reload"));
});

Vite Integration

For frontend development with HMR:

// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  server: {
    port: 5173,
    hmr: true,
  },
});
# Use Bun to run Vite
bunx --bun vite

Testing with Watch

# Watch tests
bun --watch test

# Watch specific file
bun --watch test src/utils.test.ts

# With bail (stop on first failure)
bun --watch test --bail

Environment Detection

// Ch
Read more
Ships withsecondsky-claude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

Get the whole plugin

Other skills on secondsky-claude-skills.