cron— time fires the run (a schedule).webhook— a remote service POSTs to fire the run.watch— a local file changes and fires the run. This is the shipped “hook.”
buttons serve, which hosts the trigger engine alongside the local REST API.
Watch a file
--watch selects the file-watch kind; --path is the single file to watch (required). When that file’s size or modification time changes, the button presses.
Pass args that the press should receive each time it fires:
--arg KEY=VALUE is repeatable.
How watching works
The engine polls the file withos.Stat every 500 ms and compares modification time and size. It deliberately does not use fsnotify — polling survives editor rename-on-save and needs no native dependency. The first poll records a baseline and does not fire; only a later change triggers the press. Each firing is recorded in run history like a normal press.
Watching is active only while buttons serve is running — the same process that serves the REST API also runs the cron/watch trigger engine in-process. Pass --no-triggers to serve the API without firing triggers.
Manage triggers
trigger list shows each trigger’s id; rm takes the button name and that id. There is no pause/resume — remove and re-add to change a trigger.
Not yet shipped
Only three trigger kinds exist today:cron, watch, and webhook. There is no buttons trigger hook ... --enable "<source>" command, no git-event hooks (pre-commit, post-push), and no button/drawer lifecycle events (button:<name>.completed, *.failed). The --watch trigger is the way to react to a local file change.
For the other shipped paths:
- Time-based:
buttons trigger add <button> --cron --schedule "0 */6 * * *". - Remote callback into a button:
buttons trigger add <button> --webhook --webhook-path /hooks/x [--token …]. - Remote callback into a drawer (n8n-style auth, Cloudflare tunnel):
buttons drawer <name> trigger webhook, served bybuttons webhook listen.