Track subscriptions, renewals, and recurring costs.
Home opens with your subscriptions. Expand Collection tools for totals, search, filters, sorting, and bulk actions; press / to open search directly. Calendar, Insights, and Settings stay available when you need more detail.
Choose several service presets or paste website links, then enter each plan's price and billing cycle in one review. Nothing is saved until you confirm the batch; prices start empty, and zero-cost plans are supported. Possible duplicates stay visible so separate plans are never silently merged.
Use Add subscription for a single plan, with a service preview and optional custom icon URL. You can move a new draft into quick setup without losing its details.
Currency-aware prices, active/paused/cancelled tracking, anchored renewals, trials, and calendar. Search, table view, bulk actions, budgets, and savings scenarios help manage the Collection. Totals are projections; recorded price changes are not payment records.
Features, shortcuts, and limits
Press ⌘/Ctrl K to search subscriptions, starter templates, and commands. Hold ⌘ or Ctrl to reveal shortcuts; use arrows or J/K between subscriptions and Enter to manage one. ? shows the full shortcut list. The speaker button controls TIKS interaction sounds on this device.
Settings → Browser reminders enables renewal and trial notifications on this device. Reminders need HTTPS or localhost and run best effort while Subs is open and unlocked, not after the browser is closed. Sound and reminder settings stay local and are not included in backups.
docker compose up --build -d
docker compose logs subsOpen http://localhost:7574. Copy the setup token from the logs and choose a six-digit PIN. Data stays in the mounted ./data directory; back it up before updating. Use HTTPS and set SUBS_ORIGIN when exposing Subs through a reverse proxy.
Requires Bun 1.4.3+.
bun install --frozen-lockfile --linker hoisted
bun run devOpen http://localhost:5173. bun run lint, bun run typecheck, and bun run test run the checks. bun run build builds both targets; bun run start starts the private server.
The separate DEMO_MODE build uses sample data stored only in your browser, illustrative exchange rates, and no backend or PIN. Reset restores the samples. Skipping PIN is built into this browser-only target, not private-server DISABLE_AUTH.
bun run build:demo
bun run preview:demoPreview the built static site with Wrangler Pages at http://127.0.0.1:4174. Use bun run dev:demo for Vite development at http://127.0.0.1:5174.
Publishing the demo is a manual, credentialed step. The supported flow is the Cloudflare MCP Pages deployment against the subs-demo project; bun run deploy:demo remains as a local Wrangler fallback that builds the demo and directly uploads dist/demo to Cloudflare Pages with --branch main. Root wrangler.jsonc sets pages_build_output_dir; there are no Pages Functions, backend, or bindings. Ordinary local and Docker builds never publish.
The Cloudflare Pages demo is live at subs.ajnart.dev, its only canonical hostname, with verified HTTPS and no PIN or backend. It is also available at subs-demo.pages.dev. Browser data is separate for each hostname; export/import a backup to move demo edits.
The Checks workflow validates main and every push or pull request on application and Docker checks. It does not deploy: publishing the demo is a manual, credentialed Cloudflare MCP operation, so no Actions secret or automatic upload is configured. Local Wrangler OAuth and MCP authentication are the supported publishing credentials.
| Variable | Default | Use |
|---|---|---|
DATA_DIR |
./data, /data in Docker |
Database directory |
SQLITE_PATH |
<DATA_DIR>/subs.sqlite |
Override database file |
SUBS_SETUP_TOKEN |
Generated in server logs | First-use operator token |
SUBS_ORIGIN |
Request origin | Public origin behind a proxy |
SUBS_COOKIE_SECURE |
Enabled on HTTPS | Explicit Secure-cookie override |
DISABLE_AUTH |
false |
Exactly true disables PIN protection |
Export from Subs 2 or preserve data/config.json, then restore through Settings → Import. Legacy arrays and browser/server storage envelopes are supported. Review the preview before replacing anything; keep the original backup. USE_LOCAL_STORAGE and the old storage API are retired.
JSON backups contain subscriptions and preferences, including custom icon URLs, not PINs, sessions, or recorded price history. Collections are bounded to a restorable 2 MiB backup. Known service icons are bundled; custom public HTTP(S) icon URLs and other public service favicons load directly in your browser without a referrer, never through a server proxy. Unsafe schemes and recognizable private/local addresses are blocked; DNS and redirects remain browser-controlled. Hovering or focusing a public service link requests a preview from Microlink; previews do not load automatically.
Stop Subs and back up ./data, then:
docker compose run --rm --no-deps subs bun scripts/reset-pin.ts --confirm
docker compose up -d subs
docker compose logs subsComplete setup again. Subscriptions and preferences are preserved.




