Files
GearBox/CLAUDE.md
2026-04-03 13:55:59 +02:00

6.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

GearBox is a single-user web app for managing gear collections (bikepacking, sim racing, etc.), tracking weight/price, and planning purchases through research threads. Full-stack TypeScript monolith running on Bun.

Commands

# Development
bun run dev                 # Starts both Vite client (:5173) and Hono server (:3000) concurrently
bun run dev:client          # Vite dev server on :5173 (proxies /api to :3000)
bun run dev:server          # Hono server on :3000 with hot reload

# Database
bun run db:generate         # Generate Drizzle migration from schema changes
bun run db:push             # Apply migrations to gearbox.db

# Testing
bun test                    # Run all tests
bun test tests/services/item.service.test.ts  # Run single test file

# Lint & Format
bun run lint                # Biome check (tabs, double quotes, organized imports)

# Build
bun run build               # Vite build → dist/client/

Architecture

Stack: React 19 + Hono + Drizzle ORM + SQLite, all running on Bun.

Client (src/client/)

  • Routing: TanStack Router with file-based routes in src/client/routes/. Route tree auto-generated to routeTree.gen.ts — never edit manually.
  • Data fetching: TanStack React Query via custom hooks in src/client/hooks/ (e.g., useItems, useThreads, useSetups). Mutations invalidate related query keys.
  • UI state: Zustand store (stores/uiStore.ts) for panel/dialog state only — server data lives in React Query.
  • API calls: Thin fetch wrapper in lib/api.ts (apiGet, apiPost, apiPut, apiDelete, apiUpload).
  • Styling: Tailwind CSS v4.

Server (src/server/)

  • Routes (routes/): Hono handlers with Zod validation via @hono/zod-validator. Delegate to services.
  • Services (services/): Pure business logic functions that take a db instance. No HTTP awareness — testable without mocking.
  • Route registration in src/server/index.ts via app.route("/api/...", routes).

Shared (src/shared/)

  • schemas.ts: Zod schemas for API request validation (source of truth for types).
  • types.ts: Types inferred from Zod schemas + Drizzle table definitions. No manual type duplication.

Database (src/db/)

  • Schema: schema.ts — Drizzle table definitions for SQLite.
  • Prices stored as cents (priceCents: integer) to avoid float rounding.
  • Timestamps: stored as integers (unix epoch) with { mode: "timestamp" }.
  • Tables: categories, items, threads, threadCandidates, setups, setupItems, settings, users, sessions, apiKeys.

Testing (tests/)

  • Bun test runner. Tests at service level and route level.
  • tests/helpers/db.ts: createTestDb() creates in-memory SQLite with full schema and seeds an "Uncategorized" category. When adding schema columns, update both src/db/schema.ts and the test helper's CREATE TABLE statements.

Path Alias

@/* maps to ./src/* (configured in tsconfig.json).

Key Patterns

  • Thread resolution: Resolving a thread copies the winning candidate's data into a new item in the collection, sets resolvedCandidateId, and changes status to "resolved".
  • Setup item sync: PUT /api/setups/:id/items replaces all setup_items atomically (delete all, re-insert).
  • Image uploads: POST /api/images saves to ./uploads/ with UUID filename, returned as imageFilename on item/candidate records.
  • Image URL fetching: POST /api/images/from-url fetches an image from a URL, saves locally, returns { filename, sourceUrl }.
  • Aggregates (weight/cost totals): Computed via SQL on read, not stored on records.
  • Authentication: Public-read, authenticated-write. Cookie sessions for web UI, API keys (X-API-Key header) for programmatic access. POST /api/auth/setup for first-time account creation. Auth middleware protects all POST/PUT/DELETE on /api/* except /api/auth/*.

Authentication

  • First run: No users exist. Visit /login to create your admin account.
  • Web UI: Cookie-based sessions (gearbox_session), 30-day expiry, auto-refreshed.
  • Programmatic access: API keys created in Settings > API Keys. Pass via X-API-Key header.
  • Public read: All GET endpoints work without auth. POST/PUT/DELETE require auth.
  • Auth routes: /api/auth/login, /api/auth/logout, /api/auth/setup, /api/auth/me, /api/auth/password, /api/auth/keys.

MCP Server

GearBox includes a built-in MCP server for integration with Claude Code and Claude Desktop. Enabled by default, disable with GEARBOX_MCP=false. Authenticated via API key.

Tools (19 total)

Tool Description
list_items List all items, optionally filter by category
get_item Get item details by ID
create_item Add item to collection (for decided items; use create_thread for research)
update_item Update item details
delete_item Remove item from collection
list_categories List all categories
create_category Create a new category
list_threads List research threads (recommended workflow for gear purchases)
get_thread Get thread with candidates
create_thread Start a research thread to compare gear options
resolve_thread Pick winning candidate, adds it to collection
add_candidate Add candidate to a research thread
update_candidate Update candidate details
remove_candidate Remove candidate from thread
list_setups List gear setups
get_setup Get setup with items and totals
create_setup Create a new setup
update_setup Update setup name or items
upload_image_from_url Fetch image from URL, save locally

Resources

  • gearbox://collection/summary — Overview of collection: totals, items per category, active threads.

Configuration

Claude Code (.claude/settings.json):

{
  "mcpServers": {
    "gearbox": {
      "type": "streamable-http",
      "url": "http://localhost:3000/mcp",
      "headers": {
        "X-API-Key": "<your-api-key>"
      }
    }
  }
}

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "gearbox": {
      "type": "streamable-http",
      "url": "http://localhost:3000/mcp",
      "headers": {
        "X-API-Key": "<your-api-key>"
      }
    }
  }
}

Generate an API key from Settings > API Keys after logging in.