npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@remcostoeten/dev-menu

v0.2.0

Published

Zero-config dev process launcher and TUI for mono- and single-package repos

Downloads

389

Readme

dev-menu

Run all your dev servers from one terminal, with a keyboard bar for the things you do all day: open the app, restart a crashed process, free a stuck port, flip an env flag, read a grouped git status.

It works with no setup. Point it at a repo and it finds your apps (workspace packages, framework ports, a docker compose stack), starts them together, and prints colored, prefixed logs so you can tell who said what.

Requirements

Node 18+ or Bun — it runs on either, on Linux, macOS, or Windows. Optional: lsof (Linux/macOS) or netstat (Windows) for killing port listeners, and a clipboard tool for copying captured errors (wl-copy / xclip / xsel on Linux; pbcopy and clip ship with macOS and Windows). Run dev-menu doctor to check what your machine has.

Install

Run it once without installing:

bunx @remcostoeten/dev-menu
npx @remcostoeten/dev-menu

Or install it globally:

bun add -g @remcostoeten/dev-menu
npm install -g @remcostoeten/dev-menu

Either way the installed command is dev-menu. On Bun it runs natively; on Node it loads its TypeScript through jiti, so there is no build step and no Bun requirement.

First run

In a repo with no dev-menu.config.ts, a short wizard offers to detect your processes and write one. Say no and it auto-detects on every run instead. There is nothing you have to configure to get started.

Commands

Every command also accepts a short -x and a long --name form.

dev-menu                          run the TUI (dev mode)
dev-menu prod                -p   run the production build (start|preview|serve)
dev-menu run <tag...>             run only the named processes
dev-menu doctor              -d   check your setup (runtime, config, ports, tools)
dev-menu tags                     print the detected process tags
dev-menu init                -i   run the setup wizard again
dev-menu check-source-clean  -c   exit non-zero if guarded paths have uncommitted changes
dev-menu install-shell       -s   add `dm` / `devmenu` aliases + tab-completion (fish|bash|zsh)
dev-menu help                -h   show help
dev-menu version             -v   print the installed version

An unknown command errors and suggests the closest match instead of silently launching the TUI.

Running a subset

dev-menu run web api starts only those processes and skips the rest. Tags come from your config or from auto-detection — dev-menu tags lists them, and with shell integration installed, dev-menu run <Tab> completes them.

Doctor

dev-menu doctor checks the runtime version, whether your config loads, which processes were detected, and whether the package manager, port-killing tool, clipboard tool, and docker (when a compose stack is detected) are available. It also probes each configured port and warns when one is already taken. Exits non-zero when a required check fails.

Production mode

dev-menu prod (also dev-menu start or dev-menu preview) launches the same TUI, but instead of each app's dev script it auto-detects and runs the first of start, preview, or serve it finds in that app's package.json — via your package manager (bun/npm/pnpm/yarn). No config is needed; apps without one of those scripts are skipped. Build your apps first if their preview script expects a prior build.

Shell aliases and completion

install-shell writes short dm and devmenu aliases plus tab-completion for your shell. It auto-detects from $SHELL, or you name one explicitly, and you can add your own alias names after the shell:

dev-menu install-shell              # autodetect, installs dm + devmenu
dev-menu install-shell fish         # or bash | zsh
dev-menu install-shell fish men     # also install a custom `men` alias
dev-menu install-shell zsh --print  # print the snippet instead of writing it

For bash and zsh it appends a marked block to ~/.bashrc / ~/.zshrc (re-running replaces it, never duplicates). For fish it writes a function and completion file per alias under ~/.config/fish. After that, each alias runs dev-menu, <Tab> completes every command and flag, and dev-menu run <Tab> completes your project's process tags.

check-source-clean

check-source-clean is meant for a pre-format or pre-lint step, so a formatter cannot rewrite source you have not committed yet:

{
  "scripts": {
    "format": "dev-menu check-source-clean && oxfmt ."
  }
}

Keys

o  open a URL              i  incognito (next open in a private window)
r  restart (pick one/all)  E  captured errors (copy, clear, kill listeners, E+I hands them to an AI CLI)
p  stop/start one process  A  launch an AI CLI
k  kill port listeners     O  toggle .env options
s  git panel               x  run a configured script
q  quit

Git panel

s opens an interactive git panel instead of a read-only status: files are grouped into conflicts / staged / changes / untracked, and a cursor (j/k or arrows) selects one.

space  stage / unstage the selected file     c  commit staged (prompts for a message)
a      stage everything                      P  push
u      unstage everything                    U  pull
B      checkout a local branch               Esc back

Staging per file means partial commits without leaving the TUI. Push, pull, commit, and checkout show git's own output afterwards; any key returns to the panel.

The top status bar shows a dot per process — yellow while starting, green once its ready line appears in the logs, red after a crash, hollow when stopped with p — plus live CPU and memory usage for each process tree (Linux/macOS).

Configuration

Everything is optional. A field you leave out falls back to auto-detection or a sensible default. Create dev-menu.config.ts at the repo root:

import { defineConfig } from '@remcostoeten/dev-menu'

export default defineConfig({
  processes: [
    {
      tag: 'api',
      color: '33',
      cmd: 'bun',
      args: ['run', '--hot', 'src/index.ts'],
      cwd: 'apps/api',
      url: 'http://localhost:3000',
      port: 3000,
      openKey: 'a',
    },
    {
      tag: 'web',
      color: '36',
      cmd: 'bun',
      args: ['run', 'dev'],
      cwd: 'apps/web',
      url: 'http://localhost:5173',
      port: 5173,
      openKey: 'f',
    },
  ],
  envToggles: [
    { label: 'dev login bypass', key: 'DEV_LOGIN_BYPASS', file: 'apps/api/.env', restart: true },
  ],
  links: [{ label: 'dashboard', url: 'http://localhost:3000/admin', openKey: 'd' }],
  scripts: [
    { label: 'db migrate', cmd: 'bun', args: ['run', 'db:migrate'], cwd: 'apps/api', key: 'm' },
    { label: 'db seed', cmd: 'bun', args: ['run', 'db:seed'], cwd: 'apps/api' },
  ],
  guardedPaths: ['apps/web/src/', 'apps/api/src/'],
  autoRestart: false,
})

defineConfig is typed, so your editor lists and describes every field.

Where the config lives

The wizard can write the config to the repo root (committed) or to ~/.dev-menu, where it is symlinked in and git-ignored. Use the second option when you do not want dev tooling in the repo. Set DEV_MENU_HOME to change that directory.

Error patterns

dev-menu watches process output for errors and collects them in the E panel, starting a new block whenever an error header appears. It ships a generic set of patterns. Add your stack's own signatures with errorPatterns, which extend the defaults rather than replacing them:

export default defineConfig({
  errorPatterns: {
    line: [/\bDrizzleQueryError\b/, /\[better-auth\]/i],
    header: [/^\s*(NeonDbError|APIError):/i],
  },
})

Scripts

scripts adds one-off tasks (migrations, seeds, codegen) to the x menu, so you run them without leaving the TUI. Output is prefixed like any other process, and the exit code is reported. args, cwd, and key are optional.

Ready patterns

A process dot turns from yellow to green when its logs match a ready line (ready in …, Local: http://…, listening on …, and other framework defaults). Add your own with readyPatterns, which extend the defaults:

export default defineConfig({
  readyPatterns: [/API booted/i],
})

What auto-detection finds

  • Workspace packages from workspaces in package.json or from pnpm-workspace.yaml, running each one that has a dev script. Libraries and native shells like Tauri or Electron are skipped unless nothing else can run.
  • The package manager, from the lockfile (bun, pnpm, yarn, npm).
  • Ports, from a --port / -p / PORT flag in the dev script, known framework defaults (Next, Vite, Astro, Nuxt, and others), or dependencies.
  • A docker compose stack, added as a docker compose up process with live per-container health, unless your dev script already runs compose.
  • Each package's src/ folder, guarded for check-source-clean.

License

MIT