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
15 changes: 15 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT\" | grep -qE '\\.(ts|tsx)\"'; then pnpm tsc --noEmit 2>&1 | head -30; fi"
}
]
}
]
}
}
12 changes: 9 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,24 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- uses: pnpm/action-setup@v4
- uses: pnpm/action-setup@v6

- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: 20
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Lint
run: pnpm lint

- name: Type check
run: pnpm tsc --noEmit

- name: Run tests
run: pnpm test

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ingest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ jobs:
ingest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- uses: pnpm/action-setup@v4
- uses: pnpm/action-setup@v6

- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: 20
cache: pnpm
Expand Down
40 changes: 39 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,49 @@

This is a RAG chatbot that answers TTRPG rules questions using Old School Essentials markdown files stored in `vault/`.

`DEBUG=true` enables server-side logging of query, retrieved doc count, and chunk previews. `CHATBOT_ENABLED=false` disables the LLM entirely.
**Data flow:** User message → `app/api/chat/route.ts` (Next.js API route) → `lib/retrieval.ts` (Cohere embedding + Supabase vector search) → Anthropic Claude LLM (via AI SDK) → streamed response.

**Key files:**
- `app/api/chat/route.ts` — streaming chat API route
- `lib/retrieval.ts` — RAG retrieval logic (embedding + vector search)
- `lib/supabase-client.ts` — Supabase client (anon key, browser/server)
- `scripts/ingest.ts` — ingestion pipeline: reads vault MD → chunks → embeds → upserts to Supabase
- `scripts/supabase-admin.ts` — Supabase admin client (service role key, scripts only)
- `components/` — React chat UI components
- `vault/` — source OSE markdown files (read-only reference material)

**Environment flags:**
- `DEBUG=true` — server-side logging of query, retrieved doc count, and chunk previews
- `CHATBOT_ENABLED=false` — disables the LLM entirely (retrieval still runs)

Plans are found in `docs/plans`

## Path-scoped rules

- `lib/` — pure functions; no direct Supabase admin client usage here (use `scripts/supabase-admin.ts` for admin ops)
- `scripts/` — CLI entry points; may use admin client; never imported by app code
- `components/` — React only; no direct API calls (use `useChat` hook from AI SDK)
- `app/api/` — Next.js route handlers; keep thin — delegate logic to `lib/`

## Setup

Pre-commit hooks require gitleaks for secret scanning:
```bash
brew install gitleaks
```

## Commands

```bash
pnpm test # run vitest unit tests
pnpm lint # run ESLint
pnpm tsc --noEmit # type check (no output files)
pnpm dev # start Next.js dev server
pnpm ingest # run ingestion pipeline (requires .env.local)
```

## Remember

- Write tests FIRST before writing production code
- Check for TS errors before considering a task 'done'
- `pnpm tsc --noEmit` must pass before any PR is merged
6 changes: 5 additions & 1 deletion lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ pre-commit:
check:
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc,md}"
run: npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
stage_fixed: true
stage_fixed: true
typecheck:
run: pnpm tsc --noEmit
secrets:
run: gitleaks protect --staged --redact
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"postinstall": "lefthook install",
"dev": "next dev",
"build": "next build",
"start": "next start",
Expand Down