stackrun is a wrapper around concurrently and cf-tunnel that simplifies running multiple services with optional integrated Cloudflare tunneling.
- 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
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 stackrunConfiguration 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 stackrunAPI usage:
ESM (Node.js, Bun, Deno)
import { stackrun, defineStackrunConfig } from "stackrun";CommonJS (Legacy Node.js)
const { stackrun, defineStackrunConfig } = require("stackrun");- Type:
ConcurrentlyOptions - Default:
{ killOthers: "failure", handleInput: true, prefixColors: "auto" }
All options from the concurrently API including killOthers, prefix formatting, max processes, and more.
- Type:
boolean - Default:
false
When true, creates tunnels for services with url and tunnelUrl defined.
-
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"
}
}
- Type:
string[] - Default:
[]
Commands to run before starting the services.
- Type:
string[] - Default:
[]
Commands to run after all services have completed.
- 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.
// 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",
},
],
});// 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",
},
],
});Local development
Published under the MIT license.
Published under the MIT license. Made by @jasenmichael ❤️
🤖 auto updated with automd