# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Tusk is a PostgreSQL database management GUI built with Tauri 2 (Rust backend) and React (TypeScript frontend). ## Development Commands ```bash npm run app:dev # Start full app in dev mode (Vite HMR + Rust backend) — alias for `tauri dev` npm run app:bundle # Build production desktop executable — alias for `tauri build` npm run dev # Start only the Vite frontend dev server (port 5173) npm run build # Build frontend (tsc + vite build) npm run lint # ESLint ``` `npm run tauri ` still works for any raw Tauri CLI subcommand. Rust backend builds automatically via Tauri when running `npm run tauri dev/build`. To check Rust compilation independently: ```bash cd src-tauri && cargo check ``` ## Architecture ``` Frontend (React/TS) ──IPC invoke()──> Backend (Rust/Tauri) ──sqlx──> PostgreSQL ``` ### IPC Communication Pattern All frontend-backend communication goes through Tauri's typed IPC. The full pipeline for adding a new backend-exposed feature: 1. **Rust command** — `#[tauri::command]` async fn in `src-tauri/src/commands/.rs` 2. **Register** — add to `invoke_handler` in `src-tauri/src/lib.rs` 3. **TS wrapper** — typed `invoke()` call in `src/lib/tauri.ts` 4. **React hook** — TanStack React Query hook in `src/hooks/use-.ts` 5. **Types** — shared interfaces in `src/types/index.ts` ### Backend (src-tauri/src/) - **`state.rs`** — `AppState`: holds connection pools (`pools`, `ch_clients`), read-only flags, DB flavors (PostgreSQL/Greenplum/ClickHouse), config path, chat-agent caches (`overview_cache`, `tables_by_db_cache`), MCP signal channels, and `ai_settings`. Connections default to read-only. - **`error.rs`** — `TuskError` enum with `thiserror`, serialized as string for IPC. `TuskResult` type alias. - **`utils.rs`** — `escape_ident()` for safe SQL identifier quoting. - **`commands/`** — one module per domain (connections, queries, schema, data, export, management, history, saved_queries, ai, chat, chat_tools, memory, settings). Each function takes `State<'_, AppState>` and returns `TuskResult`. - **`models/`** — serde-serializable structs matching TypeScript types. SQL safety: identifiers use `escape_ident()`, data queries use sqlx parameterized queries. Read-only mode wraps queries in `SET TRANSACTION READ ONLY` + `ROLLBACK`. ### Frontend (src/) - **State**: Zustand store (`stores/app-store.ts`) — connections, active connection/database, tabs, read-only flags, pg version. - **Data fetching**: TanStack React Query hooks in `hooks/` — one hook per domain, wrapping `src/lib/tauri.ts` functions. - **AI chat**: tool-calling architecture — backend commands in `commands/chat.rs` / `commands/chat_tools.rs`, frontend tool definitions in `components/chat/tool-registry.ts`. Chat panel (`ChatPanel.tsx`) replaces the former inline `AiBar`, explain/fix, and chart-preview UIs. - **UI**: shadcn/ui + Radix primitives, Tailwind CSS 4, warm dark "Graphite & Honey" theme (IBM Plex Mono, honey accent). CodeMirror SQL editor with a custom theme from `src/lib/editor-theme.ts`. - **Layout**: resizable panels (sidebar + main area with tab bar). ### Stored Data Connections are persisted to `~/.config/tusk/connections.json`. History and saved queries are stored in similar JSON files in the same config directory. ## Conventions - **Frontend files**: Components `PascalCase.tsx`, hooks `use-kebab-case.ts`, one feature per directory under `components/` - **Path alias**: `@` maps to `./src` - **Rust errors**: always use `TuskError` variants, never `unwrap()` in commands - **New PG types**: add conversion case in `pg_value_to_json()` in `commands/queries.rs` - **AI chat tools**: add Rust-side tool implementation in `commands/chat_tools.rs` and register it in both the backend dispatch (`ChatTool`) and the frontend `components/chat/tool-registry.ts` (schema, display component, card builder).