grat

v1.3.2 · macOS & Linux

Your dev services, under control.

grat starts the long-running commands a project needs, waits until each one is genuinely ready, keeps their ports out of each other's way, and can put a single path on the public internet when a webhook has to reach you.

MIT licensed. One binary, no daemon, no config server.

grat start
Starting services  example.com
  [info] backend          checking managed state
  [...] backend          starting isolated process
  [...] backend          waiting for listener and health probe
  [ok] backend          ready on http://127.0.0.1:4001/
  [info] frontend         checking managed state
  [...] frontend         starting isolated process
  [ok] frontend         ready on http://127.0.0.1:3000/
  [ok] worker           ready

Status  example.com

SERVICE   STATE    PORT  PID    ENDPOINT                PUBLIC
frontend  running  3000  16445  http://127.0.0.1:3000/
backend   running  4001  16435  http://127.0.0.1:4001/
worker    running  -     16462
01. Install

One command

$ brew install phranck/grat/grat

Release binaries are published for macOS and Linux on Intel and ARM, verified against their checksums and GitHub's signed attestation.

  1. grat initWrites a declarative grat.config from the scripts your project already has.
  2. grat startStarts every service and waits until each one answers.
  3. grat statusShows what runs, on which port, under which PID, and what is public.
02. Services

Ready means ready, not started

A process that has been launched is not a service that answers. grat waits for a listener owned by the command it started, then for the health path to return, and only then calls it ready.

Start

Each command runs in its own process session, with the port it was given in PORT and a small, deliberate environment.

Stop

Signals reach the process group grat created, and only after the live PID, start identity and group all match what it recorded.

Logs

Output goes straight to .grat/log/, so a service keeps its log after the command that started it has exited.

03. Ports

Every role owns a lane

Ports stop being a thing you remember. A service's role decides the range it may live in, and grat allocates inside it, across every project it knows about.

frontend
3000-3099
developer
3100-3199
backend
4000-4099
dashboard
4500-4599
other
5000-5099
30005099
04. Public access

A webhook can reach your laptop

A payment provider confirms from server to server, to an address it reaches from the internet. grat makes one of your services reachable there, at a name that stays the same, and sets Tailscale up on the way if it is missing.

$ grat expose backend
$ grat expose --path /api/webhooks/creem backend

Running the command is the decision, so nothing has to be prepared first. Where only a callback has business with the internet, name the path and everything else stays inside.

grat expose backend
Exposing service  example.com
  [info] Tailscale        is not installed on this machine
  [info] Command          brew install tailscale
  [...] Tailscale        installing
  [ok] Tailscale        installed
  [info] Tailnet          this machine is signed in to no tailnet
  [...] Sign-in          opening the page in your browser
  [ok] Tailnet          this machine is connected
  [...] backend          publishing /api/webhooks/creem
  [ok] backend          reachable at https://mini.tail1234.ts.net/api/webhooks/creem