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

devtooie

v0.5.0

Published

Dependency-aware CLI for running a monorepo's local dev processes.

Readme

devtooie

A dependency-aware terminal UI (TUI) for running a monorepo's packages during local development.

dev + TUIdevtooie.

You describe your packages once, in a small typed config file. devtooie resolves build-time, dev-time, and runtime dependencies between them, builds whatever needs building (in the right order), and then runs the packages you picked.

devtooie's terminal UI driving the example monorepo

Features

  • Dependency-aware builds. Declare build/dev/runtime deps once; devtooie builds what needs building, in the right order, before it runs anything.
  • Language-agnostic packages. A package is driven through a handful of named scripts, so it can be written in anything: a Node package (via its package.json) or a Go, Rust, … package (via a Makefile with the equivalent targets). See Package supporting scripts.
  • Streamed, filterable logs. Every package's output is streamed live into one combined view; filter it down to a single package or a search term on the fly (the f hotkey; matching is case- and accent-insensitive).
  • Structured logs, by default. devtooie auto-formats every package's JSON logs (Go slog, pino, winston, …) as a colored [LEVEL] message for local dev — no NODE_ENV branching in your app, and nothing to configure. See Logging.
  • Two run modes. An interactive terminal UI to pick and watch packages, or a --plain log-streaming mode for coding agents.
  • One-off commands. devtooie cmd runs a single command (or a package script/target) in a package's directory with that package's resolved environment — for migrations, seeds, scrapers, or an agent driving your project. See Running one-off commands.
  • Per-package hierarchical .env loading. Each package's .env files (workspace- and package-scoped) are resolved and injected into its process automatically — and live-reloaded, restarting the affected package when a file changes.
  • Readiness ordering. healthcheck + waitFor hold a package until the services it needs are actually up.
  • Lifecycle-aware. Each package declares whether its dev process watches or just builds, so you (or an agent) know exactly what to do after a code edit.
  • Control API + agent skill. A localhost HTTP API drives a running session headlessly and lets a second invocation hand off cleanly; an installable skill teaches a coding agent to use it.

Example

A complete, runnable example monorepo lives in example/: four packages — a shared TypeScript library (isomorphic), a Node API (backend), a Go worker driven through a Makefile (worker), and a web frontend — wired up with dependency-aware builds, .env loading, healthchecks, and waitFor readiness ordering.

Requirements

  • Node 20+. A .ts config additionally needs Node ≥23.6 (native type-stripping); on older Node, use a compiled devtooie.config.js/.mjs.
  • Unix only (macOS/Linux). Windows is not supported.
  • pnpm. Node packages are run with pnpm run <script>, and packages that depend on each other are resolved through pnpm workspace links (workspace:*). (Makefile packages are run with make instead.)
  • A package.json (or Makefile) per package with the scripts devtooie drives (dev, build, ...) — see Package supporting scripts below.

Install

pnpm add -D devtooie

Getting started: devtooie init

pnpm devtooie init

This is an interactive, idempotent setup flow. It will:

  1. Ask whether to install the agent skill (recommended: yes).
  2. Scaffold devtooie.config.ts at your repo root (an existing config file is left untouched).
  3. Reconcile a root tsconfig.json so the config type-checks with Node globals in scope (idempotent — your other settings are left untouched).
  4. If you opted in to the skill, install it.

Pass -y/--yes to accept the defaults non-interactively.

After that, fill in the scaffolded config's packages array with your real packages (see below) and run pnpm devtooie.

devtooie.config.ts

The one file you author and commit — the single source of truth the CLI reads on every run.

import { defineConfig } from 'devtooie';

export default defineConfig({
  packages: [
    {
      name: 'core-api',
      port: 3001, // is provided as PORT environment variable to the process
      // `$port` is substituted with this package's `port`.
      healthcheck: 'http://localhost:$port/health',
    },
    {
      name: 'worker',
      // a dev process that doesn't watch files: it builds once, then runs. devtooie
      // doesn't watch your source, so after you edit its code you (or an agent, via the
      // control API) restart it — the command's flags say which. See docs/package-lifecycle.md.
      command: ['start', { watches: false, builds: true }],
    },
    {
      name: 'web',
      port: 3000,
      waitFor: ['core-api'], // hold until core-api's healthcheck passes
      deps: { runtime: ['core-api'] }, // selecting web also runs core-api
    },
  ],
});

See Configuration options for every defineConfig and package field.

Running the Terminal UI

pnpm devtooie

Package supporting scripts

devtooie drives each package through named scripts — a Node package declares them in its package.json scripts; a package in any other language (Go, Rust, …) declares the equivalent make targets in a Makefile. devtooie invokes them as pnpm run <name> or make <name>.

  • dev — the long-running process devtooie starts and streams. An application usually needs only this; devtooie builds its dependencies for it.
  • build — a shared library that other packages build against adds this too, so devtooie can build it in the build phase before its dependents start.

A shared library (Node) — dev + build:

// packages/shared/package.json
{
  "name": "shared",
  "scripts": {
    "dev": "tsc --watch", // re-emits dist on change
    "build": "tsc",
  },
}

An application needs only a dev process — a Node backend:

// packages/backend/package.json
{
  "name": "backend",
  "scripts": {
    "dev": "node --watch src/index.ts",
  },
}

…or a Go program, via a Makefile:

# packages/worker/Makefile
.PHONY: dev
dev:
	@go run .

An app can add build + clean too, for the occasional case where you need to rebuild it from scratch to clear stale build output — those enable the rebuild command (the b hotkey / POST /command/rebuild); see Package lifecycle.

Running one-off commands (devtooie cmd)

Sometimes you don't want the whole session — you just need to run one command with a package's exact environment: a migration, a seed script, a scraper, a REPL. devtooie cmd does that. It runs a command in a package's directory with that package's resolved env vars injected — the same environment the TUI would give it:

cd packages/api
devtooie cmd -- pnpm run migrate     # a literal command, in api's dir with api's env
devtooie cmd -c seed -- --rows=100   # run api's `seed` script/target, forwarding args
cd ../..
devtooie cmd -p api -- pnpm start    # or target a package by name, from anywhere

The package is inferred from your current directory (or named explicitly with -p). Output streams to your terminal and is also written to a logfile. It's especially handy for a coding agent driving your project. Full reference: devtooie cmd.

Configuration options

The full defineConfig and per-package field reference — including dependencies, TypeScript project references, and typed package names — lives in docs/configuration.md.

Logging

devtooie auto-formats structured (JSON) logs — from Go slog, pino, winston, … — into a colored [LEVEL] message for local dev, with no NODE_ENV branching and nothing to configure. You can add on-screen timestamps, and override or customize the formatter per package. See docs/logging.md.

Every session is also teed to a timestamped logfile. Read the current one from another terminal with devtooie logs (or devtooie logs -f to follow it live) — see devtooie logs.

Package lifecycle when you edit code

A package's command flags declare whether its dev process watches or just builds, which tells you (or an agent) whether to restart or rebuild it after a code edit. See docs/package-lifecycle.md.

Environment (.env) loading

devtooie loads .env files for every package it runs and injects them into that package's child process — merged over the current process.env without mutating it. Parsing is handled by dotenvx under the hood. Files are resolved at two scopes: the workspace root and the package's own directory. Only files that exist are loaded.

your-monorepo/
├── .env                     # workspace scope — base for every package
├── .env.local               # workspace scope, higher precedence
└── packages/
    ├── core-api/
    │   ├── .env              # package scope — overrides workspace scope
    │   └── .env.local        # highest precedence for core-api
    └── web/
        └── .env

Default files, ascending precedence within a scope:

  1. .env
  2. .env.development
  3. .env.local

Package scope overrides workspace scope, and within a scope a later file overrides an earlier one. ${VAR} references expand against already-loaded files and the current environment; file values win over the ambient environment (so NODE_OPTIONS=$NODE_OPTIONS --flag extends the inherited value).

A package's port is also injected as PORT (an explicit .env PORT still overrides it).

Customize the list via env.files (each name is still resolved at both scopes):

defineConfig({
  env: { files: ['.env', '.env.local'] },
  packages: [/* … */],
});

While a session runs, devtooie watches these files (and where new ones would appear) and restarts the affected package(s) on change — editing a workspace-level file restarts every running package that uses it.

The same resolution is available as a standalone command: from inside a package's directory, devtooie cmd -- <command> runs a one-off command in that package's dir with its resolved env (or invoke one of its scripts/targets with -c) — see devtooie cmd.

Advanced CLI usage

Every flag and subcommand — plus devtooie cmd for running a command in a package's environment on demand — is documented in docs/cli.md.

Agent skill

If you opt in during devtooie init, devtooie installs an agent-facing skill file at .claude/skills/devtooie/SKILL.md (and, best-effort, under .agents/ / .cursor/ if those directories already exist). It teaches a coding agent how to run devtooie headlessly (--plain -p <package>), drive a running session through the control API, read the logfile for debugging, and onboard a new package. The installed file is managed — treat it as generated, not something to hand-edit. devtooie init and every devtooie run refresh it to the installed version.

The skill points the agent at a single consolidated guide, packages/devtooie/docs/agents.md — the same material as this README plus how to drive devtooie headlessly, in one self-contained file. It's the one doc that ships inside the package (so the skill can load it from node_modules); the topic docs above live at the repo root.

Control API

While a session runs, devtooie exposes a localhost-only HTTP API for driving it (restart/rebuild a package, query status, hand off between invocations). See docs/control-api.md.

License

MIT