One typed config
Describe every service once in stackctl.config.ts. Pick one and the services it needs come with it, started in order.
A terminal UI and CLI for a monorepo's services, infrastructure, tests and CI during development.
Services, what each one needs, how to tell it is ready, and the infrastructure under them, in TypeScript your editor checks. The terminal UI, your tests, CI and coding agents all read the same file.
The config file// stackctl.config.ts
import { defineConfig } from 'stackctl';
export default defineConfig({
reverseProxy: {
port: 4000,
routes: [
{ subdomain: 'api', service: 'backend' }, // http://api.localhost:4000
{ subdomain: 'app', service: 'frontend' }, // http://app.localhost:4000
],
},
services: {
backend: {
port: ({ envs }) => Number(envs.BACKEND_PORT),
healthcheck: '/health',
},
frontend: {
port: 3000,
deps: [{ service: 'backend', wait: true }],
urls: [{ label: 'home', url: '/' }],
},
},
infra: {
'docker-compose': {
services: {
db: {
afterReady: async ({ exec, fresh }) => {
await exec('pnpm', ['migrate']);
if (fresh) {
await exec('pnpm', ['seed']);
}
},
},
},
},
},
});