Pull mirror of github.com/chad-russell/sweatshop (source of truth is GitHub)
  • TypeScript 97.6%
  • JavaScript 1.3%
  • CSS 0.8%
  • Shell 0.3%
Find a file
Chad Russell 18eb123de6
All checks were successful
deploy / checks (push) Successful in 42s
deploy / deploy (push) Successful in 5m36s
Merge pull request #74 from chad-russell/glen/0090-phase4-catalog-install
feat(skills): public catalog discovery + install (0090 phase 4)
2026-10-30 23:39:04 -04:00
.agents/skills refactor!: 0010 phase 6 — delete eve 2026-10-01 19:34:43 -04:00
.forgejo/workflows ci: checkout moved ~/ss/sweatshop -> ~/sweatshop 2026-10-23 10:35:42 -04:00
.github pr-65 screenshot after-settings.png 2026-10-29 01:01:54 -04:00
app feat(chat): ?prompt= prefills the fresh composer (0090 §6) 2026-10-31 03:20:15 +00:00
components feat(chat): ?prompt= prefills the fresh composer (0090 §6) 2026-10-31 03:20:15 +00:00
db feat(settings): /settings becomes an index with four sub-routes (0090 phase 1) 2026-10-30 22:41:37 +00:00
design docs(themes): 0086 VSCode theme importer spec + vendored sources 2026-10-27 17:08:04 +00:00
docs docs(0090): public catalogs — discovery + install (Chad's caveat) 2026-10-30 21:55:12 +00:00
drizzle feat(skills)!: remove DB catalog, binding, and built-in runbooks — S3 catalog is the one system (0088 stage 2) 2026-10-29 04:40:02 +00:00
lib fix(skills): parse folded YAML descriptions in catalog listings (0090 §7) 2026-10-31 03:32:26 +00:00
public feat(brand): adopt Night shift factory logo 2026-10-21 13:37:26 -04:00
scripts fix(themes): importer curation pass — blends, chain flips, visibility gates 2026-10-27 18:16:13 +00:00
tests fix(skills): parse folded YAML descriptions in catalog listings (0090 §7) 2026-10-31 03:32:26 +00:00
vendor/bridge-locks/@ai-sdk fix(harness): vendor bridge pnpm lockfiles — upstream tarball regression (vercel/ai#23829) 2026-10-27 18:31:38 +00:00
workflows feat(skills)!: remove DB catalog, binding, and built-in runbooks — S3 catalog is the one system (0088 stage 2) 2026-10-29 04:40:02 +00:00
.env.example feat(settings): edit git credentials from /settings 2026-10-26 12:04:11 -04:00
.gitignore docs: AGENTS.md path B + vendor workflow reference docs 2026-09-30 13:11:01 -04:00
AGENTS.md feat(skills)!: remove DB catalog, binding, and built-in runbooks — S3 catalog is the one system (0088 stage 2) 2026-10-29 04:40:02 +00:00
biome.jsonc chore(deps): refresh packages and replace eslint with biome 2026-10-26 20:02:37 -04:00
CHANGELOG.md docs(changelog): public catalog discovery + install (0090 phase 4) 2026-10-31 03:34:06 +00:00
components.json feat(web): next.js + tailwind v4 + shadcn + three-theme token system 2026-09-29 16:37:36 -04:00
Containerfile.dev chore(deps): refresh packages and replace eslint with biome 2026-10-26 20:02:37 -04:00
Containerfile.sandbox Merge pull request #58 from chad-russell/feat/pr-screenshots 2026-10-27 14:25:59 -04:00
DESIGN.md feat(themes): import Catppuccin Mocha, Dracula, Tokyo Night, Rosé Pine Moon 2026-10-27 18:17:27 +00:00
dev fix(dev): docker-portable checks, bash-3.2 arrays, DEV_PUBLISH for local mode 2026-10-20 21:46:16 +00:00
drizzle.config.ts feat(db): sqlite scaffold — drizzle schema, migrations, data/ 2026-09-29 17:16:04 -04:00
instrumentation-node.ts fix(harness): vendor bridge pnpm lockfiles — upstream tarball regression (vercel/ai#23829) 2026-10-27 18:31:38 +00:00
instrumentation.ts fix(previews): node-only instrumentation module; resolve runtime container id from /etc/hostname 2026-10-03 21:42:45 -04:00
next.config.ts build(next): explicitly select native TypeScript CLI 2026-10-26 20:11:18 -04:00
package-lock.json feat(skills): S3-backed dynamic catalog — store, harness mounting, appendix, save_skill (0088 stage 1) 2026-10-29 04:30:31 +00:00
package.json feat(skills): S3-backed dynamic catalog — store, harness mounting, appendix, save_skill (0088 stage 1) 2026-10-29 04:30:31 +00:00
postcss.config.mjs feat(web): next.js + tailwind v4 + shadcn + three-theme token system 2026-09-29 16:37:36 -04:00
README.md build(next): select Turbopack explicitly and drop webpack workaround 2026-10-26 20:20:43 -04:00
skills-lock.json refactor!: 0010 phase 6 — delete eve 2026-10-01 19:34:43 -04:00
tsconfig.json feat(web): next.js + tailwind v4 + shadcn + three-theme token system 2026-09-29 16:37:36 -04:00
vitest.config.ts chore(test): persist vitest transforms across runs (fsModuleCache) 2026-10-24 19:15:10 +00:00

sweatshop

A personal software factory: a single Next.js app whose agent runtime is the Vercel AI SDK (WorkflowAgent) on the Workflow SDK. You talk to an agent; the agent works in sandboxed containers per conversation — cloning your repos, running harnesses (pi, claude, cursor, codex), serving live previews, and opening PRs you approve.

Single-user by design. AGENTS.md is the full architecture contract; docs/ holds the numbered design history. This file is how to run it when it isn't already yours.

Requirements

  • Linux or macOS host with a Docker-compatible container engine: podman, OrbStack, Docker Desktop, or colima. The app shells out to the engine's docker/podman CLI; sandboxes run as sibling containers.
  • Node 24 (for ./dev's helper commands and any host-side tooling).

Where it runs

One hard rule: the app container and the sandboxes must share one container engine. Sandboxes are reached over a private container network (sweatshop-harness); the harness bridges (claude / cursor / codex) and the preview proxy dial sandbox IPs there — membership in that network is the boundary, so split-engine setups cannot work.

Two supported topologies:

  1. All-local (a laptop): everything in your local engine via ./dev. Sandboxes and the app sit on the same sweatshop-harness network; previews land on pv-<slug>.previews.localhost (browsers resolve *.localhost to 127.0.0.1) with no wildcard certificate needed.
  2. All-on-one-box (a home-server / VM): the app runs as a systemd unit (or compose) on the machine, browser reaches it over LAN or Tailscale. Previews need PREVIEW_BASE_DOMAIN — a real domain with wildcard DNS pointing at the box (plus a cert) — or an SSH tunnel of the proxy port to your laptop.

Not supported: app on the laptop, sandboxes on a remote daemon. The app dials sandbox container IPs, which are only routable inside the same engine's network — DOCKER_HOST does not change that.

Quickstart

cp .env.example .env.local                      # set at least one key FIRST
./dev install                                   # deps, inside the engine
./dev exec -- npm run db:migrate
DEV_PUBLISH=3000:3000 ./dev exec -- npm run dev # or: build && start

./dev runs everything inside the dev container with the repo bind-mounted; .env.local is passed through. The wrapper publishes nothing by default — in the all-local mode set DEV_PUBLISH (a comma list of host:container pairs) so your browser can reach the app, e.g. DEV_PUBLISH=3000:3000,80:3001 also fronts the preview proxy on port 80 for the pv-<slug>.previews.localhost URLs. Point your browser at http://localhost:3000. Set SWEATSHOP_DB to move the sqlite database (default ./data/sweatshop.db).

Both npm run dev and npm run build explicitly select Turbopack. Native addons and harness bridge packages use serverExternalPackages in the checked-in next.config.ts; no local config overlay or --webpack flag is needed.

Production builds (./dev exec -- npm run build) use the project-local TypeScript 7 native Go compiler for type checking, explicitly selected by experimental.useTypeScriptCli in next.config.ts. The separate ./dev exec -- npm run typecheck gate uses the same compiler. Build-time checks remain enabled so Next.js also checks its freshly generated route types. No Go toolchain or @typescript/native-preview install is needed. See Next.js's CLI checker documentation and TypeScript 7's release notes.

Before your first sandbox: build the sandbox image —

./dev exec -- docker build -t localhost/sweatshop-sandbox -f Containerfile.sandbox .

(or any engine-pullable image per project via the project's image_ref, or SWEATSHOP_SANDBOX_IMAGE for the default).

Provider keys & harness logins

At least one provider key in .env.local — the default routes are derived from what's available (glm > openrouter > gloo):

Env What it unlocks
ZAI_API_KEY GLM provider (Z.AI coding plan) + web_search (first backend)
ANTHROPIC_SEARCH_API_KEY web_search backend via Claude's server-side search (not ANTHROPIC_API_KEY)
TAVILY_API_KEY web_search backend (last in line)
GLOO_API_KEY Gloo provider
OPENROUTER_API_KEY OpenRouter provider

SWEATSHOP_DEFAULT_PROVIDER + SWEATSHOP_DEFAULT_MODEL override the derived default; per-surface pickers on /settings override those.

Harness logins (all optional, per harness):

  • pi — provider-routed (one of the keys above); no separate login.
  • claude — CLAUDE_CODE_OAUTH_TOKEN (from claude setup-token) in .env.local. Single-user personal use.
  • cursor — browser login; save auth.json under data/harness-auth/cursor/.
  • codex — Log in with ChatGPT on /settings (in-app OAuth).

Git-host credentials for the gh / forgejo agent tools and sandbox clones live as rows in the git_credentials sqlite table, editable on /settings → Git credentials (shows only the start/end of each token). .env.local is not read for these.

Previews

Preview URLs are pv-<slug>.<PREVIEW_BASE_DOMAIN> (scheme per PREVIEW_URL_SCHEME). Unset, the base falls back to previews.localhost — fine on a laptop (publish the proxy with DEV_PUBLISH=...,80:3001 so http://pv-<slug>.previews.localhost resolves to it), unreachable from other machines. On a home-server setup set PREVIEW_BASE_DOMAIN to your wildcard domain. The proxy listens on PREVIEW_PROXY_PORT (3001) and must be published where browsers can reach it.

Security posture

Single-user, LAN-only, no auth layer. Provider keys are env; git-host and harness credentials are stored plaintext in sqlite by design (reversible migration later). Secrets reach sandboxes read-scoped. Do not expose this to the internet — add a real verifier first.