Skip to content

tasteforge/taskify

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

taskify · the TasteForge chat-and-phone build loop

A forkable template that lets you fire build tasks at a project from a Claude chat or any phone, have a worker on a server do the work, and approve the results — without depending on a specific device.

Fork it once into a GitHub template repo; every future project is then one create-repo task away.


How it fits together

  Claude (any chat)            Vercel (front door)            Supabase
  fire by curl + bearer  ─────▶  /api/tasks  ──────────────▶  Postgres queue
                                 console (/status/remote)      + Google auth
  You (any phone)        ─────▶  Google sign-in ─────────────▶  (RLS allowlist)
                                                                     ▲
                                              outbound poll          │
                                 Hetzner box · worker.py ────────────┘
                                 (no inbound surface · holds secrets)

Why this shape:

  • The box has no open ports. runner/worker.py polls Supabase outbound for queued tasks and runs them. Nothing to expose, nothing to IP-block.
  • The front door is Vercel — a single /api/tasks route. Claude authenticates with a static agent bearer token; you authenticate with Google sign-in (Supabase Auth), locked to an email allowlist.
  • Secrets live in exactly two places: the box .env and Vercel env. Never in the browser, never in a chat, never in a doc.

This is the one deliberate deviation from docs/TF-AUTONOMY-PLAN.md: the API moved off the box (no more on-box FastAPI) because Supabase + Vercel do that job better and leave the box dark. See docs/GPRED-LEARNINGS.md for what carried over from the first Hetzner loop and what didn't.


Repo layout

taskify/
├─ README.md             ← this file
├─ LICENSE               ← MIT
├─ .gitignore            ← protects .env, node_modules, venv, logs/, repos/, .next
├─ .env.example          ← the secret contract (box + Vercel + console)
├─ runner/               ← the box worker (no inbound surface)
│  ├─ worker.py          ← poll Supabase → dispatch → write status back
│  ├─ handlers.sh        ← one handler per task type (build, claude-code, …)
│  ├─ bootstrap.sh       ← one-shot box setup: venv, deps, systemd service
│  ├─ schema.sql         ← Supabase tables, RLS, allowlist
│  └─ curl.sh            ← the fire / poll recipe Claude runs from a chat
├─ web/                  ← the Vercel front door + console (Next.js App Router)
│  ├─ app/api/tasks/route.ts      ← the single front door (agent bearer + Google)
│  ├─ app/status/remote/          ← the remote-control console (dark)
│  ├─ app/styles/tf-tokens.css    ← TasteForge design tokens, vendored verbatim
│  └─ public/setup.html           ← the hostable setup wizard
└─ docs/
   ├─ TF-AUTONOMY-PLAN.md   ← tiers, milestones, the gate matrix + design rubric
   ├─ TF-REMOTE-CONTROL.md  ← the paste-into-any-chat remote-control charter
   └─ GPRED-LEARNINGS.md    ← reusable patterns from the first Hetzner loop

Setup, step by step

You touch a terminal once (steps 2–3, from a laptop). Everything after is chat-and-phone. A hostable walkthrough lives at /setup.html once web/ is deployed.

1 · Supabase (the queue + auth)

  • Create a project. Open the SQL editor and run runner/schema.sql.
  • Add your email: insert into allowed_users(email) values ('you@tasteforge.ai');
  • Seed a project: insert into projects(id,name,repo) values ('app-skeleton','App skeleton','app-skeleton');
  • (Optional now) Authentication → Providers → enable Google, set the redirect to the Supabase callback shown on that screen.

2 · The box (the worker)

scp -r runner/ .env.example you@your-box:/opt/tf/   # worker, handlers, bootstrap
ssh you@your-box
cd /opt/tf && cp .env.example .env && nano .env      # fill in the box secrets
bash bootstrap.sh                                    # venv, deps, systemd service
journalctl -u tf-runner -f                           # watch it poll

The service restarts on crash and on reboot, and polls Supabase for queued tasks.

3 · Vercel (the front door + console)

  • Import web/ as a Vercel project (root directory web).
  • Set the Vercel env vars from .env.example (the front-door + console blocks). SUPABASE_SERVICE_KEY and AGENT_TOKEN are server-only — never NEXT_PUBLIC_.
  • Deploy. Your endpoint is https://<app>.vercel.app/api/tasks and the console is at https://<app>.vercel.app/status/remote.

4 · Fire from a chat

Paste docs/TF-REMOTE-CONTROL.md into a new Claude chat, then give it the endpoint URL and the AGENT_TOKEN for that session. Claude runs curl.sh-style calls. The console’s live mode talks to the same /api/tasks over your signed-in Google session.


Who authenticates how

Caller Auth Path
Claude (chat) AGENT_TOKEN bearer curl → /api/tasks
You (any phone) Google sign-in (Supabase) console → /api/tasks
The worker Postgres service connection outbound poll, no inbound

The gate matrix (enforced — never weaken it)

Autonomous: build · typecheck · preview · screenshot · claude-code on a feature branch · design-eval · ingest to a scratch branch · backlog-pull · create-repo.

Ask first (held for your approval): merge to main, production data, anything a client sees, schema migrations, major dependency bumps, deletions.

Never (hard stop): push to main without review; read/write/echo a secret; expose an engine codename on an external surface; irreversible deletion; act outside the repo + allowed infra; disable a gate.

Frontend-producing tasks resolve to needs-review, never succeeded — a human approves the surface. Every frontend task carries a design-eval step and is scored against the 7-axis rubric in docs/TF-AUTONOMY-PLAN.md; nothing below the bar surfaces for review. runner/worker.py enforces the review gate (REVIEW_TYPES), and the console mirrors it.


Design

Custom interfaces follow the tasteforge design kit as the single source of truth: Inter, the locked tokens, JetBrains Mono on numerics, European sentence case, no emoji, light theme by default. The kit’s @tasteforge/ui package is an unpublished workspace gated behind Untitled UI PRO, so — per the kit’s own recommendation — this template vendors its token + theme CSS verbatim at web/app/styles/ (tf-tokens.css, tf-themes.css). Re-point those imports at @tasteforge/ui/tokens.css once the package is published.

The one sanctioned dark surface is the technical remote-control console at /status/remote; everything else is light. (JetBrains Mono is added in tf-mono.css because the kit ships no mono token yet but the system mandates mono numerics.)


Run the web app locally

cd web
npm ci
npm run dev      # http://localhost:3000  → /status/remote runs in demo mode
npm run build    # production build (green with no secrets present)

The console boots in demo mode (a simulated loop in the browser); switch to live from the connection panel to talk to a deployed /api/tasks.


Fork for a new project

The master control room is just the console reading every project row in the one shared Supabase. To spin up a new project on the same loop:

  1. Make this repo a GitHub template (Settings → Template repository).
  2. Set GITHUB_TEMPLATE in the box .env to this repo’s name, and GITHUB_ORG to your org.
  3. Fire a create-repo task from a chat or the console:
    curl -sS -X POST "$API" -H "$AUTH" -H 'content-type: application/json' \
      -d '{"type":"create-repo","payload":{"name":"my-next-thing"}}'
    The worker calls the GitHub generate-from-template API (handlers.shcreate-repo) to create a new private repo from the template under your org.
  4. Register it so the console picks it up:
    insert into projects(id,name,repo)
      values ('my-next-thing','My next thing','my-next-thing');
  5. New project, same loop, same console — no new infra. The box clones the repo on first task and works only on feature branches; you keep the merge and design gates.

Security: the GitHub PAT is fine-grained, scoped to the org’s repos, contents + (for create-repo) administration, and lives only in the box .env. SUPABASE_SERVICE_KEY bypasses RLS and is server-side only — the browser uses the anon key, and RLS + the allowlist protect the data. Rotate AGENT_TOKEN whenever you like.

About

TasteForge chat-and-phone build loop: worker + Vercel front door + remote-control console. Forkable template.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors