govisor is a lightweight Linux-first supervisor for host processes. It is built for the case where you want one YAML file to define a small group of long-running programs and you want simple lifecycle control without introducing containers or a heavier orchestration layer.
- Local dev stacks with 2-6 long-running processes. Example: API, worker, and a frontend dev server.
- Small side projects deployed on one VM. Example: a Go API plus a queue worker plus a cron-like process.
- Background automation on a personal server. Example: poller, sync job, webhook listener, log shipper.
- Internal tools where one YAML file should define what should be running.
Install by module path:
go install github.com/deltron-fr/govisor/cmd/govisor@latestThis places the govisor binary in your GOBIN or $(go env GOPATH)/bin.
For a specific release, pin the version:
go install github.com/deltron-fr/govisor/cmd/govisor@v1.0.0To remove it, delete govisor from GOBIN or $(go env GOPATH)/bin.
Start the supervisor server:
govisor startStop it with Ctrl-C or by terminating the govisor start process.
In another terminal, create a config file:
name: dev-stack
processes:
- name: api
command: go
args: ["run", "./cmd/api"]
environment:
APP_ENV: development
PORT: "8080"
workdir: ./services/api
restart: on-failure
- name: worker
command: go
args: ["run", "./cmd/worker"]
environment:
QUEUE_NAME: background-jobs
workdir: ./services/worker
restart: always
- name: frontend
command: npm
args: ["run", "dev"]
environment:
NODE_ENV: development
workdir: ./frontend
restart: unless-stoppedApply it:
govisor apply -f ./govisor.yamlCheck status:
govisor statusShow recent logs for a process:
govisor logs apiStop all supervised processes:
govisor stopgovisor start
govisor apply -f <config.yaml>
govisor status
govisor logs <process-name>
govisor stop
$ govisor status
NAME STATUS COMMAND CREATED UPDATED
api RUNNING go 14:03:11 14:03:12
worker RUNNING go 14:03:11 14:03:13
frontend RUNNING npm 14:03:11 14:03:11
Config files are YAML with this top-level shape:
name: my-stack
processes:
- name: api
description: optional description
command: go
args: ["run", "./cmd/api"]
environment:
APP_ENV: development
PORT: "8080"
workdir: ./services/api
restart: on-failure
shell: false| Field | Required | Description |
|---|---|---|
name |
yes | Name of the config group. |
processes |
yes | List of processes to supervise. |
processes[].name |
yes | Unique process name. Names must be unique across all configs applied to the running supervisor. Duplicate names are rejected. |
processes[].description |
no | Human-readable description. |
processes[].command |
yes | Executable or command string to run. |
processes[].args |
no | Arguments passed to the command when shell is false. |
processes[].environment |
no | Environment variables added to the inherited environment. Configured values override inherited variables with the same name. |
processes[].workdir |
no | Working directory for the process. Relative paths are resolved from the config file directory. |
processes[].restart |
no | Restart policy: always, never, on-failure, unless-stopped. If omitted, the default is always. |
processes[].shell |
no | If true, runs the command through sh -c. |
name: side-project
processes:
- name: app
command: ./bin/app
environment:
APP_ENV: production
HTTP_PORT: "8080"
workdir: .
restart: always
- name: poller
command: ./bin/poller
environment:
POLL_INTERVAL: 30s
workdir: .
restart: on-failure
- name: webhook-listener
command: ./bin/webhook-listener
workdir: .
restart: unless-stoppedname: local-dev
processes:
- name: frontend
command: npm run dev
environment:
NODE_ENV: development
API_BASE_URL: http://localhost:8080
workdir: ./frontend
shell: true
restart: unless-stopped
- name: tailwind
command: npm run watch:css
workdir: ./frontend
shell: true
restart: always
- name: api
command: go run ./cmd/api --listen "$LISTEN_ADDRESS"
environment:
APP_ENV: development
LISTEN_ADDRESS: 127.0.0.1:8080
workdir: ./backend
shell: true
restart: on-failuregovisor uses per-user runtime and state directories.
Socket: $XDG_RUNTIME_DIR/govisor/govisor.sock
Logs: $XDG_STATE_HOME/govisor/logs/
When XDG_RUNTIME_DIR is unset or empty, the socket falls back to:
~/.local/state/govisor/run/govisor.sock
When XDG_STATE_HOME is unset or empty, logs fall back to:
~/.local/state/govisor/logs/
Each process writes to <logs-directory>/<process-name>.log. Govisor creates
the required runtime and log directories automatically. The server and CLI must
resolve the same socket path, so they should run with the same
XDG_RUNTIME_DIR value.
govisor writes stdout and stderr for each process into its own log file.
Retrieve the most recent log output for a supervised process with:
govisor logs <process-name>The command returns up to the last 4 KiB of the process's current log file.
Current rotation behavior is intentionally simple:
- rotation is size-based
- the size threshold is 10 MiB per log file
- the rotation check runs every 45 seconds
- the active file becomes
<name>.1.log - a fresh
<name>.logfile is opened
More robust rotation is planned later, including archiving older logs, deleting old logs by age, and supporting safer restart behavior around rotation.
- A configuration name can only be applied once while the server is running.
- Process names must be unique across all applied configurations. If a config repeats a process name, or reuses the name of an already managed process,
govisor applyrejects the config before starting any of its processes. - This project is best treated as Linux-first today.
depends_onprocess dependency graphs- more complete log rotation and retention
- cgroup-based memory controls on Linux
For local development, run:
make helpRun the test suite:
go test ./...
go test -race ./...govisor is released under the MIT License. See LICENSE.
For small changes:
- Fork the repo and create a branch.
- Make the change.
- Run
go test ./.... - Open a pull request with the reasoning behind the change.
For larger changes, opening an issue first is usually the better path so the direction is clear before implementation.