Skip to content

Hooks ​

Hooks are Lua functions in your config that run inside the daemon when something happens to an app.

HookCalledArguments
on_changefor each changed file, before restartingfile, app
on_startafter the process startsapp
on_exitwhen the process exits on its ownapp, code

The app argument is a table:

FieldValue
app.nameApp name
app.projectProject name
app.cwdAbsolute working directory
app.pidProcess ID (in on_start and on_exit)

on_change ​

Called once per changed file, after the debounce period and before the restart. Return false to skip the restart. Any other value, including no return value, lets it happen. If any file in the batch allows a restart, the app restarts.

lua
on_change = function(file, app)
  -- tests and docs don't affect the running server
  if file:match("_test%.go$") or file:match("%.md$") then
    return false
  end
  print(app.name .. ": rebuilding because " .. file .. " changed")
end,

file is relative to the app's cwd, for example internal/orders/handler.go.

on_start ​

Called after the process has started:

lua
on_start = function(app)
  print("started with pid " .. app.pid)
end,

on_exit ​

Called when the process exits by itself. It isn't called when watchd stops it. code is the exit code:

lua
on_exit = function(app, code)
  if code ~= 0 then
    print(app.name .. " crashed with exit code " .. code)
  end
end,

Output ​

print() in a hook writes to the app's log. It shows up in watchd logs and the dashboard, marked with »:

console
api | » api: rebuilding because handler.go changed

Limits ​

Hooks run inside the long-lived daemon, so they're restricted to keep it safe:

  • Time limit: each call can run for at most 2 seconds. A hook that runs longer (an endless loop, for example) is stopped, and the error is logged.
  • Errors are contained: a hook that raises an error is reported in the app's log, and everything carries on. A failing on_change doesn't block the restart.
  • Sandbox: hooks can't run shell commands, write files or exit the process. See Lua in configs.

Hooks share the config's Lua state, so they can use variables and functions defined at the top of the file:

lua
local restarts = 0

return {
  apps = {
    {
      name = "api",
      cmd = "go run .",
      watch = { "*.go" },
      on_change = function(file)
        restarts = restarts + 1
        print("restart #" .. restarts .. " caused by " .. file)
      end,
    },
  },
}

Released under the MIT License.