Rerun turns repeatable activities into checklists. Build a list for each thing you do more than once — kayaking, road trips, campouts, yard work — then keep it exactly the way you want it.
Going kayaking? Open the kayaking list, run through it top to bottom, and go kayaking. Reset the list and it's ready for next time.
Local and self-hosted: everything lives on your machine in a SQLite file. No cloud account, no sync, no subscription.
A few things worth checking twice (or a hundred times).
| Checklist | Why? | |
|---|---|---|
| 🚣 | Kayaking | Paddle? Check. Kayak? Hopefully. |
| 🏕️ | Camping | Because forgetting tent stakes once is enough. |
| 🚙 | Road Trips | One checklist, a hundred adventures. |
| 🏠 | Home Projects | For those jobs you'll definitely do again. |
| 🧳 | Travel Packing | Your passport would appreciate being remembered. |
| 🔧 | Maintenance | Oil changes, seasonal chores, and everything in between. |
| Layer | Tech |
|---|---|
| Backend | Node.js, Express 4, TypeScript (ESM) |
| Frontend | React 18, Vite, TypeScript |
| Database | SQLite via better-sqlite3 (WAL mode) |
| Auth | PBKDF2 password hashing, server-side sessions in SQLite |
Compliments of Claude, ChatGPT/Codex, Qwen3.8-Flash-Next, and a touch.. and I do mean like a super, duper tiny touch, of my own development experience.
services:
rerun:
image: ghcr.io/nwish/rerun:latest
ports:
- "3001:3001"
volumes:
- rerun-data:/app/data
restart: unless-stopped
# environment:
# # Behind TLS (reverse proxy): session cookies get the Secure flag
# - HTTPS=1
# # Behind a reverse proxy: rate limits use the real client address, not the proxy's
# - TRUST_PROXY=1
# # Public origin used in invitation links
# - APP_URL=https://rerun.example.com
# # Invitation email (without SMTP_HOST, invite links are logged instead)
# - SMTP_HOST=smtp.example.com
# - SMTP_PORT=587
# - SMTP_USER=you@example.com
# - SMTP_PASS=your-smtp-password
# - SMTP_FROM=Rerun <rerun@example.com>
volumes:
rerun-data:Need Node.js ≥ 22.12 (24 recommended) and npm
npm install
npm run dev- App: http://127.0.0.1:5173
- API: http://127.0.0.1:3001 (the Vite dev server proxies
/api/*here)
Both servers run under one command (concurrently); api runs in watch mode.
First account: none is seeded. Open the app → "No account? Create one" → register. That account is yours and admin.
| Script | What it does |
|---|---|
npm run dev |
API (watch mode) + Vite dev server together |
npm run dev:api |
API only (http://127.0.0.1:3001) |
npm run dev:web |
Vite dev server only (http://127.0.0.1:5173) |
npm run build |
Build the frontend to dist/ (API runs TS directly) |
npm start |
Production: Express serves the built UI + API |
npm run typecheck |
Type-check the frontend without emitting |
npm run build
npm start # serves UI and API on http://127.0.0.1:3001| Var | Default | Notes |
|---|---|---|
PORT |
3001 |
API port |
HOST |
127.0.0.1 |
Bind address; set 0.0.0.0 to expose |
NODE_ENV |
— | production serves the built UI |
HTTPS |
— | 1 adds the Secure flag to the session cookie — set only when served over TLS (reverse proxy, etc.) |
SMTP_HOST |
— | SMTP server for invitation emails (e.g. smtp.fastmail.com). Unset: emails are logged to the server console instead of sent |
SMTP_PORT |
587 |
SMTP port |
SMTP_SECURE |
— | 1 for implicit TLS (port 465); default uses STARTTLS |
SMTP_USER |
— | SMTP auth user (optional; some relays need no auth) |
SMTP_PASS |
— | SMTP auth password |
SMTP_FROM |
Rerun <rerun@localhost> |
From address for emails |
APP_URL |
request origin | Base URL used in invitation links when the email is sent |
TRUST_PROXY |
— | Set when running behind a reverse proxy so rate limits see real client addresses: a hop count (1 for one proxy) or a name/CIDR list (loopback,172.16.0.0/12). Leave unset when clients connect directly — trusting the header with no proxy in front lets anyone forge their address |
The server reads a .env file from the repo root when present — create it from .env.example. Values in a real environment always take precedence over the file.
