This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
CodeNest is a cross-platform desktop application for managing local project directories. Built with Tauri 2.x (Rust backend) + Vue 3 (frontend), it helps developers centralize scattered projects with features like language analysis, IDE launching, project scanning, and WebDAV sync.
# Install dependencies
pnpm install
# Start development server (runs both Tauri and Vue dev servers)
pnpm dev
# Run all checks (lint, typecheck, tests)
pnpm check
# Linting
pnpm lint # Check for issues
pnpm lint:fix # Auto-fix issues
# Type checking
pnpm typecheck # Vue/TypeScript
# Tests
pnpm test # Frontend unit tests (Vitest)
pnpm test:rust # Rust tests
# Build
pnpm build:exe # Build executable only (no installer)
pnpm build # Build with platform installer (CI mode)
pnpm build:vue # Build Vue frontend only- Frontend: Vue 3 (Composition API) + Pinia (state) + Reka UI (components) + UnoCSS (styles) + vue-i18n (i18n)
- Backend: Tauri 2.x (Rust) with custom commands for filesystem, language analysis, project scanning, and system integration
- Build: Vite (frontend bundler), pnpm (package manager)
src/— Vue 3 frontend applicationviews/— Main views (HomeView, ProjectEditorView, SettingsView)stores/— Pinia stores (projectsStore, settingsStore, projectScannerStore, editorLangGroupsStore)services/— Business logic (projectScannerService, languageAnalyzer, licenseDetector)components/— Reusable Vue componentsconstants/— Enums, types, editor configslocales/— i18n translation files (zh-CN, en)desktop/api.ts— Type-safe wrapper for Tauri commands
src-tauri/— Rust backendsrc/lib.rs— Command registrationsrc/*.rs— Command modules (project, scanner, data, webdav, system, etc.)tauri.conf.json— Tauri app configurationCargo.toml— Rust dependencies
tests/— Frontend unit tests (Vitest)
- Frontend state (Pinia stores) loads from localStorage cache immediately for fast startup
- Tauri commands load persistent JSON files from app data directory asynchronously
- Stores sync state to both localStorage (cache) and disk (via Tauri commands)
- Data files stored in OS-specific app data directory with automatic backup on write
Managed by src-tauri/src/data.rs and src/stores/helpers/persistence.ts:
projects.json— Project listsettings.json— User settings (theme, language, IDE paths, scanner config, WebDAV)language-editor-map.json— Language-to-editor mappingsprojects.scanner.json— Scanner cache (scanned paths, project metadata)
WebDAV passwords stored separately in OS secure storage (keyring) when available.
- Root scanning: Recursively scans user-specified directories for projects
- IDE history: Imports from JetBrains config, VS Code/Cursor/Windsurf/Trae state.vscdb, Claude Code/Codex/Gemini CLI history
- Language analysis: Uses linguist-style detection (implemented in
src-tauri/src/analyzer.rs) - Caching: Scans are cached by directory signature (file count, sizes, modification times) to avoid re-analysis
- Implementation:
src-tauri/src/scanner.rs+src/services/projectScannerService.ts
- Launch commands: Configurable per editor with
{project}and{cwd}placeholders - Auto-detection: Rust code detects installed editors on Windows/macOS/Linux
- Terminal mode: Some editors (Neovim, CLI tools) open in terminal instead of GUI
- Default editor per project: Can be set manually or auto-selected by language
- Supported editors: JetBrains IDEs, VS Code, Cursor, Windsurf, Trae, Zed, Sublime Text, Neovim, Claude Code, Codex CLI, Gemini CLI, Android Studio, Visual Studio
- Implementation:
src-tauri/src/project.rs(detection/launch) +src/constants/codeEditor.ts(editor metadata)
- Analyzes project files to determine language distribution
- Prioritizes programming languages > markup > data > prose
- Detects main language and generates percentage breakdown
- Implementation:
src-tauri/src/analyzer.rs+ linguist data insrc/types/linguist.ts
- Scans project root for LICENSE*/COPYING* files
- Detects common licenses (MIT, Apache 2.0, GPL-3.0, GPL-2.0, BSD, ISC, Mozilla, etc.)
- Uses keyword matching with scoring
- Implementation:
src/services/licenseDetector.ts+src-tauri/src/project.rs::read_project_license
- Manual upload/download of settings and project list to WebDAV server
- Creates local backup before download
- Preserves local WebDAV credentials (not synced to remote)
- Implementation:
src-tauri/src/webdav.rs
- Single File Components with
<script lang="ts" setup>(Composition API) - Auto-imports: Vue APIs, Pinia stores via
unplugin-auto-import - Path alias:
~/resolves tosrc/ - Component size limit: Files over ~200 lines should be refactored into smaller modules
- Component organization: Views use a
components/subdirectory for view-specific components, with ashared/folder for reusable sub-components
When refactoring large view components (like HomeView, ProjectEditorView):
- Extract shared components first (bottom-up): Create small, reusable components in
shared/folder - Then extract view-specific components: List items, cards, sections that use the shared components
- Finally extract container components: View containers that compose the smaller components
- Main view becomes orchestrator: Keep only composables integration, global state, lifecycle hooks, and layout
Example structure (HomeView refactored from 2,142 → 1,045 lines):
views/HomeView/
├── HomeView.vue (main container ~1000 lines)
├── components/ (view-specific components)
│ ├── HomeHeader.vue
│ ├── HomeFilterBar.vue
│ ├── ProjectListView.vue
│ ├── ProjectListItem.vue
│ ├── ProjectGridView.vue
│ ├── ProjectCard.vue
│ └── shared/ (reusable sub-components)
│ ├── ProjectActions.vue
│ ├── ProjectHeader.vue
│ ├── ProjectMeta.vue
│ └── ProjectEditorChip.vue
└── composables/ (logic, keep unchanged during refactor)
- Pinia stores follow pattern: reactive state + computed + async load/save
- Dual persistence: localStorage (cache) + Tauri commands (disk)
- Load sequence: hydrate from cache → load from disk → save sanitized data
- Normalization: Path normalization for cross-platform consistency (Windows verbatim prefix stripping, case handling)
- UnoCSS with custom shortcuts and presets (Wind3, attributify, icons, typography)
- Attributify mode preferred: Use
flex="~ items-center gap-3"instead ofclass="flex items-center gap-3" - Minimize CSS classes: Only use class names for component-specific identifiers
- SCSS usage: Reserve for complex scenarios only (animations, transitions, pseudo-elements, media queries, deep selectors)
- Custom icons via
presetIconsandsrc/assets/icons.json - Theme system: Light/dark/system with custom accent colors
- Shortcuts defined in
unocss.config.ts
Styling example:
<template>
<!-- Good: UnoCSS attributify -->
<div
flex="~ col gap-3"
p="x-4 y-3"
bg="white dark:gray-9"
border="1 solid gray-3 rounded-2"
class="project-card"
/>
</template>
<style lang="scss" scoped>
// Only for complex logic
.project-card {
transition: all 180ms ease;
&:hover {
@apply shadow-$shadow-surface-hover;
transform: translateY(-1px);
}
}
</style>- vue-i18n with Simplified Chinese (zh-CN) and English (en)
- Translation files:
src/locales/ - Manual maintenance required: Do NOT use i18n Ally extension (causes placement issues)
- All commands registered in
src-tauri/src/lib.rs::run() - Commands organized by module (project, scanner, data, system, etc.)
- Use
#[tauri::command]attribute - Return
Result<T, String>or custom result types withsuccess: boolfield
- Atomic writes: Write to
.tmp→ validate → backup original → replace - Backup recovery: If write fails, restore from
.bak - JSON validation: Parse before write, parse after write
- Implementation:
src-tauri/src/data.rs::write_data_file_safely
- Cross-platform: Use
Path/PathBuffromstd::path - Display paths: Strip Windows verbatim prefix (
\\?\) for display - Normalization: Lowercase on Windows, preserve case on Unix for comparison
- Async runtime: Use
tauri::async_runtime::spawn_blockingfor CPU-bound work - Project existence checks: Run concurrently with limit (12 concurrent checks)
- Framework: Vitest
- Test files:
tests/*.test.ts - Run:
pnpm test - Coverage: License detection, store persistence, locale key validation
- Framework: Standard Rust
#[test]+#[cfg(test)] - Test files: Inline in source files (e.g.,
src-tauri/src/data.rs) - Run:
pnpm test:rustorcargo test --manifest-path src-tauri/Cargo.toml
- Follow Angular commit conventions (feat:, fix:, docs:, style:, refactor:, test:, chore:, perf:, ci:)
- Branch strategy:
mainfor stable releases, temporary branchesfeat/,fix/,doc/ - No interactive git flags (
git rebase -i,git add -i) in this environment
- Platform differences: macOS uses native title bar, Windows/Linux use custom decorations
- Pre-commit hook: Runs
pnpm lint-stagedto lint all changed files - Build optimization: Release builds use
opt-level = "z", LTO, strip for smaller binaries - i18n maintenance: Do NOT use i18n Ally extension, manually maintain translation files
- WebDAV password: Stored in OS keyring when available, falls back to settings.json for unsupported systems
- Code size limit: Files over a few hundred lines must be refactored into smaller modules (see Component Refactoring Pattern)
- Component architecture: Props down, events up; use shared components for reusability
- Performance priority: Lower memory is wanted, but never at the cost of runtime performance