Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 0 additions & 140 deletions .claude/commands/create-local-dev.md

This file was deleted.

33 changes: 33 additions & 0 deletions .claude/commands/dev-login.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
description: Bootstrap the local DB, mint a session cookie, and open a signed-in Chromium window at localhost:3000 -- one command, no manual paste.
---

Run one command. It does the bootstrap, the mint, ensures the dev server
is serving `localhost:3000` (starting `pnpm dev` detached if nothing is
listening yet), the cookie injection, and opens a detached Chromium window
already signed in as `$1` (default `dev@keeperhub.local`):

```bash
pnpm dev:login "${1:-dev@keeperhub.local}"
```

The window is a separate Chromium instance (its own user-data-dir under
`.claude/.dev-chrome-profile/`), so it does not touch the user's normal
Chrome. The terminal returns as soon as the browser launches.

Hard refusals to respect:
- The script refuses to run if `DATABASE_URL` host is not local. Do not
edit that guard, and do not run this against staging or prod.
- Do not commit `.claude/.dev-session-cookie-LOCAL` or
`.claude/.dev-chrome-profile/` (gitignored).

If the user wants only the cookie file (no browser) for a manual paste
into their normal Chrome, run instead:
```bash
KEEPERHUB_DEV_MINT=1 pnpm dev:mint-cookie "${1:-dev@keeperhub.local}"
```

If they only need the DB set up (no cookie, kh CLI only), run:
```bash
pnpm dev:bootstrap
```
80 changes: 80 additions & 0 deletions .claude/skills/create-local-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
name: create-local-dev
description: Bring a fresh KeeperHub worktree to a signed-in Chromium window against the shared local Docker Postgres in one command, without going through the signup UI. Use when starting work in a new worktree, when "I'm not signed in to localhost:3000", or any time you need an authenticated browser session for local manual testing. Avoids the ~30 tool-call signup -> OTP -> MFA -> TOTP loop by reusing in-codebase session helpers, then auto-opens a Chromium window with the cookie already loaded.
---

# Local-dev one-command sign-in

This skill is the fast path from a fresh worktree to a signed-in browser.

It does not touch any production auth code: it composes Drizzle inserts
and the existing `signSessionCookieValue` / `hashSessionToken` helpers from
`lib/auth-session-token-hash.ts`, then loads the cookie into a Playwright
Chromium profile and launches it detached.

Hostname guard refuses to run unless `DATABASE_URL` resolves to a local
Postgres host. The standalone `dev:mint-cookie` additionally requires
`KEEPERHUB_DEV_MINT=1`; `dev:login` sets that env var for its mint child
because invoking `dev:login` is itself the explicit acknowledgement.

## When to invoke

- You opened a new worktree and the app at `localhost:3000` is anonymous.
- The user asks to "log in locally" / "sign in for testing".
- A manual-test task needs a real authenticated session (workflow list,
org-scoped endpoints, anything that goes through `getDualAuthContext`).

Do NOT invoke this skill against staging or prod. The script will refuse
on hostname grounds. Do not try to defeat that guard.

## The one command

```bash
pnpm dev:login
```

Optional override: `pnpm dev:login some-other@email`. Default is
`dev@keeperhub.local`.

What it does, in order:
1. Asserts the local-DB hostname guard.
2. Runs `pnpm dev:bootstrap` (idempotent): backfills the drizzle journal
only if the schema was bootstrapped via `db:push`, runs `pnpm db:migrate`,
seeds the persistent e2e users plus a dev user/org/membership, pre-trusts
`127.0.0.1` + `::1` in `user_trusted_ips`, marks the dev user
`twoFactorEnabled=true` so the proxy MFA gate lets them through,
binds the local `kh` CLI token from `~/.config/kh/hosts.yml`, and
upserts 8 workflow fixtures (Manual / Schedule / Webhook / Event,
on+off, plus a soft-deleted row).
3. Mints a Better Auth session row (matches the shape of
`app/api/auth/oauth-mfa-finalize/route.ts`) and writes the signed cookie
to `.claude/.dev-session-cookie-LOCAL`.
4. Seeds that cookie into a Playwright-managed Chromium persistent profile
under `.claude/.dev-chrome-profile/` (gitignored).
5. Spawns Chromium detached against `http://localhost:3000` with that
profile. The terminal returns. The Chromium window is independent from
the user's normal Chrome (separate user-data-dir).

Re-running `pnpm dev:login` just refreshes the cookie inside the same
profile, so the user can keep the window open across sessions.

## Lower-level commands (rarely needed)

- `pnpm dev:bootstrap` -- DB setup only, no cookie or browser. Use for CI
or when scripting against the seeded fixtures via the kh CLI.
- `KEEPERHUB_DEV_MINT=1 pnpm dev:mint-cookie <email>` -- mint a cookie file
only, no browser. Use when you want the signed value for manual paste
into another browser, or for headless cookie-driven scripts.

## Boundaries

- Do NOT modify `lib/auth.ts`, `lib/auth-session-token-hash.ts`, or any
`app/api/**` route to weaken the auth flow for local convenience. This
whole skill exists precisely so we never need to.
- Do NOT commit `.claude/.dev-session-cookie-LOCAL` or
`.claude/.dev-chrome-profile/` (gitignored already).
- Do NOT add an env override that lets the mint script run against a
non-local DB. There is no legitimate reason to forge a session against
staging or prod.
- Chromium is launched detached. The script exits as soon as the browser
is up; closing the script does not close the browser.
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ analysis/
.cursor/
.probes/

# Local-dev sign-in tooling (pnpm dev:login). Never run in production and
# dev-bootstrap.ts imports from tests/, which is excluded above.
scripts/seed/dev-bootstrap.ts
scripts/seed/fixtures/dev-workflows.ts
scripts/dev-mint-session.ts
scripts/dev-login.ts
scripts/dev-login-browser.ts

# Dev-only config files
playwright.config.ts
vitest.config.mts
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ packages/*/dist/
.claude/test-*-output.txt
.claude/worktrees/

# Local dev session cookie minted by scripts/dev-mint-session.ts
.claude/.dev-session-cookie-LOCAL

# Chromium profile seeded by scripts/dev-login.ts (cookies + cache only)
.claude/.dev-chrome-profile/

# Playwright MCP screenshots
.playwright/
.playwright-cli/
Expand All @@ -152,6 +158,8 @@ reports/

.mcp.json

.claude/.dev-server-LOCAL.log

# Understand-Anything: commit knowledge-graph.json + config.json + .understandignore.
# Ignore meta (timestamp churn) and fingerprints (per-machine incremental cache).
.understand-anything/intermediate/
Expand Down
53 changes: 53 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,59 @@ Note: a shell-set `DATABASE_URL` overrides the value in `.env` (drizzle.config.t

---

## Local Dev Sign-in

To get a fresh worktree to a signed-in browser without going through the
signup -> OTP -> MFA -> TOTP UI loop, run one command:

```bash
pnpm dev:login # default dev@keeperhub.local
pnpm dev:login some-other@example.com # any seeded email
```

This bootstraps the DB (idempotent), mints a Better Auth session via the
same helpers (`signSessionCookieValue`, `hashSessionToken`) the production
OAuth-MFA finalize path uses, ensures a dev server is serving
`http://localhost:3000` (reuses one if it is already up, otherwise spawns
`pnpm dev` detached -- logs to `.claude/.dev-server-LOCAL.log` -- and waits
for it to respond), seeds the signed cookie into a Playwright-managed
Chromium profile, and launches Chromium detached at the now-serving URL.
When a server is already running the terminal returns as soon as the
browser launches; on a cold start it blocks until the server is ready. The
Chromium instance has its own user-data-dir under
`.claude/.dev-chrome-profile/`, so it does not touch the user's normal
Chrome.

Lower-level commands for headless / scripted use:

- `pnpm dev:bootstrap` -- DB setup only. Backfills the drizzle journal
only if the schema was bootstrapped via `db:push`, runs `pnpm db:migrate`,
seeds the persistent e2e users plus a dev user/org, pre-trusts
`127.0.0.1` + `::1`, marks the dev user `twoFactorEnabled=true`, binds
the local `kh` CLI token from `~/.config/kh/hosts.yml`, and upserts 8
workflow fixtures (Manual/Schedule/Webhook/Event triggers, on+off, plus
a soft-deleted row).
- `KEEPERHUB_DEV_MINT=1 pnpm dev:mint-cookie <email>` -- mints a cookie
file at `.claude/.dev-session-cookie-LOCAL` without opening a browser.

**Hard boundaries -- do not relax these:**

- All three scripts refuse to run unless `DATABASE_URL` host is
`localhost`, `127.0.0.1`, `::1`, `db`, or `postgres`. The standalone
`dev:mint-cookie` additionally requires `KEEPERHUB_DEV_MINT=1`;
`dev:login` sets that env var for its mint child because invoking
`dev:login` is itself the explicit acknowledgement. Do not add other
bypass envs.
- None of these scripts edit `lib/auth.ts`,
`lib/auth-session-token-hash.ts` (imported only), or any `app/api/**`
route. The whole point is to avoid any production runtime change for
local convenience. If a future task needs to weaken production auth,
do it in production auth and review it there -- not here.
- `.claude/.dev-session-cookie-LOCAL`, `.claude/.dev-chrome-profile/`, and
`.claude/.dev-server-LOCAL.log` are gitignored. Do not commit them.

---

## Plugin Development

**Context**: Building Web3 integrations for the workflow system. Plugins go in `plugins/`.
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
"db:seed-test-wallet": "tsx scripts/seed/seed-test-wallet.ts",
"db:seed-workflows": "tsx scripts/seed/seed-protocol-workflows.ts",
"db:seed-all": "pnpm db:seed && pnpm db:seed-test-wallet && pnpm db:seed-workflows",
"dev:bootstrap": "tsx scripts/seed/dev-bootstrap.ts",
"dev:mint-cookie": "tsx scripts/dev-mint-session.ts",
"dev:login": "tsx scripts/dev-login.ts",
"db:setup": "pnpm db:migrate && pnpm db:setup-workflow && pnpm db:seed",
"db:setup-workflow": "workflow-postgres-setup",
"discover-plugins": "tsx scripts/discover-plugins.ts",
Expand Down
Loading
Loading