/stackrun

It simplifies running multiple services concurrently with optional Cloudflare tunneling (It's a wrapper around "concurrently" and "cf-tunnel" packages)

Primary LanguageTypeScriptMIT LicenseMIT

🥞 stackrun 🏃

stackrun is a wrapper around concurrently and cf-tunnel that simplifies running multiple services with optional integrated Cloudflare tunneling.

npm version npm downloads codecov license

✅ Features

  • Simple Configuration: Single config file for all your services and tunneling needs
  • Service Execution: Run multiple services simultaneously with concurrently
  • Cloudflare Tunneling: Built-in support for exposing local services via cf-tunnel
  • Flexible Configuration: TS/JS/JSON config files with c12 loader
  • Environment Management: Define regular and tunnel-specific environment variables for each service
  • Lifecycle Hooks: Run commands before starting and after stopping your services
  • Smart Output Handling: Color-coded service output with customizable prefixes

🚀 Usage

CLI:

Install package globally:

# npm
npm install -g stackrun

# pnpm
pnpm install -g stackrun

CLI usage:

# Run with default config file
stackrun

# With custom config file
stackrun -c custom.config.js

# Enable tunneling
stackrun --tunnel
# or set env var
TUNNEL=true stackrun

Configuration file:

// stack.config.ts
import { defineStackrunConfig } from "stackrun";

export default defineStackrunConfig({
  concurrentlyOptions: { killOthers: "failure" },
  commands: [
    {
      name: "api",
      command: "npm run dev",
      cwd: "./api",
      url: "http://localhost:4000",
      tunnelUrl: "https://api.example.dev",
    },
    {
      name: "web",
      command: "npm run dev",
      cwd: "./web",
    },
  ],
});

API:

Install package:

# ✨ Auto-detect
npx nypm install stackrun

# npm
npm install stackrun

# yarn
yarn add stackrun

# pnpm
pnpm install stackrun

# bun
bun install stackrun

# deno
deno install stackrun

API usage:

ESM (Node.js, Bun, Deno)

import { stackrun, defineStackrunConfig } from "stackrun";

CommonJS (Legacy Node.js)

const { stackrun, defineStackrunConfig } = require("stackrun");

⚙️ Options

concurrentlyOptions

  • Type: ConcurrentlyOptions
  • Default: { killOthers: "failure", handleInput: true, prefixColors: "auto" }

All options from the concurrently API including killOthers, prefix formatting, max processes, and more.

tunnelEnabled

  • Type: boolean
  • Default: false

When true, creates tunnels for services with url and tunnelUrl defined.

cfTunnelConfig

  • Type: Omit<TunnelConfig, "ingress"> & { commandOptions?: {...} }

  • Default:

    {
      cfToken: process.env.CLOUDFLARE_TOKEN,
      tunnelName: "stackrun",
      removeExistingTunnel: false,
      removeExistingDns: false,
      commandOptions: {
        name: "Tunnel",
        prefixColor: undefined,
      },
    }
    

Configuration for cf-tunnel. All options except ingress are supported (ingress is automatically generated from command entries).

You can also customize how the tunnel command appears in the output using commandOptions:

cfTunnelConfig: {
  cfToken: process.env.CF_TOKEN,
  tunnelName: "my-project",
  // Customize the tunnel command options passed to concurrently when running cf-tunnel
  commandOptions: {
    name: "TUNNEL",
    prefixColor: "cyan"
  }
}

beforeCommands

  • Type: string[]
  • Default: []

Commands to run before starting the services.

afterCommands

  • Type: string[]
  • Default: []

Commands to run after all services have completed.

commands

  • Type: StackrunConfigCommands[]
  • Required: Yes

An array of command configurations to run concurrently. Extends concurrently's Command type with additional stackrun-specific properties for tunneling.

Each command configuration supports:

Option Type Description
command string Command to run (required)
name string Name for the command in logs
cwd string Working directory for the command
env Record<string, string | boolean | undefined> Environment variables
prefixColor string Color for the command prefix
url string Local URL for tunneling (required for tunnel creation)
tunnelUrl string Public URL for tunnel (required for tunnel creation)
tunnelEnv Record<string, string | boolean | undefined> Environment variables that override regular env when tunneling is enabled

Additional options from concurrently's Command are also supported.

📝 Examples

Basic Stack

// stack.config.ts
import { defineStackrunConfig } from "stackrun";

export default defineStackrunConfig({
  commands: [
    {
      name: "api",
      command: "npm run dev",
      cwd: "./api",
      prefixColor: "green",
    },
    {
      name: "web",
      command: "npm run dev",
      cwd: "./web",
      prefixColor: "blue",
    },
  ],
});

With Docker and Tunneling

// stack.config.ts
import { defineStackrunConfig } from "stackrun";
import "dotenv/config";

export default defineStackrunConfig({
  tunnelEnabled: true,
  cfTunnelConfig: {
    cfToken: process.env.CF_TOKEN,
    tunnelName: "my-project",
    removeExistingTunnel: true,
  },
  beforeCommands: ["docker compose -f docker-compose.dev.yml up -d db"],
  afterCommands: ["docker compose -f docker-compose.dev.yml down db"],
  commands: [
    {
      name: "api",
      command: "npm run dev",
      cwd: "./api",
      url: "http://localhost:4000",
      tunnelUrl: "https://api.example.dev",
      prefixColor: "green",
    },
    {
      name: "web",
      command: "npm run dev",
      cwd: "./web",
      url: "http://localhost:3000",
      tunnelUrl: "https://app.example.dev",
      prefixColor: "blue",
    },
  ],
});

💻 Development

Local development
  • Clone this repository
  • Install latest LTS version of Node.js
  • Enable Corepack using corepack enable
  • Install dependencies using pnpm install
  • Run interactive tests using pnpm dev

License

Published under the MIT license.

Contributors

Published under the MIT license. Made by @jasenmichael ❤️


🤖 auto updated with automd