# CLAUDE.md

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

## Git Rules

**NEVER commit without explicit user permission.** Always ask before running `git commit`. Other agents may be working on the codebase concurrently.

## Build & Dev Commands

All commands run from repo root.

**IMPORTANT: Always use workspace-specific commands.** Never use `npm run build` or `npm run test` which build/test ALL workspaces. This wastes time and can cause confusing output when you only need to verify one app.

### Workspace-Specific Commands (preferred)

```bash
# Dashboard
npm run dashboard:check   # Typecheck + lint in parallel (FAST - use this to validate changes)
npm run dashboard:build   # Build dashboard for production
npm run dashboard:test    # Run dashboard tests (vitest)
npm run dashboard:dev     # Start dashboard dev server (port 5173)

# Relay
npm run relay:dev         # Start relay dev server (port 8787)
npm run relay:build       # Build relay for production
npm run relay:test        # Run relay tests (jest)

# Guides
npm run guides:dev        # Start guides dev server (port 5174)
npm run guides:build      # Build guides for production
```

**After making changes, run `npm run dashboard:check` to quickly validate.** This runs typecheck and lint concurrently and is faster than a full build.

### Global Commands (avoid unless deploying)

```bash
npm run build             # Build ALL workspaces - avoid, use workspace-specific
npm run lint              # Lint all workspaces
npm run lint:fix          # Lint and auto-fix all workspaces
npm run test              # Test ALL workspaces - avoid, use workspace-specific
```

### CLI Tool

```bash
npm run cli                             # Show all commands
npm run cli auth login                  # Store Kalshi credentials
npm run cli auth status                 # Check auth status
npm run cli discover series             # List Kalshi series
npm run cli discover markets <ticker>   # List markets for a series

# Polymarket exploration (alias: poly)
npm run cli polymarket search "Lakers"  # Search markets by text
npm run cli poly series                 # List sports series
npm run cli poly events nba-2026        # List events in a series
npm run cli poly slug <slug>            # Look up specific market
npm run cli poly analyze                # Analyze slug patterns
```

## Package Management

**This project uses npm (not pnpm).** Check for `package-lock.json`.

```bash
# Install dependencies (run from repo root)
npm install

# Add a dependency to dashboard workspace (use PACKAGE NAME, not path)
npm install <package> -w @galactus/dashboard

# Add a dependency to relay workspace
npm install <package> -w @galactus/relay

# Wrong: npm install <package> -w apps/dashboard
# Right: npm install <package> -w @galactus/dashboard
```

## Architecture

**Monorepo with npm workspaces:**

- `apps/dashboard` - React 18 + Vite frontend SPA (trading terminal)
- `apps/guides` - React 18 + Vite SPA (standalone educational content with KaTeX)
- `apps/relay` - Express + WebSocket server (CORS bypass, transport-only)
- `packages/shared` - Shared TypeScript types

**Frontend-Backend Split:**

- Frontend holds API keys and signs all requests (private key never leaves browser)
- Backend relay is transport-only (CORS + WebSocket forwarding)
- RSA-PSS signing via WebCrypto API; node-forge handles PEM format conversions

**Data Flow:**

- HTTP: Dashboard → relayHttp → Relay Server (8787) → External API
- WebSocket: Dashboard → relayWs → Relay Server → External WS
- Real-time market data via MarketStream class
- Candlestick aggregation happens client-side

**State Management:**

- React hooks (useState, useEffect, useCallback, useRef) - no Redux
- useRef for non-reactive state (API clients, charts, streams)
- Credentials stored in localStorage

## Key Files

- `apps/dashboard/src/App.tsx` - Root component, orchestrates state/streams/charts
- `apps/dashboard/src/lib/kalshiApi.ts` - Kalshi REST API client with RSA-PSS auth
- `apps/dashboard/src/lib/kalshiAuth.ts` - Crypto key handling, PKCS#1 → PKCS#8 conversion
- `apps/dashboard/src/lib/relayHttp.ts` - HTTP relay client
- `apps/dashboard/src/lib/relayWs.ts` - WebSocket relay client
- `apps/dashboard/src/lib/marketStream.ts` - WebSocket market data stream
- `apps/dashboard/src/lib/positionTracker.ts` - P&L calculation engine
- `apps/dashboard/src/lib/chartManager.ts` - Lightweight Charts wrapper
- `apps/dashboard/src/lib/polymarket/` - Polymarket integration

## Key Classes

- `PositionTracker` - Tracks positions, calculates P&L for long/short YES/NO sides
- `OrderMonitor` - Polls for order fills, emits fill events
- `MarketState` - Time-series store for candlesticks
- `ChartManager` - Wraps Lightweight Charts, manages chart lifecycle

## Environment Variables

Dashboard (`apps/dashboard/.env`):

- `VITE_DASHBOARD_PASSWORD_HASH` - SHA-256 hash of dashboard gate password
- `VITE_ROUTER_BASE` - Base path for subdirectory deployment (e.g., `/dashboard`)
- `VITE_RELAY_HTTP_URL` - Override relay HTTP endpoint (default: `/relay/http`)
- `VITE_RELAY_WS_URL` - Override relay WS endpoint (default: `ws://localhost:8787/relay/ws`)

Relay (`apps/relay/.env`):

- See `apps/relay/.env.example` for relay-specific configuration

## Technologies

- React 18.2.0, Vite 6.4.1, TypeScript 5.3.3 (strict mode)
- Tailwind CSS 3.x (components in `src/components/atoms/`)
- Lucide React for icons
- Lightweight Charts 5.1.0 for OHLC candlesticks
- node-forge 1.3.3 for RSA-PSS signing and PEM handling
- ethers 5.8.0 + @polymarket/clob-client for Polymarket integration
- Express 4 + ws for relay server
- KaTeX for math rendering (guides app only)

## Styling

- Tailwind CSS with CSS variables for theming (dark mode default)
- `apps/dashboard/src/globals.css` - Tailwind directives + CSS variables
- `apps/dashboard/src/styles.css` - Legacy custom styles (being migrated)
- `apps/dashboard/src/lib/utils.ts` - `cn()` helper for className merging
- Path alias: `@/` maps to `apps/dashboard/src/`

## UI Component Rules

**CRITICAL: NEVER use native HTML form elements directly.** This is a strict rule with no exceptions. Use the styled components in `apps/dashboard/src/components/atoms/` instead:

- `<select>` → **NEVER USE.** Use `<Dropdown>` from `@/components/atoms/Dropdown`
- `<input type="checkbox">` → **NEVER USE.** Use `<Toggle>` from `@/components/atoms/Toggle`
- Modals → Use `<Modal>` from `@/components/atoms/Modal`

Native elements look ugly and break the dark theme. Always check `apps/dashboard/src/components/atoms/` for existing styled components before creating new ones. If you find yourself writing `<select>` or native checkbox inputs, STOP and use the component versions instead.

## Number Formatting Rules

**CRITICAL: All numbers displayed to users must use locale formatting with thousand separators.**

### Monetary Values

**Use the `<Money>` component** from `@/components/atoms/Money` for ALL monetary displays:

```tsx
import { Money } from '@/components/atoms/Money';

// P&L (colored, with +/- sign)
<Money value={pnl} variant="pnl" />           // +1,234.56 (green) or -1,234.56 (red)

// Currency (with $ prefix)
<Money value={price} />                        // $1,234.56

// Plain number (no $, no color)
<Money value={amount} variant="plain" />       // 1,234.56
```

**NEVER** use `.toFixed(2)` for monetary values. **NEVER** manually format currency.

### Other Numbers

- Use `{value.toLocaleString()}` for integers (quantities, counts, queue positions)
- Or use `formatNumber()` from `@/lib/formatters`

Examples:

- ✗ Bad: `{pnl.toFixed(2)}` or `$${price.toFixed(2)}`
- ✓ Good: `<Money value={pnl} variant="pnl" />` or `<Money value={price} />`

## Code Organization Rules

**No barrel files (`index.ts`) unless they reduce significant import clutter.** Don't create `index.ts` files just for the sake of it. Only add them when consumers would otherwise need 5+ import lines from the same directory. Prefer direct imports like `from '@/components/market-explorer/MarketCard'` over barrel re-exports.

**Folder naming:** Use kebab-case for multi-word folder names.

- ✓ Good: `market-explorer/MarketExplorer.tsx`, `order-book/OrderBook.tsx`
- ✗ Bad: `MarketExplorer/MarketExplorer.tsx`, `order_book/OrderBook.tsx`

## File Search Rules

**Always exclude `node_modules` from file searches.** When using Glob, Grep, or any file search:

- Use patterns like `apps/**/*.ts` or `packages/**/*.ts` instead of `**/*.ts`
- Never search the root `node_modules/` directory
- If you need to inspect a dependency, read the specific file directly

## Skills

**When writing lessons, guides, or educational content:** Always invoke the `lesson-planning` skill FIRST using the Skill tool. This provides pedagogical guidelines, UI components to use, and quality standards. Lesson files live in `apps/guides/src/components/guides/lessons/`.

## Documentation Conventions

All documentation files live in the `docs/` directory (except `README.md` and `CLAUDE.md` which stay at root).

**Naming convention:** Use lowercase kebab-case for all markdown filenames.

- ✓ Good: `some-spec-abc.md`, `feature-documentation.md`
- ✗ Bad: `SOME-SPEC-ABC.md`, `FEATURE_DOCUMENTATION.md`, `SomeSpecAbc.md`

## Operating Model

This project uses the StreamRift Hand Kit. Type `/commands` to see all available commands.

**"Hand" is a command router.** When StreamRift says "hand" followed by anything, parse the intent and execute the matching slash command. Examples:

- "hand" / "run it" / "hand mode" → execute `/run-it`
- "hand, status report" / "sitrep" → execute `/sitrep`
- "hand, architect the auth layer" → execute `/architect auth layer`
- "hand, scout MCP servers" → execute `/scout MCP servers`
- "hand, build user dashboard" → execute `/build user dashboard`
- "hand, forge the CI pipeline" → execute `/forge CI pipeline`
- "hand, war room on v2 strategy" → execute `/war-room v2 strategy`
- "hand, make it so" / "engage" → execute `/make-it-so`
- "hand, wrap it" / "debrief" → execute `/wrap-it`
- "hand, commands" → execute `/commands`

If the intent after "hand" doesn't match a known command, treat it as a general request in COO mode (proactive co-pilot, sandwich format, decision framework from `/run-it`).

**Deep context trigger:** When StreamRift asks "why am I doing this", "what's the point", "remind me of the vision", or needs strategic grounding for a decision — read `.hand/STREAMRIFT-FULL.md`. This is the full origin story, principles in depth, and decision-making lenses. Don't load it on boot. Load it when the moment calls for it.

## Documentation Index

| Document              | Description                            |
| --------------------- | -------------------------------------- |
| `README.md`           | Quick start guide - how to run the app |
| `docs/deployment.md`  | Deployment configuration and setup     |
| `docs/devops.md`      | DevOps workflows and CI/CD             |
| `docs/merge-notes.md` | Notes from monorepo merge              |
