Vite+ is one CLI for dev, build, tests, lint, format, and package management—it wraps Vite and related bundled tooling. vp dev and vp build invoke Vite. Explore with vp help, vp <command> --help, and vp --version.
Common commands: vp install, vp dev, vp check, vp lint, vp test, vp build, vp preview, vp run <script>, vp add / vp remove / vp update.
Workflow: After pulling, run vp install when dependencies or lockfiles may have changed. Before calling work done, run vp check and vp test — CI runs vp check → vp test → vp build.
- Using the package manager directly: Do not use pnpm, npm, or Yarn directly. Vite+ can handle all package manager operations.
- Always use Vite commands to run tools: Don't attempt to run
vp vitestorvp oxlint. They do not exist. Usevp testandvp lintinstead. - Running scripts: Vite+ commands take precedence over
package.jsonscripts. If there is atestscript defined inscriptsthat conflicts with the built-invp testcommand, run it usingvp run test. - Do not install Vitest, Oxlint, Oxfmt, or tsdown directly: Vite+ wraps these tools. They must not be installed directly. You cannot upgrade these tools by installing their latest versions. Always use Vite+ commands.
- Use Vite+ wrappers for one-off binaries: Use
vp dlxinstead of package-manager-specificdlx/npxcommands. - Import JavaScript modules from
vite-plus: Instead of importing fromviteorvitest, all modules should be imported from the project'svite-plusdependency. For example,import { defineConfig } from 'vite-plus';orimport { expect, test, vi } from 'vite-plus/test';. You must not installvitestto import test utilities. - Type-Aware Linting: There is no need to install
oxlint-tsgolint,vp lint --type-awareworks out of the box.
vp checkfails on warnings too —lint.optionssetsdenyWarnings,typeAware, andtypeCheck.src/routeTree.gen.tsis generated. It is excluded from fmt and lint; never edit it by hand.- Class names are merged with
cnfromcn(drop-in forclsx+tailwind-merge). Oxfmt's Tailwind class sorting is configured forcnonly. - Only
.test.ts/.test.tsxfiles undersrc/are collected (test.includeinvite.config.ts). Import test utilities fromvite-plus/test. ~/*maps tosrc/*— declared once intsconfig.json(compilerOptions.paths) and consumed by Vite throughresolve.tsconfigPaths: true. Relative imports are forbidden; see.claude/rules/typescript/project-structure.md.- Committing runs
.vite-hooks/pre-commit→vp staged, which appliesvp check --fixto stagedjs,jsx,ts,tsx,json,cssfiles. - New dependency versions must be 24h old.
pnpm-workspace.yamlsetsminimumReleaseAge: 1440, sovp add/vp updateon a freshly published version fails withERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION. Wait it out or pick an older version — do not bypass the policy.trustPolicy: no-downgradeis also on. - Edits trigger react-doctor automatically via the
PostToolBatchhook in.claude/settings.json(--scope changed --blocking warning). Fix what it reports before calling work done.
Human-readable source of truth: CODING_GUIDELINES.md. .claude/rules/ holds short English excerpts for agents. Do not add conventions only in one place.
Installed packages are the source of truth (package.json). Do not write code against libraries that are not installed.
- Installed: TanStack Start + React 19, Convex (
convex+@convex-dev/react-query), TanStack Query (Convex SSR adapter only, via@tanstack/react-query+@tanstack/react-router-ssr-query), Mantine 9 (with@mantine/dates+dayjs) andtailwind-preset-mantineon Tailwind 4, Valibot, Formisch, better-result,cn. - Tooling: Vite+ (
vp). Convex CLI viavp run convex:dev/vp exec convex …. - Auth: not wired yet. Do not add Better Auth, Clerk, or WorkOS in this bootstrap.
- Rejected: Better Auth, Jotai, ky, MSW, TanStack Form, generated API clients (
src/lib/api/generated/),clsx/tailwind-merge(cncovers this), Elysia / Drizzle /pg. TanStack Query is only forconvexQuery(...)— do not use it as a generic REST client.
UI defaults to Mantine components; Tailwind handles layout on the wrappers around them. See CODING_GUIDELINES.md §UI and .claude/rules/typescript/mantine-tailwind.md. src/styles.css imports tailwind-preset-mantine, which pulls in Tailwind and @mantine/core/styles.layer.css in the right layer order — do not add a bare @import "tailwindcss". Rationale in docs/adr/0003-mantine-with-tailwind-preset.md.
Not part of vp check. Use vp run so installs stay routed through Vite+.
- Fallow (
vp run fallow) — unused files, dependencies, and exports. Use when trimming deps or refactoring entry points (.fallowrc.jsonconfigures the project). - react-doctor (
vp run doctor) — React-focused health checks. The script uses--no-lint; keep ordinary linting onvp lint.
Issues live in GitHub Issues for sc30gsw/cairn, managed via the gh CLI. See docs/agents/issue-tracker.md.
The five canonical triage roles are used verbatim as label strings. See docs/agents/triage-labels.md.
Single-context: CONTEXT.md + docs/adr/ at the repo root. See docs/agents/domain.md.
This is a TanStack Start (SSR) + Convex app. The web UI (src/routes/index.tsx) renders OwnerGate and DayPage (Convex days.open / days.get). src/router.tsx throws if VITE_CONVEX_URL is unset — so the Convex backend must be running before/alongside the web dev server.
- Node / PATH: The base image ships
/exec-daemon/node(v22) earlier inPATH, but this repo requires Node>=24.17.0.~/.bashrcprepends the nvm-installed Node 24.17.0 and/workspace/node_modules/.bin(sovpis onPATH). Interactive/login shells get Node 24 andvpautomatically; a bare non-interactivebash -cmay still see the v22 shim. - Convex backend (headless): No Convex login is available in cloud VMs. Run the backend in anonymous local mode:
CONVEX_AGENT_MODE=anonymous vp exec convex -- dev(keep it running, e.g. in tmux). First run prompts "Set up Convex AI files?" — answern(don't modify the repo). It provisions a local backend athttp://127.0.0.1:3210and writes.env.local(VITE_CONVEX_URL,CONVEX_DEPLOYMENT,VITE_CONVEX_SITE_URL);.env.localis git-ignored. - Seed data: New users start with an empty catalog (no auto-seed on
days.open). Callmutations.catalog.ensureto load the Notion-derived default catalog, or add items/presets manually. Verify withconvex run days:get '{"dateJst":"2026-08-17","todayJst":"2026-08-17"}'after signing in, or viavp test. - Auth (Cloud Agent / PR testing): Set
BETTER_AUTH_SECRETandSITE_URL=http://localhost:3000on the Convex deployment;VITE_SITE_URL=http://localhost:3000in.env.local. Sign up with username + email + password on the login screen, or use Google OAuth whenGOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRETare set (calendar sync additionally needs the Google Calendar API enabled on that OAuth client — seedocs/specs/calendar-sync.md§6). - Web dev server:
vp devserves athttp://localhost:3000/. - What works:
vp test(passes) andvp build(Rolldown, passes). - Pre-existing breakage — not a regression: This branch already overrides
react-doctor/no-nested-component-definition. Runningtscdirectly (TS 7) rejectstsconfig.json'sbaseUrl; type-checking is intended to run viavp, and Vite resolves the~/*alias at runtime. Do not "fix" these as part of unrelated work.
This project uses Convex as its backend.
When working on Convex code, always read
convex/_generated/ai/guidelines.md first for important guidelines on
how to correctly use Convex APIs and patterns. The file contains rules that
override what you may have learned about Convex from training data.
Convex agent skills for common tasks can be installed by running
npx convex ai-files install.
This repo is indexed in graft/: small linked markdown nodes that explain each
system and carry exact file:line spans, kept in sync with the code through git.
For ANY task here — understanding how something works, finding where code lives,
or scoping a change — get context from the graph before grepping or opening
source files. Re-ask freely (it's cheap) and reuse literal identifiers you
already have (symbol, error string, file name) as the query. New to this repo?
Run graft map first — a token-budgeted orientation (dir clusters, hubs,
hotspots), no LLM, no key.
- Run
graft ask "<your question>" --source→ ranked nodes with the relevant code spans inlined (each hit's ≤8-line crux by default;--fullfor whole definitions when the crux isn't enough). Match the tool to the task shape: for understanding or editing, the top node IS the answer — cite itscovers:file:line spans and edit straight from--source. For exhaustive tasks ("every occurrence / every caller of this pattern"), ranked results are top-N, not complete — rungraft grep "<literal>"instead (exhaustive over indexed files, grouped by enclosing symbol), falling back to rawgrep -rnonly for unindexed files. graft skeleton <file>→ every definition's signature + span, ~10× cheaper than reading the file; use it to skim an API surface.graft callers <symbol>gives precomputed, exact edges — who calls this. Add--direction outfor what it calls, or--depth Nto walk transitively for the full blast radius. For structural questions, skip ranking and use this directly.- Or browse:
graft/INDEX.mdlists every node; follow the links. - Monorepos and folders of multiple repos rank fairly across sub-projects —
hits carry
[scope/]labels naming which one they're from. Narrow withgraft ask "<task>" --in <scope>/once you know where you're working.
If a returned span is truncated ("+N more lines"), open the file at that exact range before finalizing. Only open source files when a node genuinely lacks a needed detail, and then at the exact file:line the node points to — never re-read whole files.
After big code changes, refresh the graph with graft build (deterministic,
no API key, $0).