add-background-job
SkillFiles & storageAdd a new periodic background job binary (like delete_expired_tokens, delete_unowned_media, sync_sources) to Rellm's backend. Use when asked to create a new scheduled/cron-style maintenance or sync job for the Rust backend, since there's no central registry -- it must be wired by hand into ~7 files.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the add-background-job skill
What this skill tells your AI
The instructions your AI receives, as published by jonlatane/jonline in .claude/skills/add-background-job/SKILL.md and read by ahel’s review.
Rellm's background jobs are small standalone binaries under backend/src/bin/*.rs, each doing one pass of work (no internal loop/sleep) and exiting. Looping/scheduling is entirely external and, everywhere the job runs (local/Homebrew/Linux tarball, and cluster deploys since 2026-09-04), goes through the same backend/background_jobs.sh, which re-invokes the binary on an interval -- cluster deploys run it in the single rellm-jobs Deployment (deploys/k8s/server_internal.yaml & co.) rather than a per-job K8s CronJob. There's no registry file to grep for "the list of jobs" -- every one of the touch points below has its own hand-maintained copy of the job list, so adding a job means editing all of them the same way delete_expired_tokens/delete_unowned_media/sync_sources already are.
1. The binary: backend/src/bin/<job_name>.rs
- Put the actual logic in
backend/src/logic/(e.g.logic/event_sync.rs) if it's non-trivial or needs to be unit-testable/reused by an RPC handler; keep thebin/file itself thin (connect, query what's due, call logic, log, exit). - Boilerplate (copy
delete_expired_tokens.rsfor a sync job, ordelete_unowned_media.rs/generate_preview_images.rsfor an async one needing#[tokio::main], e.g. MinIO/HTTP):extern crate diesel; extern crate rellm; use rellm::{db_connection, init_bin_logging, init_crypto}; pub fn main() { init_crypto(); init_bin_logging(); log::info!("..."); let pool = db_connection::establish_pool(); // NOT establish_connection() -- let mut conn = pool.get().expect("..."); // that returns a bare PgConnection, // but shared `logic/` fns expect // PgPooledConnection (pool.get()). // ... do the work, log per-item errors and continue rather than panicking on one bad row ... } - Sanity check it actually compiles as its own binary target (easy to miss a type mismatch that the lib build alone won't catch):
cd backend && cargo build --bin <job_name>.
2. deploys/docker/server/Dockerfile
Add one COPY line under the # Background job binaries comment, following the __server_release naming CI renames binaries to:
COPY backend/target/release/<job_name>__server_release /opt/<job_name>
3. .github/workflows/server_ci_cd.yml -- three separate lists
push_rellm_imagejob, step "Rename Rust binaries for Dockerfiles": addmv backend/target/release/<job_name> backend/target/release/<job_name>__server_release &&(this is what step 2's Dockerfile COPY consumes -- skip thepush_preview_generatorjob's identical-looking rename step unless the job is actually copied intodeploys/docker/preview_generator/Dockerfiletoo).create_homebrew_releasejob: add<job_name>to thefor bin in rellm disable_cdn_grpc ...; doline.create_linux_releasejob: add<job_name>to its own (separate)for bin in rellm disable_cdn_grpc ...; doline.
4. backend/background_jobs.sh
Append one line to the JOBS array: "<job_name> <startup_delay_seconds> <interval_seconds>". This file is copied verbatim into both the Homebrew and Linux tarball packages by the CI job in step 3 -- don't hand-edit a shipped copy.
5. docs/rellm_linux.sh and docs/rellm_homebrew.sh
Both are standalone launcher scripts (one becomes the Linux tarball's bin/rellm, the other gets spliced into the Homebrew formula) with the same shape -- edit both, identically, in three places each:
- The
Background jobs:section of therellm_helpheredoc: add a one-line (or wrapped) description. - A new shell function using the shared exec helper:
<job_name>() { _rellm_exec_bin <job_name> "$@" }(add it neardelete_expired_tokens/delete_unowned_media, under the# Background jobscomment). - The
RELLM_COMMANDSarray (near the top of the file, aboverellm_help): add<job_name>to it -- it's the single source of truth for both dispatch (bottom of file) andrellm --list-commands/tab-completion, so this one edit covers both (it'll otherwise hit theUnknown commandbranch and won't tab-complete).
K8s: nothing to do
Cluster deploys (deploys/k8s/server_external.yaml, server_internal.yaml, server_internal_insecure.yaml) don't define jobs individually -- the rellm-jobs Deployment in each just runs backend/background_jobs.sh (step 4), which picks up any job appended to its JOBS array automatically. If the job needs env vars beyond DATABASE_URL (e.g. MINIO_*), check the rellm-jobs container's env: block already has them -- it currently carries the union of everything any job needs, so a new job needing only existing vars requires no edit there either.
Checklist
-
backend/src/bin/<job_name>.rs(logic inbackend/src/logic/if non-trivial) --cargo build --bin <job_name>passes -
deploys/docker/server/DockerfileCOPY line -
server_ci_cd.yml: rename step (push_rellm_image), Homebrewfor bin, Linuxfor bin -
backend/background_jobs.shJOBS entry -
docs/rellm_linux.sh: help text, function,RELLM_COMMANDSarray -
docs/rellm_homebrew.sh: help text, function,RELLM_COMMANDSarray - If the job needs new env vars: add them to the
rellm-jobsDeployment'senv:in all threedeploys/k8s/server_*.yaml(identical block, all three)
Signals
- GitHub stars
- 65
- Forks
- 5
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
add-background-job- Source
- github.com/jonlatane/jonline