Skip to content

Repository files navigation

Superfocus (self-hosted)

An OS-agnostic, self-hosted execution system: 90-day Seasons, a hard 168-hour budget, calendar-bound time blocks, passive activity auditing, and coaching that runs on a local model.

Built from the analysis in Superfocus Architecture and Replication.pdf, with the macOS-specific parts of that design replaced by portable equivalents. See docs/ARCHITECTURE.md for the reasoning.

Runs the same on Windows, macOS and Linux. Nothing in the core knows which one it is on.

Layout

packages/core       domain model, Plan Strength scoring, prompts, PORTS  (no I/O, no OS)
packages/adapters   the only code allowed to touch a machine or a network
packages/db         Drizzle schema + TimescaleDB migration
apps/web            Next.js UI and API
apps/desktop        Tauri v2 shell (tray, hotkeys, notifications)
infra               Docker Compose, Dockerfile, Caddyfile

Quick start

No database server, no Docker, no install:

npm install
npm run db:migrate          # creates an embedded Postgres under ./data
npm run db:seed             # optional demo season
npm run dev                 # http://localhost:3210
npm test                    # 88 tests, no services required
npm run build:check         # production build that will not disturb `npm run dev`

DATABASE_URL defaults to pglite://./data/superfocus-db — PGlite, real Postgres compiled to WASM, running in-process. The schema, the SQL and the query layer are identical to a server; point DATABASE_URL at a postgresql:// URL whenever you want one.

Optional Docker stack (Postgres + Timescale, Redis, the app, and Ollama behind --profile gpu):

cp .env.example .env        # set DB_PASSWORD
npm run stack:up

What works with nothing configured

Everything except enforcement and coaching. SoftBlocker and ManualTracker are always available on every platform, so a session always starts — the UI just tells you plainly that nothing is protecting it.

All of it goes in the .env at the repository root, and the app must be restarted to pick it up.

Add capability incrementally:

Want Set Notes
Block distracting domains PIHOLE_BASE_URL + PIHOLE_API_TOKEN Recommended. No admin rights, covers phones too
Block on this machine only ENABLE_HOSTS_BLOCKER=true Needs Administrator / root
Passive activity audit SCREENPIPE_URL Install Screenpipe on the host, not in Docker
Slack DND + status SLACK_USER_TOKEN Scopes: users.profile:write, dnd:write
AI coaching INFERENCE_BASE_URL Any OpenAI-compatible endpoint. Without it, coaching still runs rule-based
Google Calendar GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET Then click Connect in Settings; the refresh token is stored for you
Any other calendar CALDAV_URL + CALDAV_USERNAME + CALDAV_PASSWORD Nextcloud, Radicale, Fastmail, iCloud, Synology

GET /api/adapters reports what is actually usable right now.

Privacy

  • Screenshots are never stored. Screenpipe extracts text on the host; only text reaches the database, capped at 2000 characters per sample.
  • reality_logs has a 90-day retention policy when the Timescale migration is applied.
  • INFERENCE_ALLOW_REMOTE=false (the default) refuses any inference endpoint that is not loopback or RFC1918, so telemetry cannot leave the machine by accident. Every coaching audit records was_remote permanently.

Status

The whole loop runs — plan the day, protect it, do the work, learn from it:

Screen What it does
Compass / Plan Strength and its four components, today's schedule, live shield status
Plan /plan The day drawn to scale; add and delete blocks, edit Major Moves and confidence
Focus /focus Engages the shield for a block, counts up, always releases on exit
Reflect /reflect Plan Strength against adherence, observed divergence, coaching
Seasons /seasons Create and edit seasons, goals, why-statements, anti-goals
Settings /settings Timezone, adapter status, Google/CalDAV calendar sync

Focus sessions record what the shield actually managed on this machine, so a retro can tell "I got distracted" apart from "nothing was blocking me".

Coaching runs at 07:00 and 21:00 in your timezone, plus a weekly review. With no model configured it still runs, from a deterministic rule-based composer, and says so rather than pretending a model wrote it. Every audit records whether the request left your machine.

Access control

With no SUPERFOCUS_PASSWORD set the app is open — right on your own machine, wrong anywhere else, and the Settings screen says so rather than leaving it ambiguous. Set it (plus SUPERFOCUS_SESSION_SECRET) and every page sits behind a login, with a 30-day signed cookie verified in middleware.

This is single-user by design: one password, no account creation, no reset. getPrimaryUserId takes the oldest account. If you need real multi-user accounts, this is the piece to replace.

Note: PGlite is single-process. Stop npm run dev before running db:seed or any script against the same pglite:// directory, or the dev server will keep serving stale rows.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages