DeepSeek Harness Remote
DeepSeek Harness Remote 可將手機或另一台電腦與你運行 DeepSeek Harness 的電腦安全連接,隨時隨地繼續你的工作,方便隨時查看進度並繼續工作。
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Kairos is a self-hostable scheduling app with Calendly parity: personal, group, round robin, collective and multi pool event types, availability schedules, calendar sync (Google, Microsoft, CalDAV, ICS), conferencing (Google Meet, Microsoft Teams, Zoom, Jitsi), booking pages and embeds, single-use links and one-off meetings, meeting polls, routing forms, workflows (email and SMS automations), contacts, payments, webhooks and a Calendly-compatible REST API.
It is a Next.js 16 app (App Router, React 19, TypeScript, Tailwind CSS 4) on Postgres through Drizzle ORM. It runs with zero configuration: locally it uses an embedded PGlite database, and on Vercel it needs only a Postgres database (Neon). Everything else is optional and detected from environment variables.
Requirements: Node.js 22.
npm install
npm run db:seed # optional demo account (run it while the dev server is stopped, see below)
npm run dev # http://localhost:3000
Sign in with [email protected] / password123 (seeded demo account "Julian Joseph", local only). Without the seed,
sign up: the first account becomes the instance admin.
Without DATABASE_URL the app stores data in PGlite under .data/pglite (git ignored). PGlite allows one process per
directory, so stop npm run dev before running npm run db:seed against the same directory, or point one of them at
another directory with PGLITE_DIR. Missing SESSION_SECRET and ENCRYPTION_KEY are generated once and stored in the
database. Emails and SMS are stored in the outbox until a provider is configured (Admin > Outbox shows them).
To use a local Postgres instead, set DATABASE_URL=postgres://... in .env.local; migrations apply automatically.
GET /api/health answers { "ok": true, "db": "pglite", "setupRequired": false, "version": "...", "time": "..." }.
npm run db:seed (never automatic, refused on Vercel) creates or updates the demo account from the owner's real
setup. Re-running it updates the same rows instead of duplicating them.
[email protected] / password123, page /julianjoseph, time zone
America/Los_Angeles, 12 hour clock, instance admin./julianjoseph/30min, purple, Google Meet, 15 minute buffers before and after),
"60 Minute Virtual" (/julianjoseph/60min, same settings) and "In-Person Meal or Coffee" (/julianjoseph/meal, 2
hours, green, "Block Off Work" schedule, 8 venues plus "ask invitee").Options (pass them after --):
| Command | Adds |
|---|---|
npm run db:seed -- --demo | 3 meetings in the next two weeks, 2 contacts, and the demo workflow, routing form and poll of their modules |
npm run db:seed -- --scenario=team | members [email protected] (admin) and [email protected] (same password) and the team "Sales" (/sales) with a round robin ("Sales Intro", /sales/intro) and a collective ("Team Demo", /sales/demo) event type |
npm run db:seed -- --scenario=empty | nothing (applies migrations only) |
The seed uses the same database as the app (DATABASE_URL, else PGlite at PGLITE_DIR or .data/pglite). End to
end tests seed the same scenarios through POST /api/test/seed.
| Script | What it does |
|---|---|
npm run dev | Next.js dev server (Turbopack) |
npm run build | node scripts/migrate.ts && next build (migrates first when a database URL exists) |
npm start | serve a production build |
npm run lint | ESLint 9 (flat config from eslint-config-next) |
npm run typecheck | next typegen && tsc --noEmit for the whole project (through scripts/heavy.sh tsc) |
npm run typecheck:owned -- --module=<id> <paths...> | incremental type check that prints only diagnostics in the given paths |
npm test | Vitest: unit and PGlite integration tests |
npm run test:pg | race and real Postgres tests (*.pg.test.ts) on a throwaway embedded Postgres |
npm run e2e | Playwright (see "Testing") |
npm run db:generate | drizzle-kit migration generation (foundation only) |
npm run db:seed | demo account (see "Demo data"; -- --demo for meetings and contacts, -- --scenario=team for the team scenario) |
npm run check:dashes | fails on em or en dashes anywhere (copy style rule GEN-11) |
npm run check:bundle | fails when the booking page's gzipped client JS exceeds 250KB (GEN-07, after a build) |
npm run build (default), Node.js 22.DATABASE_URL (pooled), DATABASE_URL_UNPOOLED and the legacy POSTGRES_* variables.APP_URL (your production domain), ENCRYPTION_KEY, CRON_SECRET and any integration variables
(see below), then Redeploy.GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET on Vercel.Until a database is connected, every page shows the setup page with status 503, API routes answer 503
{ "error": "setup_required" } and GET /api/health answers { "ok": false, "db": "missing", "setupRequired": true };
the app never falls back to PGlite on Vercel. Never run npm run db:seed against a production database.
npm run build runs scripts/migrate.ts before next build, and every cold start checks cheaply whether the
database is behind the bundled migrations (one query on the pooled connection) and only then migrates over the
unpooled connection under a transaction advisory lock. Concurrent cold starts apply each migration once.MIGRATE_ON_PREVIEW=1, because the Neon integration often attaches the
production database to previews and an unmerged migration would land on production. With Neon preview branching
(each preview gets its own branch database), set MIGRATE_ON_PREVIEW=1 for the Preview environment only. A preview
whose code is ahead of its database logs a warning and shows an admin banner.Register these exact URIs (built from APP_URL, never from the per-deployment VERCEL_URL). For Google, the
step-by-step guide is docs/GOOGLE_SETUP.md.
| Provider | Redirect URI | Variables |
|---|---|---|
| Google (sign in, Calendar, Meet) | {APP_URL}/api/auth/google/callback | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
| Microsoft (sign in, Outlook, Teams) | {APP_URL}/api/auth/microsoft/callback | MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, MICROSOFT_TENANT (default common) |
| Zoom | {APP_URL}/api/integrations/zoom/callback | ZOOM_CLIENT_ID, ZOOM_CLIENT_SECRET |
Google apps in "Testing" status issue refresh tokens that expire after 7 days; calendar scopes need verification for public use. Microsoft app registrations must allow accounts in any organizational directory and personal accounts.
Every variable is optional and documented in .env.example: database URLs, APP_URL,
NEXT_PUBLIC_APP_NAME, SESSION_SECRET, ENCRYPTION_KEY, CRON_SECRET, ADMIN_EMAILS, SIGNUP_POLICY, Google,
Microsoft and Zoom OAuth, JITSI_BASE_URL, email (RESEND_API_KEY or SMTP_*, EMAIL_FROM), SMS (TWILIO_*),
payments (STRIPE_*, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, PAYPAL_*), bot protection (TURNSTILE_*), uploads
(BLOB_READ_WRITE_TOKEN), tuning (CALENDAR_CACHE_TTL_SECONDS, JOBS_POLL_INTERVAL_SECONDS, SAFE_FETCH_ALLOW_HOSTS)
and logging (LOG_LEVEL). Integrations without their variables stay hidden or show "Not configured".
Reminders, calendar sync, webhooks, poll deadlines and other background work are durable jobs in the database. They run right after the request that created them, and a periodic trigger catches up:
vercel.json): GET /api/cron once a day (17 13 * * *), the most a Hobby plan allows. Vercel
sends Authorization: Bearer $CRON_SECRET when CRON_SECRET is set..github/workflows/cron.yml): every 10 minutes. Set the repository variable APP_URL and the
repository secret CRON_SECRET; the workflow is skipped while either is missing. GitHub runs schedules late (often
10 to 60 minutes) and disables them on public repositories after 60 days without activity. On a private repository
on the free plan every run bills at least one minute (about 4,320 minutes a month against 2,000 included): change
the schedule to */30 * * * * or rely on the pinger below.GET {APP_URL}/api/cron every 5 minutes with the header Authorization: Bearer {CRON_SECRET}, so reminders arrive
on time.Self-hosted instances (not on Vercel) also run an in-process poller every JOBS_POLL_INTERVAL_SECONDS (default 30).
npm test runs Vitest with an in-memory PGlite per test file (tests/helpers/db.ts, factories in
tests/factories, provider fakes in tests/helpers/fake-providers.ts).npm run test:pg starts a throwaway embedded Postgres (scripts/with-embedded-pg.mjs) and runs the *.pg.test.ts
files: race tests must run on real Postgres because PGlite is a single backend.E2E_PORT=3400 PGLITE_DIR=.data/pglite-e2e-mine NEXT_DIST_DIR=.next-e2e-mine scripts/heavy.sh server npx playwright test e2e/<module> starts its own next dev (or next start with E2E_SERVER=start after a build into
the same NEXT_DIST_DIR) with E2E_TEST_MODE=1 and a random E2E_SECRET. The test API (/api/test/*) answers 404
unless both are set and the request carries the secret, and always on Vercel. In this repository's build sandbox
Chromium is preinstalled; never run playwright install there (CI installs it).e2e/fixtures (api.reset(), seed("owner" | "team" | "empty"), loginAs(page, email), outbox, axe). The foundation suite (e2e/foundation: test API harness, framing headers, every sidebar
link, the setup page decision, the UI kit gallery, login and signup) runs with E2E_PORT=3400 PGLITE_DIR=.data/pglite-e2e-foundation NEXT_DIST_DIR=.next-e2e-foundation; with E2E_SERVER=start it also starts
the same build with VERCEL=1 and no database to check the real setup mode responses.The codebase is built by parallel agents, each owning a module from docs/WORKPLAN.json:
ownedPaths). Agents edit only their own files and import anything else.// OWNER: <module-id>) and a placeholder for every route, so modules can
work concurrently. Owners replace stub implementations but keep the exported signatures.src/db/** and drizzle/**. Modules that need a schema change file a request in
docs/schema-requests and use metadata jsonb columns meanwhile.scripts/heavy.sh <server|tsc> <command...> (at most two of each kind at once on the
build machine). npm run typecheck:owned -- --module=<id> <paths...> type checks the whole project incrementally but
reports only the module's own diagnostics.runAction, authorization helpers, now() for business time and $now
in SQL, safeFetch for user-supplied URLs, no em or en dashes) are in ARCHITECTURE section 26.