{"owner":"kimlimjustin","repo":"xplorer","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# Xplorer\n\nTauri 2.x desktop file manager. React 18 + TypeScript frontend, Rust backend, pnpm monorepo.\n\n## Project structure\n\n- `apps/client/` -- React frontend (Vite + TypeScript + Tailwind CSS)\n- `apps/src-tauri/` -- Rust backend (Tauri 2.x commands + operations)\n- `apps/web/` -- Next.js marketplace server (Prisma, Stripe billing, admin dashboard)\n- `packages/sdk/` -- Internal service layer (`@xplorer/sdk`), wraps Tauri invoke()\n- `packages/extension-sdk/` -- Sandboxed extension SDK (`@xplorer/extension-sdk`)\n- `packages/create-extension/` -- Extension scaffolder CLI\n- `packages/extensions/` -- Built-in extension packages\n- `e2e/` -- Playwright end-to-end tests\n- `infra/` -- Docker Compose for local PostgreSQL\n- `scripts/` -- Extension signing and utility scripts\n\n## Path aliases\n\n- `@/` -> `apps/client/src/`\n- `@xplorer/sdk` -> `packages/sdk/src/index.ts`\n- `@xplorer/extension-sdk` -> `packages/extension-sdk/src/index.ts`\n\n## Commands\n\n```\npnpm install                     # Install deps -- NEVER use npm\npnpm run dev                     # Frontend + Tauri dev server\npnpm run build                   # Production build\nnpx vitest run                   # Frontend unit tests\nnpx vitest run <path>            # Run a single test file\ncd apps/src-tauri && cargo test  # Rust tests\npnpm run lint                    # ESLint\npnpm run lint:fix                # ESLint autofix\npnpm run format                  # Prettier\nnpx tsc --noEmit                 # TypeScript type check\ncd apps/web && pnpm dev          # Marketplace dev server\n```\n\n## Verification\n\nIMPORTANT: After making code changes, always verify by running the relevant subset:\n1. `npx tsc --noEmit` -- typecheck passes\n2. `npx vitest run <changed-test>` -- affected tests pass\n3. `pnpm run lint` -- no lint errors\n\nDo NOT run the full test suite unless asked. Prefer running single test files for speed.\n\n## Architecture rules\n\n- **TauriAPI facade**: `apps/client/src/lib/tauri-api.ts` delegates to `@xplorer/sdk`. Add new Tauri commands through SDK services, NEVER call `invoke()` directly from components.\n- **Rust commands**: Register in `apps/src-tauri/src/main.rs`. Logic goes in `apps/src-tauri/src/operations/` modules.\n- **Context menus**: Define in `apps/client/src/lib/context-menu-factory.ts` using `i18n.t()` for labels.\n- **State**: React hooks + localStorage (`xplorer:settings` key). No Redux/Zustand.\n- **Routing**: wouter (not react-router). Protocol URLs: `xplorer://home`, `xplorer://trash`, etc.\n- **Extensions**: Sandboxed, access `window.XplorerSDK`. Use JSX + inline styles + CSS variables in extensions. NEVER use Tailwind inside extensions.\n\n## Code style\n\n- Arrow functions for all new functions and components. Do not use `function` keyword.\n- Files under 1000 lines. Extract hooks/helpers/sub-components when approaching limit.\n- TypeScript strict mode. Use `unknown` with narrowing, not `any`.\n- Prefix unused params with underscore: `_param`.\n- `const` by default; `let` only for reassignment; never `var`.\n- Triple-equals (`===`) always. Exception: `== null` is allowed.\n- PascalCase component filenames. `use-kebab-case.ts` for hooks.\n- Only `console.warn()` and `console.error()` allowed. No `console.log()`.\n\n## i18n\n\n- i18next + react-i18next. Locales: `en`, `zh`, `ja`, `id`.\n- Files: `apps/client/src/locales/{lang}.json`.\n- Components: `const { t } = useTranslation()` then `t('namespace.key')`.\n- Non-React: `import i18n from '@/i18n'` then `i18n.t('key')`.\n- Add new keys to ALL 4 locale files when adding translatable strings.\n\n## Styling\n\n- Tailwind CSS with `--xp-*` CSS variables (defined in `apps/client/src/styles/tokyo-night.css`).\n- Utility classes: `.bg-xp-*`, `.text-xp-*`, `.border-xp-*`.\n- Theme classes on `document.documentElement`: `.theme-glass` (default), `.theme-tokyo-night`, `.theme-dracula`, `.theme-nord`, `.theme-catppuccin`.\n- Default: Xplorer Glass (semi-transparent RGBA + backdrop-filter blur).\n- Toggle via `applyTheme()` in `apps/client/src/lib/utils.ts`.\n\n## Rust conventions\n\n- `chrono` for date/time (not `time` crate).\n- `zip` 0.6 for archives.\n- Guard all Mutex: `.lock().unwrap_or_else(|e| e.into_inner())` to prevent poisoned panics.\n- Do not modify `Cargo.lock` manually.\n- Operation modules in `apps/src-tauri/src/operations/`. Register through `mod.rs`.\n\n## Testing\n\n- Vitest + jsdom. Tests in `apps/client/src/__tests__/`.\n- Setup at `apps/client/src/__tests__/setup.ts` mocks Tauri APIs, lucide-react, wouter, react-i18next.\n- Mock `t()` returns last dot-segment of key: `t('sidebar.home')` -> `\"home\"`.\n- When adding new lucide-react icons to components, add them to the mock in setup.ts.\n\n## Commits\n\n- Do NOT include Co-Authored-By tags.\n- Concise commit messages focused on the \"why\", not the \"what\".\n- Use conventional style: `feat:`, `fix:`, `refactor:`, `test:`, `docs:`, `chore:`.\n\n## Common gotchas\n\n- Windows paths: this runs on Windows. Use forward slashes in JS/TS, but be aware Rust paths use `\\\\`.\n- Tauri v2 uses `@tauri-apps/api` (not `@tauri-apps/api/tauri`). Check imports carefully.\n- The test setup mocks `@tauri-apps/api/core` invoke. If a new Tauri command is added, the mock must handle it.\n- Mutex poisoning in Rust is a real risk in this codebase. Always use the guard pattern above.\n"},"files":{"CLAUDE.md":"# Xplorer\n\nTauri 2.x desktop file manager. React 18 + TypeScript frontend, Rust backend, pnpm monorepo.\n\n## Project structure\n\n- `apps/client/` -- React frontend (Vite + TypeScript + Tailwind CSS)\n- `apps/src-tauri/` -- Rust backend (Tauri 2.x commands + operations)\n- `apps/web/` -- Next.js marketplace server (Prisma, Stripe billing, admin dashboard)\n- `packages/sdk/` -- Internal service layer (`@xplorer/sdk`), wraps Tauri invoke()\n- `packages/extension-sdk/` -- Sandboxed extension SDK (`@xplorer/extension-sdk`)\n- `packages/create-extension/` -- Extension scaffolder CLI\n- `packages/extensions/` -- Built-in extension packages\n- `e2e/` -- Playwright end-to-end tests\n- `infra/` -- Docker Compose for local PostgreSQL\n- `scripts/` -- Extension signing and utility scripts\n\n## Path aliases\n\n- `@/` -> `apps/client/src/`\n- `@xplorer/sdk` -> `packages/sdk/src/index.ts`\n- `@xplorer/extension-sdk` -> `packages/extension-sdk/src/index.ts`\n\n## Commands\n\n```\npnpm install                     # Install deps -- NEVER use npm\npnpm run dev                     # Frontend + Tauri dev server\npnpm run build                   # Production build\nnpx vitest run                   # Frontend unit tests\nnpx vitest run <path>            # Run a single test file\ncd apps/src-tauri && cargo test  # Rust tests\npnpm run lint                    # ESLint\npnpm run lint:fix                # ESLint autofix\npnpm run format                  # Prettier\nnpx tsc --noEmit                 # TypeScript type check\ncd apps/web && pnpm dev          # Marketplace dev server\n```\n\n## Verification\n\nIMPORTANT: After making code changes, always verify by running the relevant subset:\n1. `npx tsc --noEmit` -- typecheck passes\n2. `npx vitest run <changed-test>` -- affected tests pass\n3. `pnpm run lint` -- no lint errors\n\nDo NOT run the full test suite unless asked. Prefer running single test files for speed.\n\n## Architecture rules\n\n- **TauriAPI facade**: `apps/client/src/lib/tauri-api.ts` delegates to `@xplorer/sdk`. Add new Tauri commands through SDK services, NEVER call `invoke()` directly from components.\n- **Rust commands**: Register in `apps/src-tauri/src/main.rs`. Logic goes in `apps/src-tauri/src/operations/` modules.\n- **Context menus**: Define in `apps/client/src/lib/context-menu-factory.ts` using `i18n.t()` for labels.\n- **State**: React hooks + localStorage (`xplorer:settings` key). No Redux/Zustand.\n- **Routing**: wouter (not react-router). Protocol URLs: `xplorer://home`, `xplorer://trash`, etc.\n- **Extensions**: Sandboxed, access `window.XplorerSDK`. Use JSX + inline styles + CSS variables in extensions. NEVER use Tailwind inside extensions.\n\n## Code style\n\n- Arrow functions for all new functions and components. Do not use `function` keyword.\n- Files under 1000 lines. Extract hooks/helpers/sub-components when approaching limit.\n- TypeScript strict mode. Use `unknown` with narrowing, not `any`.\n- Prefix unused params with underscore: `_param`.\n- `const` by default; `let` only for reassignment; never `var`.\n- Triple-equals (`===`) always. Exception: `== null` is allowed.\n- PascalCase component filenames. `use-kebab-case.ts` for hooks.\n- Only `console.warn()` and `console.error()` allowed. No `console.log()`.\n\n## i18n\n\n- i18next + react-i18next. Locales: `en`, `zh`, `ja`, `id`.\n- Files: `apps/client/src/locales/{lang}.json`.\n- Components: `const { t } = useTranslation()` then `t('namespace.key')`.\n- Non-React: `import i18n from '@/i18n'` then `i18n.t('key')`.\n- Add new keys to ALL 4 locale files when adding translatable strings.\n\n## Styling\n\n- Tailwind CSS with `--xp-*` CSS variables (defined in `apps/client/src/styles/tokyo-night.css`).\n- Utility classes: `.bg-xp-*`, `.text-xp-*`, `.border-xp-*`.\n- Theme classes on `document.documentElement`: `.theme-glass` (default), `.theme-tokyo-night`, `.theme-dracula`, `.theme-nord`, `.theme-catppuccin`.\n- Default: Xplorer Glass (semi-transparent RGBA + backdrop-filter blur).\n- Toggle via `applyTheme()` in `apps/client/src/lib/utils.ts`.\n\n## Rust conventions\n\n- `chrono` for date/time (not `time` crate).\n- `zip` 0.6 for archives.\n- Guard all Mutex: `.lock().unwrap_or_else(|e| e.into_inner())` to prevent poisoned panics.\n- Do not modify `Cargo.lock` manually.\n- Operation modules in `apps/src-tauri/src/operations/`. Register through `mod.rs`.\n\n## Testing\n\n- Vitest + jsdom. Tests in `apps/client/src/__tests__/`.\n- Setup at `apps/client/src/__tests__/setup.ts` mocks Tauri APIs, lucide-react, wouter, react-i18next.\n- Mock `t()` returns last dot-segment of key: `t('sidebar.home')` -> `\"home\"`.\n- When adding new lucide-react icons to components, add them to the mock in setup.ts.\n\n## Commits\n\n- Do NOT include Co-Authored-By tags.\n- Concise commit messages focused on the \"why\", not the \"what\".\n- Use conventional style: `feat:`, `fix:`, `refactor:`, `test:`, `docs:`, `chore:`.\n\n## Common gotchas\n\n- Windows paths: this runs on Windows. Use forward slashes in JS/TS, but be aware Rust paths use `\\\\`.\n- Tauri v2 uses `@tauri-apps/api` (not `@tauri-apps/api/tauri`). Check imports carefully.\n- The test setup mocks `@tauri-apps/api/core` invoke. If a new Tauri command is added, the mock must handle it.\n- Mutex poisoning in Rust is a real risk in this codebase. Always use the guard pattern above.\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# Xplorer\n\nTauri 2.x desktop file manager. React 18 + TypeScript frontend, Rust backend, pnpm monorepo.\n\n## Project structure\n\n- `apps/client/` -- React frontend (Vite + TypeScript + Tailwind CSS)\n- `apps/src-tauri/` -- Rust backend (Tauri 2.x commands + operations)\n- `apps/web/` -- Next.js marketplace server (Prisma, Stripe billing, admin dashboard)\n- `packages/sdk/` -- Internal service layer (`@xplorer/sdk`), wraps Tauri invoke()\n- `packages/extension-sdk/` -- Sandboxed extension SDK (`@xplorer/extension-sdk`)\n- `packages/create-extension/` -- Extension scaffolder CLI\n- `packages/extensions/` -- Built-in extension packages\n- `e2e/` -- Playwright end-to-end tests\n- `infra/` -- Docker Compose for local PostgreSQL\n- `scripts/` -- Extension signing and utility scripts\n\n## Path aliases\n\n- `@/` -> `apps/client/src/`\n- `@xplorer/sdk` -> `packages/sdk/src/index.ts`\n- `@xplorer/extension-sdk` -> `packages/extension-sdk/src/index.ts`\n\n## Commands\n\n```\npnpm install                     # Install deps -- NEVER use npm\npnpm run dev                     # Frontend + Tauri dev server\npnpm run build                   # Production build\nnpx vitest run                   # Frontend unit tests\nnpx vitest run <path>            # Run a single test file\ncd apps/src-tauri && cargo test  # Rust tests\npnpm run lint                    # ESLint\npnpm run lint:fix                # ESLint autofix\npnpm run format                  # Prettier\nnpx tsc --noEmit                 # TypeScript type check\ncd apps/web && pnpm dev          # Marketplace dev server\n```\n\n## Verification\n\nIMPORTANT: After making code changes, always verify by running the relevant subset:\n1. `npx tsc --noEmit` -- typecheck passes\n2. `npx vitest run <changed-test>` -- affected tests pass\n3. `pnpm run lint` -- no lint errors\n\nDo NOT run the full test suite unless asked. Prefer running single test files for speed.\n\n## Architecture rules\n\n- **TauriAPI facade**: `apps/client/src/lib/tauri-api.ts` delegates to `@xplorer/sdk`. Add new Tauri commands through SDK services, NEVER call `invoke()` directly from components.\n- **Rust commands**: Register in `apps/src-tauri/src/main.rs`. Logic goes in `apps/src-tauri/src/operations/` modules.\n- **Context menus**: Define in `apps/client/src/lib/context-menu-factory.ts` using `i18n.t()` for labels.\n- **State**: React hooks + localStorage (`xplorer:settings` key). No Redux/Zustand.\n- **Routing**: wouter (not react-router). Protocol URLs: `xplorer://home`, `xplorer://trash`, etc.\n- **Extensions**: Sandboxed, access `window.XplorerSDK`. Use JSX + inline styles + CSS variables in extensions. NEVER use Tailwind inside extensions.\n\n## Code style\n\n- Arrow functions for all new functions and components. Do not use `function` keyword.\n- Files under 1000 lines. Extract hooks/helpers/sub-components when approaching limit.\n- TypeScript strict mode. Use `unknown` with narrowing, not `any`.\n- Prefix unused params with underscore: `_param`.\n- `const` by default; `let` only for reassignment; never `var`.\n- Triple-equals (`===`) always. Exception: `== null` is allowed.\n- PascalCase component filenames. `use-kebab-case.ts` for hooks.\n- Only `console.warn()` and `console.error()` allowed. No `console.log()`.\n\n## i18n\n\n- i18next + react-i18next. Locales: `en`, `zh`, `ja`, `id`.\n- Files: `apps/client/src/locales/{lang}.json`.\n- Components: `const { t } = useTranslation()` then `t('namespace.key')`.\n- Non-React: `import i18n from '@/i18n'` then `i18n.t('key')`.\n- Add new keys to ALL 4 locale files when adding translatable strings.\n\n## Styling\n\n- Tailwind CSS with `--xp-*` CSS variables (defined in `apps/client/src/styles/tokyo-night.css`).\n- Utility classes: `.bg-xp-*`, `.text-xp-*`, `.border-xp-*`.\n- Theme classes on `document.documentElement`: `.theme-glass` (default), `.theme-tokyo-night`, `.theme-dracula`, `.theme-nord`, `.theme-catppuccin`.\n- Default: Xplorer Glass (semi-transparent RGBA + backdrop-filter blur).\n- Toggle via `applyTheme()` in `apps/client/src/lib/utils.ts`.\n\n## Rust conventions\n\n- `chrono` for date/time (not `time` crate).\n- `zip` 0.6 for archives.\n- Guard all Mutex: `.lock().unwrap_or_else(|e| e.into_inner())` to prevent poisoned panics.\n- Do not modify `Cargo.lock` manually.\n- Operation modules in `apps/src-tauri/src/operations/`. Register through `mod.rs`.\n\n## Testing\n\n- Vitest + jsdom. Tests in `apps/client/src/__tests__/`.\n- Setup at `apps/client/src/__tests__/setup.ts` mocks Tauri APIs, lucide-react, wouter, react-i18next.\n- Mock `t()` returns last dot-segment of key: `t('sidebar.home')` -> `\"home\"`.\n- When adding new lucide-react icons to components, add them to the mock in setup.ts.\n\n## Commits\n\n- Do NOT include Co-Authored-By tags.\n- Concise commit messages focused on the \"why\", not the \"what\".\n- Use conventional style: `feat:`, `fix:`, `refactor:`, `test:`, `docs:`, `chore:`.\n\n## Common gotchas\n\n- Windows paths: this runs on Windows. Use forward slashes in JS/TS, but be aware Rust paths use `\\\\`.\n- Tauri v2 uses `@tauri-apps/api` (not `@tauri-apps/api/tauri`). Check imports carefully.\n- The test setup mocks `@tauri-apps/api/core` invoke. If a new Tauri command is added, the mock must handle it.\n- Mutex poisoning in Rust is a real risk in this codebase. Always use the guard pattern above.\n","category":"root","tokens":1317}]}