# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Build & Test Commands ```bash # Build xcodebuild -project PlantGuide.xcodeproj -scheme PlantGuide -configuration Debug # Run all tests xcodebuild test -project PlantGuide.xcodeproj -scheme PlantGuide -destination 'platform=iOS Simulator,name=iPhone 17' # Run a single test class xcodebuild test -project PlantGuide.xcodeproj -scheme PlantGuide -destination 'platform=iOS Simulator,name=iPhone 17' -only-testing:PlantGuideTests/HybridIdentificationUseCaseTests # Run a single test method xcodebuild test -project PlantGuide.xcodeproj -scheme PlantGuide -destination 'platform=iOS Simulator,name=iPhone 17' -only-testing:PlantGuideTests/SavePlantUseCaseTests/testSavePlant_Success # Build UI tests only (compile check, no simulator required) xcodebuild build-for-testing -project PlantGuide.xcodeproj -scheme PlantGuide -destination 'platform=iOS Simulator,name=iPhone 17' -quiet # Run all UI tests xcodebuild test -project PlantGuide.xcodeproj -scheme PlantGuide -destination 'platform=iOS Simulator,name=iPhone 17' -only-testing:PlantGuideUITests ``` ## App Structure **Tab Navigation**: Camera | Collection | Today | Settings ### Implemented Features - **Plant Identification** - Camera-based plant ID using on-device ML + PlantNet API fallback - **Plant Collection** - Save identified plants with care schedules - **Plant Rooms/Zones** - Organize plants by room (Kitchen, Living Room, Bedroom, etc.) - **Today View** - Dashboard showing overdue + today's care tasks grouped by room - **Progress Photos** - Capture growth photos with time-lapse playback and photo reminders - **Care Scheduling** - Watering, fertilizing, repotting, pruning, pest control tasks - **Notifications** - Local notifications for care reminders and photo reminders - **CloudKit Sync** - iCloud sync via NSPersistentCloudKitContainer - **Dark Mode** - System-following color scheme with semantic color tokens ## Architecture **Clean Architecture + MVVM** with three main layers: ``` Presentation (SwiftUI Views + ViewModels) ↓ Domain (Use Cases + Entities + Repository Protocols) ↓ Data (Repository Implementations + Data Sources) ``` ### Key Patterns - **Dependency Injection**: `DIContainer` (singleton) provides all dependencies via `LazyService` wrappers - **Use Cases**: Each user action is a separate use case class (e.g., `SavePlantUseCase`, `HybridIdentificationUseCase`) - **Repository Pattern**: Protocols in Domain layer, implementations in Data layer - **Actor-based Concurrency**: `PlantClassificationService`, `NotificationService`, and Core Data background tasks use actors - **ViewModels**: `@MainActor @Observable` classes, created via `DIContainer.makeXxxViewModel()` - **Core Data + CloudKit**: `NSPersistentCloudKitContainer` with async store loading and `waitForStoreLoaded()` pattern ### Data Flow Example ``` CameraView → IdentificationViewModel → HybridIdentificationUseCase → PlantClassificationService (on-device ML) → PlantNetAPIService (online fallback) → IdentificationView (results) ``` ### Directory Structure - `App/` - Entry point, configuration, API keys - `Core/DI/` - DIContainer and LazyService - `Core/DesignSystem/` - Color tokens, animations, appearance management - `Core/Services/` - NotificationService - `Domain/` - Business logic: Entities, UseCases, RepositoryInterfaces - `Data/` - Persistence: CoreData, Repositories, API services, Mappers - `ML/` - Core ML inference service and image preprocessing - `Presentation/` - SwiftUI views, ViewModels, navigation - `Scenes/` - Feature-specific views (Camera, Collection, Today, Settings, ProgressPhotos, Rooms) - `Common/` - Shared components and modifiers ## External Services - **PlantNet API** (`my.plantnet.org`) - Plant identification via image upload (500 free/day) - **Trefle API** (`trefle.io`) - Botanical care data (400K+ species) - **CloudKit** - iCloud sync for plants, rooms, care tasks, and progress photos API keys configured in `App/Configuration/APIKeys.swift` via environment variables. ## ML Model PlantNet-300K ResNet50 for on-device plant classification: - Input: 224x224 RGB image with ImageNet normalization - Output: 1,081 plant species probabilities - Conversion scripts in `scripts/` directory ## Core Data Model Entities (all CloudKit-compatible with optional attributes): - `PlantMO` - Plant records with identification data - `RoomMO` - User-created rooms/zones - `CareScheduleMO` - Care schedule configuration per plant - `CareTaskMO` - Individual care tasks (watering, fertilizing, etc.) - `ProgressPhotoMO` - Progress photos with thumbnails - `IdentificationMO` - Plant identification history - `PlantCareInfoMO` - Cached care information from APIs ## Testing - Unit tests in `PlantGuideTests/` with mock implementations in `Mocks/` - Test fixtures available for `Plant`, `CareTask`, `PlantCareSchedule` - Mock services: `MockPlantCollectionRepository`, `MockNetworkService`, etc. - In-memory Core Data stack for test isolation: `CoreDataStack(inMemory: true)` ### UI Testing UI tests live in `PlantGuideUITests/` using a page-object foundation. See [Docs/XCUITest-Authoring.md](Docs/XCUITest-Authoring.md) for the full guide. **Key patterns:** - Inherit `BaseUITestCase`, not `XCTestCase` - Launch with `launchClean()`, `launchWithMockData()`, or `launchOffline()` - Locate elements via `UITestID.*` identifiers (mirrors `AccessibilityIdentifiers` in app) - Navigate with screen objects: `TabBarScreen`, `CameraScreen`, `CollectionScreen`, `TodayScreen`, `SettingsScreen`, `PlantDetailScreen` - Wait with `waitForExistence(timeout:)`, `waitUntilHittable()`, `waitUntilGone()` -- never `sleep()` - One assertion focus per test method ## Claude GitHub App ### Installation 1. Go to [github.com/apps/claude](https://github.com/apps/claude) 2. Click "Install" and select this repository 3. Grant the requested permissions (read/write for code, issues, and pull requests) 4. Authenticate with your Anthropic account when prompted ### How It Works - The app reads this `CLAUDE.md` file for project context and contribution rules - Claude responds to `@claude` mentions in issues and PRs - No API key configuration needed - authentication is handled through the GitHub App integration ### Triggering Claude - **Issues**: Mention `@claude` in an issue to request implementation help - **PRs**: Mention `@claude` to request code review or changes ## Claude Contribution Rules ### Scope - Work ONLY on the issue explicitly assigned to you. - One issue = one pull request. - Do not refactor unrelated code. - Do not change public APIs unless the issue explicitly says so. ### Safety Rules - Never auto-merge. - Never force-push to main. - Never delete code unless instructed. - Preserve existing behavior unless tests say otherwise. ### iOS Rules - Respect Swift concurrency (MainActor, async/await). - Do not introduce Combine unless already used. - Prefer pure functions for new logic. - No new dependencies without approval. ### Output Expectations Each PR must include: - Clear summary of changes - Files touched (with rationale) - Risks and how to test