Configuration file
Config discovery, top-level fields, and every service field.
blink.yml lists the services to supervise. blink reads blink.yml, blink.yaml, blink.toml, or blink.json. This page documents how the file is found and every field it can carry, apart from the typed runtime blocks, which live in the runtime reference.
Discovery and loading
blink reads one project config file. With no explicit path it walks up from the current directory and takes the first file it finds, so you can run blink from any subdirectory. The names searched, in order, are blink.yml, blink.yaml, blink.toml, blink.json. The format is chosen from the file extension, not the contents.
-c / --config (or $BLINK_CONFIG) names a config path explicitly, which skips the walk-up. A named-but-missing config or a parse error fails hard. Only a missing config with no -c falls back to zero-config detection.
Note
Before any config is read, blink loads <cwd>/.env into the process environment. It only sets keys that are not already present, so a value exported in your shell wins over the file. A missing .env is not an error. This is a single top-level .env. Per-service .env files are read only during detection to sniff ports.
Top-level fields
| Field | Type | Default | Meaning |
|---|---|---|---|
ui | string | auto | interface backend, one of blink (TUI), plain (line-prefixed stdout), headless (alias none). Empty auto-selects plain when stdout is not a TTY, else blink. |
dir_root | string | config file's directory | the base every service dir/include resolves against. |
zen | bool | false | start the TUI without chrome (native scrollback). -z/--zen forces it on. |
force_shutdown | bool | true | project-wide default for reclaiming a service's declared ports before start. Override per service. |
logs.write | bool | true | write <log_dir>/<svc>.log for every service. The --logs flag and the TUI L key override at run time. |
paths | object | derived | directory layout, see Paths and environment. |
control.keys | map | default keymap | TUI key rebinds, see Keybindings. |
services | list | (none) | the supervised units, documented below. |
An unknown ui value fails at run time. force_shutdown and logs.write are nullable, so leaving them out is not the same as setting false. Unset falls back to the default shown above.
Generic service fields
services: is the ordered list of units blink supervises. These fields apply to every runtime.
| Field | Type | Default | Meaning |
|---|---|---|---|
name | string | (required) | unique identifier. Every reference (reload_on_service, log file, TUI row) keys off it. Empty or duplicate names are rejected. |
disabled | bool | false | keep the service in the file but leave it out of the run. blink edit sets this when you deselect. |
dir | string | dir_root | service working directory, relative to dir_root. Commands run here. |
runtime | string | shell | lifecycle owner, one of shell, go, node, docker. See Runtimes. |
env | map | (none) | string map merged into every command's environment, and the lookup source for env-referenced ports. Your keys win over runtime-contributed ones. |
A non-shell runtime contributes defaults (commands, watched extensions, install steps) merged into the service, and anything you set explicitly wins.
commands
Three optional phases run in order on every boot or restart.
commands:
setup:
- command: go mod download
build:
command: go build -o ./bin/api ./cmd/api
run:
command: ./bin/api
before:
- command: ./scripts/migrate.sh
after:
- command: ./scripts/notify-down.sh
command_cleanup: ./scripts/cleanup.sh
service: truesetup (a list) runs once on the first boot and again only when a runtime-declared trigger file changes, such as package.json or go.mod. It never runs on an ordinary source reload, so a live reload stays fast. This is where one-time preparation like dependency installs belongs.
build (a single command) runs on every boot and every restart, before the run command. Status shows building while it runs, and a failing build marks the service crashed and skips run.
run (a single command) is the main process. Status shows running once started.
Each run/build/before/after/setup entry is a command with these fields.
| Field | Type | Meaning |
|---|---|---|
command | string | the shell command. Empty is skipped. |
dir | string | joined onto the service dir for this command only. |
before | list | commands run to completion before command. |
after | list | commands run after command (skipped for a long-running service: true process). |
command_cleanup | string | shell command run at supervisor shutdown. Honored only on the run command. |
service | bool | marks the command as a long-running process rather than a one-shot. |
A one-shot run command (the default) is expected to finish. When it completes, its after chain runs and the status becomes exited. A long-running command (service: true) is the service process. When it exits the status becomes exited and the after chain is skipped. That skipped chain is the only effect of service: true. blink does not auto-respawn a service process, a restart comes only from a file change or a manual r in the TUI.
fs
Controls which file changes the watcher reacts to. Consulted only when reload is enabled.
fs:
extensions: [go, sql]
include:
- ../schema
exclude:
- "**/testdata/**"| Field | Type | Meaning |
|---|---|---|
extensions | list | filters matched files by extension (leading dot optional, case-insensitive). Empty watches every extension. |
include | list | extra recursive watch roots resolved against dir_root, for cross-module paths like ../schema. |
exclude | list | globs subtracted from the matched set, on top of the built-in excludes. |
blink always excludes .git, node_modules, dist, build, .next, .idea, .vscode, .blink at any depth, plus .DS_Store.
reload
Restart triggers and cross-service dependencies.
reload:
reload: true
reload_on_delete:
- "**/*.sqlite"
reload_on_service:
- db| Field | Type | Meaning |
|---|---|---|
reload | bool | enable file-change-driven restart. Not implied by runtime:, so a shell service must set it explicitly. |
reload_on_delete | list | globs that restart when a matching file is removed. Works even with reload: false. |
reload_on_service | list | orders startup (wait for each dep) and cascades restarts (restart when a dep restarts). |
Unknown dependency names and cycles in reload_on_service are rejected at load time.
ports and force_shutdown
ports lists the TCP ports the service binds. They feed the port-reclaim step before start.
ports:
- 8080 # literal
- PORT # env-var name, resolved at runtime
- ${API_PORT} # sigil accepted on input, stored as API_PORT
force_shutdown: falseA bare integer is a literal port and must be 1 to 65535. Anything non-numeric is an env-var name. A ${KEY} or $KEY sigil is stripped on input, resolved at runtime from the service env first, then the process environment. force_shutdown on a service overrides the project-wide default. nil inherits it, true reclaims this service's ports before start, false never reclaims. The reclaim only acts when the service also declares ports, and it is best-effort.