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

1dxway

v0.1.15

Published

One DX Way

Readme

NPM Version

1dx

One DX Way.

Install

Run the installer from any project (Node 18+):

npx 1dxway

Run the monitor after setup:

npx 1dxway start

The 1dx CLI itself runs on Node (it uses node-pty for embedded service processes, which is currently broken on Bun). The services 1dx manages can still be written for and launched with bun — only the CLI host changed.

Service health checks

Each entry in services[].health of 1dx.json defines how 1dx decides whether a service is up. The monitor probes services in parallel every ~1 s and runs the result through a small state machine with hysteresis (a service must fail 3 consecutive probes to flip from RUNNING to STOPPED; a single success flips it back to RUNNING).

Supported health check types:

  • tcp — open a TCP connection to host:port (defaults to 127.0.0.1). Use this for services whose port is reserved but where you don't need to speak the protocol on top.

    { "type": "tcp", "host": "127.0.0.1", "port": 54322, "timeoutMs": 800 }
  • http — issue a HEAD (or GET) request to a URL and require the status code to be in expectedStatus (default: any 2xx/3xx/4xx that isn't 502/503/504). Use this for real liveness on HTTP services such as Vite, Kong, or edge functions.

    {
      "type": "http",
      "url": "http://127.0.0.1:8080/",
      "method": "HEAD",
      "expectedStatus": [200, 301, 404],
      "bodyContains": "optional substring of GET response",
      "timeoutMs": 1500
    }
  • process — match a running process by image name and/or by a substring of its full command line. Command-line matching is the recommended option for scripts spawned by Bun/Node where the OS image name is just bun/node.

    { "type": "process", "commandLineContains": "typesafe-i18n" }
  • ambient — check an external dependency. The only supported check today is docker, which calls docker info (cached for ~5 s, invalidated on every observed up/down transition).

    { "type": "ambient", "check": "docker" }
  • all — composite. Runs all sub-checks in parallel. The service is RUNNING only if every sub-check is up; if some sub-checks are up and others are down, the service is reported as DEGRADED (yellow); if every sub-check is down, the service is STOPPED.

    {
      "type": "all",
      "checks": [
        { "type": "tcp",  "port": 54321 },
        { "type": "tcp",  "port": 54322 },
        { "type": "http", "url": "http://127.0.0.1:54321/" }
      ]
    }

The legacy { "type": "port", "port": N } form is still accepted and is auto-rewritten to { "type": "tcp", "host": "127.0.0.1", "port": N } at load time, so existing configs keep working.

Dependencies between services

Add dependsOn: ["docker"] (or any other service id) to a service to make 1dx skip probing it while its dependency is not up. The badge for a service whose dependency is down/unknown renders as WAITING instead of flapping between RUNNING and STOPPED.

{
  "id": "backend",
  "title": "Backend (Supabase)",
  "dependsOn": ["docker"],
  "health": { "type": "all", "checks": [/* ... */] }
}

Status badges

  • ● RUNNING — all health checks pass.
  • ◐ DEGRADED — some sub-checks of an all composite are passing, others aren't. Useful for backends like Supabase where Kong can be up while Postgres is still restarting.
  • ○ WAITING — service depends on another service that is not yet up.
  • ○ CHECKING — the first probe hasn't finished yet.
  • ○ STOPPED — service is down (after the hysteresis threshold). When the underlying PTY exits unexpectedly the state machine flips to STOPPED immediately with the exit code in the reason field — no need to wait for the next probe.
  • ◐ STOPPING — 1dx is in the middle of stopping the service.

How services are run

Managed services run as node-pty children of the 1dx process — there are no external terminal tabs anymore.

This means:

  • 1dx owns each service's PID directly. Stopping a service is pty.kill() on that PID; restarting is kill() + spawn(). No more taskkill /T by command-line substring, no more sibling services dying because two services share a commandLineContains needle.
  • Exit codes flow straight back into the state machine, so an unexpected crash flips the row to STOPPED with a reason like process exited (code 1) instead of waiting for a probe to fail.
  • Output is buffered (~2000 lines per service, ANSI preserved) so you can open a log view on demand without losing scrollback.
  • All children are killed on SIGINT / SIGTERM / process exit — even uncaught exceptions — so you don't leak ports between runs.

Viewing service logs (split panel)

The dashboard intentionally stays compact: status, badge, port/PID, and one reason line per service. To see a service's live stdout, focus the service (arrow keys) and press Enter. A vertical split opens with the dashboard on the left and a stack of live log panes on the right:

project / 1dx 0.1.14            │  ▌ API Server   up   pid 12345   132 ln
────────────────────────────    │  GET / 200 12ms
●  API Server   up   :4001      │  POST /api/foo 201 8ms
↳ r Restart  s Stop             │  [bun] hot reload triggered
●  Worker      up   :4002       │  ──────────────────────────────────────
────────────────────────────    │    Worker   up   pid 12346   87 ln
                                │  processed job #432
Actions:                        │  processed job #433
  d. Diagnostics                │
  n. New terminal               │
  q. Quit                       │
Open logs: api, worker          │
Enter on a service: toggle ·    │
L: close all                    │

Each pane shows the tail of the service's ring buffer (~2000 lines) with ANSI colour preserved, and stays populated even after a service exits so you can read why it died until you restart it.

Dashboard-mode controls

While focus is on the dashboard (the default):

  • Enter on a focused service: pin that service's log pane (or unpin if already pinned). When nothing is pinned, the focused service is shown as a preview pane — same layout, but the title is marked ○ … preview instead of . Pin it with Enter (or just leave it as a preview that follows your dashboard cursor). The dashboard itself shows a small next to every pinned service title.
  • or Tab: focus the first open pane (enters Scroll mode). or Shift+Tab: focus the last open pane.
  • L (capital): close every open pane and return to dashboard-only view.
  • f: toggle fullscreen mode — hides the dashboard column so the log panes get the entire terminal width. Press it while a service row is focused (or any time inside Scroll mode); the first pane is auto-focused on entry so you immediately land somewhere usable, and f again restores the split view. When the dashboard cursor is on the global Actions menu instead of a service row, f keeps its configured meaning (e.g. the playground binds it to "Open in browser"), so you don't lose your global shortcut just because the log split is open.
  • / : navigate services and actions in the dashboard.

Pane Scroll mode

Entered via or Tab from the dashboard. The focused pane's header turns cyan and gets a marker plus a SCROLL badge. While in Scroll mode:

  • / (or Tab / Shift+Tab): cycle focus to the next/previous pane. Stepping past the last pane returns to the dashboard.
  • Esc: exit pane focus, return to the dashboard. If you're in fullscreen, Esc also drops fullscreen on the way out so you don't get stuck with an invisible dashboard.
  • / : scroll one line up/down.
  • PageUp / PageDown: scroll a viewport at a time.
  • e (or g / G): jump to the end (tail, newest content).
  • s: jump to the start of the buffer (oldest line still resident). This shadows the per-service s (stop) shortcut while you're in Scroll mode; stop is still reachable from the dashboard inline strip.
  • b: toggle a bookmark at the current bottom-of-view line. The header shows a •N indicator with the bookmark count, which turns into a yellow *N whenever the line at the bottom of the view is itself a bookmark.
  • n / N: jump to the next / previous bookmark. n moves toward the tail (newer content), N moves toward the top (older); both wrap around the ends of the list. Bookmarks are stored as absolute line indices, so they stay anchored to the same content as the ring buffer slides, and are cleared when the service is restarted.
  • [ / ]: move the focused pane up/down in the stack.
  • x: close just the focused pane.
  • L: close every pane.
  • f: toggle fullscreen (hide / show the dashboard column).
  • i: enter Input mode on the focused pane.
  • Other letter shortcuts that match a per-service action (e.g. r for restart) still fire on the focused pane's service, so you can restart from inside a pane without losing focus.

Mouse wheel also works in any open log pane: scroll up over a pane (no need to click first) to step into the buffer history, scroll down to ease back toward the tail. Wheeling auto-focuses the pane you're pointing at, so a follow-up b or e lands on the right one. Both wheel and keyboard scroll are clamped against the wrap-aware top of the buffer, so you can't overshoot. Mouse capture is disabled on exit; while 1dx is running you can still copy text by holding Shift (Windows Terminal / iTerm2 / GNOME / Konsole / vscode) or Alt (Alacritty / kitty), which bypasses the capture and lets the terminal do its native selection.

A thin scrollbar runs down the right edge of every pane. The bright thumb () shows the visible window's position inside the ring buffer; it spans the whole track when nothing has scrolled off the top yet, and shrinks/moves as you scroll up. Bookmarks appear on the same track as yellow markers, so you can see at a glance how the open bookmarks are distributed and use n / N to jump between them.

Pane Input mode

Entered via i from Scroll mode. The pane's header turns magenta and gets a marker plus an INPUT badge. Every keystroke other than Esc is forwarded into that service's PTY stdin:

  • Printable characters, Enter, Backspace, Delete, Tab, and arrow keys are translated to their standard terminal byte sequences.
  • Ctrl+letter is translated to the corresponding control byte (e.g. Ctrl+C0x03, Ctrl+D0x04). This means Ctrl+C inside Input mode signals the service, not 1dx.
  • Esc exits Input mode back to Scroll mode.

This is enough to drive things like Vite's r/o hotkeys, REPL prompts, or interactive CLI installers that ask y/n questions.

Opening a real external terminal

The t global action ("Open new terminal") still spawns a real terminal tab in your host terminal app (Windows Terminal, macOS Terminal.app, or the first available Linux terminal). Use this as the escape hatch whenever you need a free-form shell — it's intentionally not a PTY child of 1dx, so it survives 1dx exit and lets you type freely without modal mediation.

Debugging probes

Set 1DX_DEBUG=1 (or ONEDX_DEBUG=1) before launching the monitor to write every probe outcome (timestamp, state, streak counters, latency, reason) to .1dx/probe.log in your project. The bundled presets also include a Toggle health diagnostics action (default shortcut d) that shows the last probe result for each service inline in the TUI.

Per-service actions and focus navigation

In addition to the global actions list at the bottom of the monitor, each managed service has its own inline action menu. To reach it, press Up from the first global action item: focus moves to the last service in the list. Use Up/Down to move between services, Esc to jump back to the actions list, or Enter to open the focused service's full-screen log view.

While a service is focused 1dx shows a small radial menu directly under its row, e.g.:

  Backend (Supabase)   ● RUNNING   :54321   PID 12345
↳ r Restart  s Stop  m Run migrations   (Esc to leave)

The defaults are inferred from the service's existing fields and current state:

  • r Restart — only shown while the service is up or degraded (nothing to restart otherwise). With node-pty the flow is just pty.kill() on the current handle followed by pty.spawn() for the start command — no shell wrappers, no taskkill, and unrelated services are untouched.
  • s Stop/Start — toggles based on current state. If the service is up or degraded, s calls pty.kill(). If it is down/unknown/ dependencyDown, s spawns the service in a new PTY.

Customizing the built-in actions

Two optional fields on a service let you override how restart and stop execute:

{
  "id": "backend",
  "stop":    { "mode": "inline",   "command": "bun", "args": ["run", "supabase:stop"] },
  "restart": { "mode": "terminal", "shellCommand": "bun run supabase:stop && bun run supabase:start" }
}

mode accepts "internal" (default — use the built-in stop/restart flow), "inline" (run via the embedded CommandRunner UI), "external" (hand the TTY over to the command), or "terminal" (spawn a new terminal tab and run shellCommand there).

Adding extra inline actions per service

Add a service.actions[] array to attach any number of additional shortcuts to a service. Each entry has the same shape as a global action:

{
  "id": "api",
  "actions": [
    {
      "id": "ping",
      "label": "Ping",
      "shortcut": "p",
      "mode": "inline",
      "command": "curl",
      "args": ["-sS", "http://127.0.0.1:4001/"]
    }
  ]
}

If an entry uses one of the reserved shortcuts r or s, it replaces the auto-injected default for that key on that service. Other shortcuts are added on top of the defaults. Service-action shortcuts only fire when the corresponding service is focused, so they don't collide with global action shortcuts.

Publish

The repo includes a manual GitHub Actions workflow at .github/workflows/release.yml. Trigger it with patch, minor, or major to:

  • bump package.json
  • typecheck and smoke-test the CLI
  • publish to npm with provenance
  • push the release commit and tag
  • create a GitHub release