Local-first background job scheduler with a web dashboard and AI-assisted automation.
Backbeat runs scheduled shell scripts and AI instructions on your own machine — on a cron schedule or once at a set time — and gives you a web UI to create jobs, watch runs live, and browse run history. Everything is stored in a single local SQLite database; nothing leaves your machine.
The Backbeat web dashboard — managing jobs, inspecting a run, and browsing the schedule.
| Jobs | Job editor |
|---|---|
![]() |
![]() |
| Run detail | Calendar |
![]() |
![]() |
- Two job types — plain shell scripts (
/bin/sh) or natural-language AI instructions executed through the Claude Code or Codex CLI. - Flexible scheduling — recurring cron expressions or one-time runs at a specific time. One-time jobs auto-disable once they fire.
- Live run monitoring — watch running and queued runs, stop a run (graceful
SIGTERM, thenSIGKILL), or drop a queued one. - Run history — paginated, status-filterable history with captured stdout/stderr logs and syntax highlighting.
- AI-assisted authoring — describe a job in plain language and let Claude draft a schedule and job body, or refine an existing one inline.
- Per-job AI overrides — pick the model, reasoning effort, and permission mode per job, or fall back to global defaults.
- Calendar view — see upcoming scheduled runs at a glance.
- Local-first — one SQLite file, XDG-compliant paths, no external services or accounts.
- Bun 1.x — the recommended runtime (Node.js also works, via a
better-sqlite3fallback). - A POSIX shell at
/bin/sh— used to run script jobs. - For AI-instruction jobs, the matching CLI on your
PATH:- Claude Code — the
claudeCLI. - Codex — the
codexCLI (optional alternative).
- Claude Code — the
git clone https://github.com/ilyasturki/backbeat.git
cd backbeat
bun install
bun run devThen open http://127.0.0.1:3786. On first launch Backbeat seeds a few disabled example jobs so you can see how scripts, AI instructions, cron, and one-time schedules are configured — enable one to try it.
- Job — a reusable task: a title, a body (shell script or AI instruction), a schedule, a working directory, environment variables, and a timeout.
- Schedule — either a cron expression (recurring) or a once timestamp (a single run, after which the job disables itself).
- Run — one execution of a job. A run is
queued, thenrunning, and finishes assuccess,failure,timeout, ordropped. Runs are started by the scheduler or manually from the UI.
The scheduler checks every second for due jobs, queues their runs, and executes them. Output is streamed to a per-run log file, and only the most recent runs per job are retained (configurable).
| Variable | Default | Description |
|---|---|---|
PORT |
3786 |
HTTP port. |
HOST |
127.0.0.1 |
Address to bind to. |
BACKBEAT_DATA_DIR |
$XDG_DATA_HOME/backbeat (~/.local/share/backbeat) |
SQLite database and run logs. |
BACKBEAT_CONFIG_DIR |
$XDG_CONFIG_HOME/backbeat (~/.config/backbeat) |
preferences.json. |
BACKBEAT_DISABLE_SCHEDULER |
(unset) | Set to 1 to start the UI/API without the background scheduler. |
- Database —
<data-dir>/db.sqlite - Run logs —
<data-dir>/logs/<job-id>/<run-id>.log - Preferences —
<config-dir>/preferences.json
All are created automatically on first run.
Set these from the Preferences page (or by editing preferences.json directly):
| Key | Default | Description |
|---|---|---|
defaultTimeoutMs |
1800000 (30 min) |
Default per-job timeout. |
aiMode |
claude |
Default AI backend (claude or codex). |
claudeBinary / codexBinary |
claude / codex |
CLI executable name or path. |
claudeModel / codexModel |
(empty) | Model override; empty uses the CLI default. |
claudeEffort / codexEffort |
(empty) | Reasoning effort (low … max). |
claudePermissionMode |
bypassPermissions |
Claude permission mode. |
codexSandbox |
danger-full-access |
Codex sandbox mode. |
logRetentionPerJob |
50 |
Number of run logs kept per job. |
Heads-up: AI-instruction jobs run the Claude/Codex CLI with permission checks bypassed by default, so they can read and modify files freely. Review job bodies, set a sensible working directory, and tighten the permission/sandbox settings if that is a concern. Backbeat binds to
127.0.0.1— keep it local unless you put authentication in front of it.
bun run build # outputs .output/server/index.mjs
bun run start # serves on http://127.0.0.1:3786bun run start is equivalent to bun .output/server/index.mjs; set PORT / HOST to
change where it listens.
A sample unit is provided in backbeat.service. Edit its
ExecStart line to point at your built .output/server/index.mjs, then:
cp backbeat.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now backbeatThe repo ships a flake with a dev shell and service modules:
nix develop— dev shell with Bun, Node, and SQLite.- NixOS — import
nixosModules.backbeatand enableservices.backbeat. - home-manager — import
homeManagerModules.backbeatfor a per-user service.
Both modules run a server you have already built with bun run build; point their
outputDir option at the resulting .output/ directory. Example (NixOS):
{
imports = [ inputs.backbeat.nixosModules.backbeat ];
services.backbeat = {
enable = true;
outputDir = "/var/lib/backbeat/checkout/.output";
port = 3786;
};
}See flake.nix for the full set of module options.
Released under the MIT License.



