This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Snips is a macOS-native snippet management tool built with Tauri 2.x, designed for building LLM prompts from reusable text snippets. It provides:
- Quick snippet capture via global shortcuts
- Fast full-text search across snippets
- Multi-select functionality for combining snippets
- Usage analytics for search ranking
- Menubar-only presence (no dock icon)
npm run tauri dev # Run app in development mode with hot-reload
npm run dev # Start Vite dev server only (for frontend testing)npm run tauri build # Build complete production application
npm run build # Build frontend onlynpm run check-all # Run ALL checks (format, lint, type-check) - use before commits
npm run format # Format TypeScript/React code with Prettier
npm run format:check # Check formatting without modifying files
npm run lint # Lint TypeScript/React code with ESLint
npm run lint:fix # Auto-fix linting issues
npm run type-check # Check TypeScript typesnpm run test # Run tests in watch mode
npm run test:coverage # Run tests with coverage report
npm run test:ui # Open Vitest UI for interactive testingcargo fmt # Format Rust code
cargo fmt -- --check # Check Rust formatting
cargo clippy -- -D warnings # Lint Rust code (warnings treated as errors)
cargo test # Run Rust tests- Entry point:
src-tauri/src/main.rscallssrc-tauri/src/lib.rs - Structure: Commands → Services → Database
commands/: Tauri command handlers (IPC layer)services/: Business logic (database, search, analytics)models/: Data structures (Snippet, Tag, Analytics)utils/: Shared utilities and error handling
- Entry point:
src/main.tsx→src/App.tsx - State: Zustand stores in
src/stores/ - Components: React components in
src/components/ui/: Reusable UI components (Button, Input, Card)- Feature components: SearchOverlay, QuickAddDialog, ManagementWindow
- Hooks: Custom React hooks in
src/hooks/ - Utils: Helper functions in
src/lib/ - Types: TypeScript type definitions in
src/types/
- Storage: Local SQLite database with FTS5 full-text search
- Schema: snippets, tags, snippet_tags (many-to-many), analytics, snippets_fts (FTS5 virtual table)
- Search: FTS5 enables fast full-text search with relevance ranking
- Analytics: Usage tracking for frequency-based search ranking
- NO
unwrap()orexpect()in production code - use proper error handling with?operator - NO
panic!()unless truly unrecoverable - MUST handle all
ResultandOptiontypes explicitly - MUST use parameterized queries (via tauri-plugin-sql) to prevent SQL injection
- Use newtype pattern for strong typing (e.g.,
SnippetId(i64)instead ofi64) - Add
#[derive(Debug, Clone)]on all data structures - Implement
thiserror::Errorfor custom errors
- NO
anytype (useunknownif needed) - NO
console.log(useconsole.warnorconsole.error) - NO unused variables (prefix with
_if intentional) - MUST use
constby default,letonly when reassignment needed - MUST type all function parameters and return values
- MUST order imports: external → internal → relative
- Keep functions under 50 lines (split if larger)
- Keep components under 300 lines (split if larger)
- Avoid type assertions (
as) unless absolutely necessary
Both TypeScript and Vite are configured with path aliases:
import { Button } from '@/components/ui/Button'; // Not '../../../components/ui/Button'
import { useSnippets } from '@/hooks/useSnippets';
import { formatDate } from '@/lib/formatters';- TypeScript: Single quotes, semicolons, trailing commas, 100 char line width
- Rust: 4 spaces, 100 char line width, idiomatic formatting
- ALWAYS run formatters before committing
- Test files colocated with implementation:
Component.tsx→Component.test.tsx - Use Vitest + React Testing Library for frontend tests
- Mock Tauri API calls in tests using
vi.mock('@tauri-apps/api/tauri') - Target 70%+ coverage for TypeScript, 80%+ for Rust
- Test error states, loading states, and user interactions
- Ensure Rust 1.82+ is installed (Tauri dependency):
rustc --version - Install dependencies:
npm install - Verify setup works:
npm run tauri dev
- Run
npm run check-allto verify all quality checks pass - Ensure all tests pass:
npm run test - Use Conventional Commits format:
feat(scope): description- New featuresfix(scope): description- Bug fixesrefactor(scope): description- Code refactoringtest(scope): description- Adding/updating testsdocs(scope): description- Documentation changeschore(scope): description- Maintenance tasks
The project follows a phased approach (see TECH_DESIGN.md):
- Phase 1 (Foundation): Database, CRUD operations, basic React structure
- Phase 2 (Core UX): Global shortcuts, search overlay, multi-select, clipboard
- Phase 3 (Polish): Analytics, management UI, performance optimization
- Rust 1.82+ required: Tauri dependencies mandate this version
- SQLite FTS5: Built-in full-text search, no external dependencies
- Zustand: Lightweight state management, better TypeScript support than Redux
- Local-first: All data stored locally in SQLite for speed and offline capability
- Menubar app: No dock icon, persistent menubar presence with badge count
- Define command in
src-tauri/src/commands/(e.g.,snippet_commands.rs) - Register in
src-tauri/src/lib.rsviagenerate_handler! - Create TypeScript types in
src/types/ - Call from frontend using
invoke('command_name', { params }) - Add tests for both Rust and TypeScript sides
- Create in appropriate directory (e.g.,
src/components/SearchOverlay/) - Include component file, test file, and
index.tsbarrel export - Use TypeScript for props interface
- Implement keyboard navigation and accessibility (ARIA labels)
- Add tests using React Testing Library
# Frontend
npm run test -- src/components/SearchOverlay.test.tsx
# Backend
cargo test --test snippet_tests- MUST support keyboard navigation (Tab, Arrow keys, Enter, Escape)
- MUST provide ARIA labels for interactive elements
- MUST maintain 4.5:1 contrast ratio for text
- MUST provide focus indicators
- MUST use semantic HTML elements
- Validate all user input before database operations
- Use parameterized queries (handled by tauri-plugin-sql)
- Sanitize HTML if rendering user content
- Limit input sizes to prevent DoS
- Never use
eval()ordangerouslySetInnerHTMLwithout sanitization
- Search response: <100ms (99th percentile)
- App startup: <1 second cold start
- Window open: <50ms to visible
- Memory usage: <100MB resident set size
For detailed information, refer to:
- README.md - Project overview, setup, and contribution guide
- VISION.md - Product vision, MVP features, and future roadmap
- TECH_DESIGN.md - Complete technical architecture and implementation plan
- STANDARDS.md - Comprehensive coding standards and best practices