Markdown · llms.txt

Deploy and cron

These scripts live in the repo root. They are a reference loop for a machine that already has a checkout, not a hosted service, and not the path for a new install (that is Install). Personal files (tweets.db, persona/PERSONA.md, .env, .tokens.json) stay on that machine. deploy.sh recompiles ./tf with the same flags as bun run build.

Run fetch on one host only. The X refresh token rotates on use.

What each script does

ScriptDoes
update.shtf refresh: incremental fetch and a flush rebuild. No LLM, no Tavily.
cron_run.shtf cron: incremental fetch, enrich, Notion sync when a key is set, flush, Slack ping if anything is pending. Prefers ./tf, otherwise bun run src/index.ts cron. Logs to logs/cron.log.
deploy.shgit pull --ff-only, bun install --frozen-lockfile, recompile ./tf. Does not touch gitignored state. Log: logs/deploy.log.
backup.shCopies tweets.db and persona/PERSONA.md into backups/, keeps 7 daily snapshots, pushes nothing. Log: logs/backup.log.

tf cron calls enrich, and enrich requires TAVILY_API_KEY. Without that key, cron fails after the fetch. Schedule update.sh (or tf refresh) instead until Tavily is configured. tf update replaces a release binary; it does not refresh tweets.db.

tf cron does not call tf generate. Generation stays something you run, or a separate agent loop, because it spends LLM time and should be read before anything is posted.

Cron

Paths below are the checkout. Use a user crontab on the same account that owns .tokens.json.

bash
# hourly refresh without an LLM
0 * * * * /path/to/tweet-factory/update.sh

# or, when TAVILY_API_KEY is set: fetch + enrich + flush + slack ping
# 0 * * * * /path/to/tweet-factory/cron_run.sh

# nightly local snapshots
15 3 * * * /path/to/tweet-factory/backup.sh

cron_run.sh and deploy.sh expect bun on PATH or at $HOME/.bun/bin.

A systemd timer can call the same scripts. The repo does not ship a unit file.

Updating the code

bash
./deploy.sh

Safe to run at the start of a loop. It fast-forwards origin/main only. If you have local commits, the pull fails and the script keeps the current checkout (it logs a warning).

Backups

backups/ is gitignored. Snapshots are named tweets-YYYY-MM-DD.db and PERSONA-YYYY-MM-DD.md. Keep that directory off any public remote. The script keeps the newest 7 of each.

Verify. ./tf refresh exits 0 on the server. logs/cron.log or the tf refresh output shows Fetch mode: incremental. ./backup.sh then ls backups shows today’s snapshot when tweets.db exists. git status does not list .env, .tokens.json, or tweets.db.