Skip to content

steveapo/pier

Repository files navigation

pier

npm version license: MIT

A small TUI dashboard for your local dev servers. Auto-discovers anything listening on common dev ports, launches saved projects, tails logs with framework-aware error/warning classification, tracks RAM + CPU per server, and auto-stops idle servers when there's no stdout and no incoming connections for 15 minutes.

Built for macOS — Linux mostly works too (uses lsof, ps, pgrep).

┌─ pier · local dev server dashboard ──── running 2 · err 0 · warn 2 ─┐
│ › ● 3000  Oikion MVP    MVP        45213  4m   612 MB  41%  0/2  managed │
│   ● 5173  Vite          docs-site  67890  1h   148 MB   3%  0/0  managed │
└─────────────────────────────────────────────────────────────────────┘
  ↑↓ select  n new  s stop  r restart  l logs  o browser  q quit

Install

pnpm add -g @steveapo/pier
# or npm i -g @steveapo/pier

Then from any directory:

pier

What it does

  • Auto-discovers every dev server listening on a dev-ish port (3000–9999 plus common outliers). No config required for that — your Next.js, Vite, Python http.server, anything.
  • Launches saved projects from ~/.pier/projects.json. First run drops a placeholder; press n then arrow to + Add new project… to open the macOS folder picker and register one — the start command is auto-suggested from your lockfile (pnpm/yarn/npm/bun) and package.json scripts.dev.
  • Captures stdout/stderr for anything pier launched, with framework-aware classification: Next.js's × Error: / , Vite's [vite] error, TypeScript error TS####, Python tracebacks (File "...", line N), HTTP request logs, deprecation warnings — all sorted into error / warn / request / info so you can filter.
  • Resource metrics — RAM (RSS, summed across the descendant tree so Next.js + swc + workers shows the real footprint) and CPU%, refreshed every 3s, colour-coded.
  • HTTP-aware idle auto-stop: a server is "idle" only when it has both no stdout for N minutes AND no ESTABLISHED connections to its port for N minutes. So chatty servers don't get killed during quiet refactoring, and silent-but-serving workers stay up.
  • Native macOS notifications on crashes, error spikes (throttled to one per 60s), and auto-stops.
  • Claim & restart: if you started a server in another terminal, pier auto-detects it as discovered. Logs aren't captured (macOS doesn't let you tap into another process's stdout retroactively), but you can press c in the logs view to sniff the original command via ps, stop the external process, and respawn it as managed — logs start streaming.

Config

~/.pier/projects.json is created on first run:

{
  "idleMinutes": 15,
  "projects": [
    {
      "id": "my-app",
      "label": "My App",
      "cwd": "/Users/you/Code/my-app",
      "command": "pnpm dev",
      "port": 3000,
      "idleMinutes": 30
    }
  ]
}
  • idleMinutes: 0 (top-level) disables auto-stop entirely.
  • Per-project idleMinutes overrides the global default.
  • Editing the JSON is supported; the launcher's + Add new project… is just a friendlier way to append to it.

Keys

List view (default)

key action
/ move cursor
n open launcher
s stop selected server
r restart (managed only)
l open logs for selected server
o open http://localhost:<port> in browser
x forget a stopped/crashed managed entry
q / Ctrl+C quit (stops all managed servers first)

Logs view

key action
Esc back to list
a show all lines
e errors only
w warnings only
h HTTP requests only
c (discovered server) claim & restart under pier
s / r stop / restart

Launcher

key action
/ select
Enter launch the selected project, or open folder picker on the + Add row
D remove the selected project from the config
Esc back to list

Columns

  • status dot — green running · yellow starting · red crashed · gray stopped
  • PORT — first listening port (detected via lsof)
  • PROJECT / CMD — project label (managed) or command name (discovered)
  • CWD — last segment of the working directory
  • PID — the actual server process (Node, not the shell wrapper)
  • UPTIME
  • RAM — RSS summed across the descendant tree, colour-thresholded at 1 GB (yellow) / 2 GB (red)
  • CPU — current %CPU summed across the tree (can exceed 100 on multi-core — that's expected during builds)
  • ERR / WRN — counters since pier started managing the process
  • SRCmanaged (pier spawned it) or discovered (pier found it via lsof)

Architecture

bin/pier.js                   # entry — imports dist/cli.js (or falls back to tsx + src)
bin/pier-dev.js               # `pnpm dev` entry — always tsx + src
src/cli.tsx                   # Ink app, polling loops, input dispatch
src/discover.ts               # lsof scan → ServerEntry[]
src/process.ts                # managed registry: spawn/kill, descendant tree, metric apply
src/ptree.ts                  # recursive `pgrep -P` walker
src/metrics.ts                # `ps -o rss,pcpu` sampler
src/parser.ts                 # framework-aware log line classifier
src/idle.ts                   # idle detection (stdout-silent AND connection-silent)
src/notify.ts                 # `osascript` notification wrapper
src/linker.ts                 # macOS folder picker + lockfile sniff + claim-external
src/config.ts                 # ~/.pier/projects.json
src/components/*.tsx          # Header, ServerList, LogPane, HelpBar

Builds with tsup into a single ESM file (dist/cli.js, ~200 KB). No build step required for local dev (pnpm dev uses tsx).

Develop

git clone https://github.com/steveapo/pier.git
cd pier
pnpm install
pnpm dev          # hot-loaded source via tsx
pnpm typecheck    # tsc --noEmit
pnpm build        # produce dist/

Publishing (maintainers)

pnpm version patch        # or minor / major
pnpm publish --access public
git push --follow-tags

prepublishOnly runs typecheck + build automatically.

Known limits

  • No log capture for discovered servers without claim-restart — macOS doesn't let you retroactively tap another terminal's stdout.
  • Idle = stdout-silent AND connection-silent for N minutes. Tunable per project.
  • No per-process disk I/O — would need dtrace (and SIP off) on macOS. Deferred.
  • macOS-first. Linux is best-effort (the codebase only uses POSIX tools); the folder picker is osascript which is macOS-only — Linux falls through with a friendly error.

License

MIT © Stavros Apostolou

About

No description, website, or topics provided.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors