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

spin-cli

v0.1.2

Published

Beautiful interactive CLI for managing multiple dev services

Downloads

371

Readme

! This is an idea I've been playing around with. It works well, but it's in very early development. The API will likely not remain stable. Although please enjoy, and send me some feedback if you try it out <3.

spin-cli

A beautiful interactive TUI for managing multiple dev services. Start your entire development stack with a single command, view logs in real-time, and control everything with vim-style keyboard shortcuts.

MIT License Node.js

Features

  • Interactive TUI — Full-screen terminal interface with real-time log streaming
  • Service Management — Start, stop, and restart shell commands or Docker containers
  • Service Groups — Organize services into groups for common workflows (e.g., spin dev)
  • Dependencies — Define service dependencies with automatic startup ordering and env sharing
  • Command Palette — Run ad-hoc commands with : (like vim), with fuzzy search
  • Background Scripts — Minimize running commands to the background
  • On-Demand Services — Only show services you're actively using; press s to start others
  • PTY Support — Proper rendering for TUI programs like ngrok, htop, etc.
  • MCP Integration — Built-in MCP server for AI assistants (Cursor, Claude Desktop)
  • Vim Keybindings — Navigate with j/k, g/G, scroll with Ctrl+d/u
  • TypeScript Config — Type-safe configuration with IntelliSense support

Installation

npm install -g spin-cli

Or with your preferred package manager:

pnpm add -g spin-cli
yarn global add spin-cli

Quick Start

  1. Initialize spin in your project:
spin init
  1. Edit spin.config.ts to configure your services:
import { defineConfig, shell, docker } from "spin-cli";

export default defineConfig({
  runnables: {
    api: shell("npm run dev", {
      cwd: "./api",
      description: "API server",
      readyWhen: (output) => output.includes("listening"),
    }),

    web: shell("npm run dev", {
      cwd: "./web",
      description: "Web frontend",
    }),

    postgres: docker("postgres:15", {
      description: "PostgreSQL database",
      ports: ["5432:5432"],
      env: { POSTGRES_PASSWORD: "dev" },
    }),
  },

  groups: {
    dev: ["postgres", "api", "web"],
  },
});

Note: You can also import from ./.spin/cli (auto-generated by spin init), which re-exports from spin-cli. Both work identically.

  1. Start your services:
spin          # Start all services
spin dev      # Start the "dev" group
spin api web  # Start specific services

Configuration

Shell Commands

shell("npm run dev", {
  cwd: "./packages/api", // Working directory
  description: "API server", // Shown in TUI
  env: { PORT: "3000" }, // Environment variables
  dependsOn: ["postgres"], // Wait for dependencies
  readyWhen: (
    output, // Ready detection
  ) => output.includes("Listening"),
  onReady: ({ output, setEnv }) => {
    // Extract dynamic values and share with dependents
    const port = output.match(/port (\d+)/)?.[1];
    if (port) setEnv("API_PORT", port);
  },
  pty: false, // Use PTY for TUI programs (default: false)
});

Docker Containers

docker("postgres:15", {
  description: "PostgreSQL database",
  ports: ["5432:5432"], // Port mappings
  volumes: ["./data:/var/lib/postgresql/data"],
  env: {
    POSTGRES_USER: "dev",
    POSTGRES_PASSWORD: "dev",
    POSTGRES_DB: "app",
  },
});

Service Groups

groups: {
  dev: ['postgres', 'redis', 'api', 'web'],
  backend: ['postgres', 'redis', 'api', 'queue'],
  infra: ['postgres', 'redis'],
}

Dependencies

Services can depend on other services. Spin ensures dependencies are started first and waits for them to be ready before starting dependent services.

runnables: {
  postgres: docker('postgres:15', {
    readyWhen: (output) => output.includes('ready to accept connections'),
  }),

  api: shell('npm run dev', {
    dependsOn: ['postgres'],  // Waits for postgres to be ready
  }),
}

Keyboard Shortcuts

| Key | Action | | -------------- | ------------------------------------------- | | 1-9 | Switch to service by number | | Tab | Next service/background script | | Shift+Tab | Previous service/background script | | j/k or ↓/↑ | Scroll down/up (3 lines) | | Ctrl+d/u | Page down/up (half screen) | | g/G | Go to top/bottom | | f | Scroll to bottom and follow new output | | : | Open command palette | | r | Restart current service | | s | Open service picker (start hidden services) | | x | Stop current service | | a | Start current service | | R | Restart all visible services | | b | View background scripts (when available) | | ? | Show help | | q | Quit |

Command Palette

Press : to open the command palette. You can:

  • Run any shell command (e.g., :npm test)
  • Execute scripts from package.json files
  • Run scripts from a configured scripts folder
  • Search through command history

Commands run in a dedicated output view where you can:

  • View output in real-time
  • Minimize to background with m
  • Cancel with c
  • Rerun with r
  • Close with Escape

MCP Integration

Spin includes a built-in MCP (Model Context Protocol) server that allows AI assistants to interact with your services.

Automatic Setup

When you run spin init, spin automatically configures MCP for detected AI tools (Cursor, Claude Desktop).

Manual Setup

Add to your MCP configuration:

{
  "mcpServers": {
    "spin": {
      "command": "spin",
      "args": ["mcp"]
    }
  }
}

MCP Commands

spin mcp           # Start MCP server (stdio)
spin mcp install   # Install MCP config to detected tools
spin mcp status    # Show installation status
spin mcp update    # Update .spin folder and install MCP

Available MCP Tools

Always available:

  • list_services — List all configured services with current status
  • get_service_status — Get detailed status of a specific service

When spin TUI is running:

  • get_logs — Get recent logs from a service (with configurable line count)

When spin TUI is not running:

  • start_spin — Returns the command to start spin (with optional group parameter)

CLI Commands

spin                      # Start all services
spin <services...>        # Start specific services or groups
spin list                 # List all services and groups
spin init                 # Initialize spin in your project
spin init --personal      # Initialize for personal use (gitignored)
spin init --force         # Overwrite existing configuration
spin mcp                  # Start MCP server
spin mcp install          # Install MCP to detected AI tools
spin mcp status           # Show MCP installation status
spin mcp update           # Update .spin folder and install MCP
spin uninstall            # Remove spin from your project
spin uninstall --force    # Remove without confirmation
spin --help               # Show help
spin --version            # Show version

Team Workflow

Spin is designed for team adoption:

  1. Commit spin.config.ts — Share configuration with your team
  2. .spin/cli.ts is auto-generated — Each developer runs spin and the CLI file is generated automatically
  3. MCP installs per-user — AI tool integrations are installed to user-specific config files

Team members just need to:

npm install -g spin-cli
spin  # Auto-generates .spin/cli.ts and starts services

Advanced Configuration

Script Sources

Configure where the command palette finds scripts:

import { defineConfig, shell, packageScripts, scriptsFolder } from "spin-cli";

export default defineConfig({
  runnables: {
    /* ... */
  },

  scripts: [
    // Include scripts from all package.json files
    packageScripts(),

    // Include scripts from a folder with a runner
    scriptsFolder("./scripts", "bun", {
      label: "scripts",
      overrides: {
        "migrate.ts": { confirm: true, description: "Run database migrations" },
      },
    }),
  ],
});

The scriptsFolder() function requires a runner as the second argument:

// Simple runner (bun, node, bash, etc.)
scriptsFolder("./scripts", "bun");

// Docker runner - execute scripts inside a container
import { dockerContext } from "spin-cli";
scriptsFolder("./ops/scripts", dockerContext("ops-container"));

// Kubernetes runner - execute scripts inside a pod
import { kubernetes } from "spin-cli";
scriptsFolder(
  "./k8s-scripts",
  kubernetes({
    selector: "app=api",
    namespace: "staging",
    runner: "bun run",
  }),
);

Shell Command Prefixes

Configure command prefixes that bypass fuzzy search and run immediately:

export default defineConfig({
  runnables: {
    /* ... */
  },

  // Commands starting with these prefixes run immediately without fuzzy search
  shellCommands: [
    "npm",
    "pnpm",
    "yarn",
    "bun",
    "git",
    "docker",
    "kubectl",
    "make",
  ],
});

PTY Support for TUI Programs

Some programs (like ngrok, htop, or interactive CLIs) require a pseudo-terminal to display properly. Enable PTY mode for these:

ngrok: shell("ngrok http 3000", {
  pty: true, // Enables PTY for proper TUI rendering
  readyWhen: (output) => output.includes("Forwarding"),
  onReady: ({ output, setEnv }) => {
    // Extract the ngrok URL and share with dependent services
    const url = output.match(/https:\/\/[^\s]+\.ngrok[^\s]*/)?.[0];
    if (url) setEnv("NGROK_URL", url);
  },
});

With pty: true, spin uses node-pty and xterm-headless to properly capture and render terminal escape codes.

Defaults

Configure default settings that apply to all runnables:

export default defineConfig({
  runnables: {
    /* ... */
  },

  defaults: {
    // Environment variables applied to all runnables
    env: {
      NODE_ENV: "development",
    },
    // Maximum lines kept in each service's output buffer (default: 1000)
    maxOutputLines: 500,
  },
});

Requirements

  • Node.js >= 18.0.0
  • Docker (optional, for Docker containers)

Development

# Install dependencies
pnpm install

# Run in watch mode
pnpm dev

# Build
pnpm build

# Run tests
pnpm test

# Type check
pnpm typecheck

# Lint
pnpm lint

License

MIT