Skip to main content

Commands

FlowLayer starts and stops services with cmd and stopCmd.

cmd

cmd is the start command for a service:

{
"services": {
"api": {
"cmd": ["go", "run", "./cmd/api"]
}
}
}

If cmd is missing or empty, FlowLayer cannot start the service and startup fails with missing cmd.

stopCmd

stopCmd is optional. When present, FlowLayer runs it during graceful shutdown before sending SIGTERM to the managed process.

{
"services": {
"api": {
"cmd": ["go", "run", "./cmd/api"],
"stopCmd": ["./scripts/stop_service.sh", "--graceful"]
}
}
}

An empty stopCmd is allowed.

String form vs array form

Both cmd and stopCmd accept either a string or an array of strings.

String form:

{
"services": {
"frontend": {
"cmd": "npm run dev"
}
}
}

Array form:

{
"services": {
"frontend": {
"cmd": ["npm", "run", "dev"]
}
}
}

Confirmed parsing rules:

  • string form is split on whitespace
  • array form is preserved as-is
  • there is no shell-style quote parsing in string form

That last point matters. If an executable path or argument contains spaces, use the array form.

Direct exec, not implicit shell

FlowLayer runs commands with direct process execution. It does not wrap cmd or stopCmd in sh -c, bash -lc, or cmd /c.

If you need shell behavior such as pipes, redirects, loops, or variable expansion, call a shell explicitly:

{
"services": {
"echo": {
"cmd": ["sh", "-c", "while true; do echo flowlayer-up; sleep 2; done"]
}
}
}

Use direct exec whenever a normal argv-style command is enough.

Working directory

The current schema does not expose a per-service working directory field.

FlowLayer starts each process without overriding cwd, so child processes inherit the current working directory of the flowlayer-server process.

If you need a different directory today, either:

  • start flowlayer-server from that directory
  • or switch directories inside an explicit shell command

Graceful stop behavior

For a running managed service, FlowLayer stops in this order:

  1. run stopCmd if configured
  2. send SIGTERM to the managed process
  3. wait up to 8 seconds for exit
  4. send SIGKILL if the process is still alive

For services with a declared port, FlowLayer also verifies that the port is released before it reports the service as stopped.

stopCmd uses the same merged environment model as cmd. See Services.

Example

{
"services": {
"api": {
"cmd": ["go", "run", "./cmd/api"],
"stopCmd": ["./scripts/stop_service.sh", "--graceful"],
"env": {
"PORT": "3000"
},
"port": 3000
}
}
}

For startup ordering, continue with Waves. For readiness probes, continue with Readiness.