Adds competitive analysis document comparing PlantGuide against major plant identification apps (PlantIn, PictureThis, Planta, etc.) and CLAUDE.md to help future Claude Code instances navigate the codebase. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
87 lines
3.3 KiB
Markdown
87 lines
3.3 KiB
Markdown
# 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 16'
|
|
|
|
# Run a single test class
|
|
xcodebuild test -project PlantGuide.xcodeproj -scheme PlantGuide -destination 'platform=iOS Simulator,name=iPhone 16' -only-testing:PlantGuideTests/HybridIdentificationUseCaseTests
|
|
|
|
# Run a single test method
|
|
xcodebuild test -project PlantGuide.xcodeproj -scheme PlantGuide -destination 'platform=iOS Simulator,name=iPhone 16' -only-testing:PlantGuideTests/SavePlantUseCaseTests/testSavePlant_Success
|
|
```
|
|
|
|
## 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<T>` 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` and Core Data access use actors for thread safety
|
|
- **ViewModels**: `@MainActor @Observable` classes, created via `DIContainer.makeXxxViewModel()`
|
|
|
|
### 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
|
|
- `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
|
|
|
|
## External Services
|
|
|
|
- **PlantNet API** (`my.plantnet.org`) - Plant identification via image upload (500 free/day)
|
|
- **Trefle API** (`trefle.io`) - Botanical care data (400K+ species)
|
|
- **Local Database** - `Resources/houseplants_list.json` (2,278 species)
|
|
|
|
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
|
|
|
|
## Known Issues
|
|
|
|
See `Docs/ARCHITECTURE_REMEDIATION_PLAN.md` for pre-production fixes:
|
|
- `InMemoryPlantRepository` doesn't conform to `PlantRepositoryProtocol`
|
|
- `CoreDataStack` lazy var initialization isn't thread-safe
|
|
- `DIContainer` uses `unowned self` in closures (crash risk)
|
|
- SwiftData initialized but unused (Core Data is the actual persistence layer)
|
|
|
|
## Testing
|
|
|
|
- Unit tests in `PlantGuideTests/` with mock implementations in `Mocks/`
|
|
- Test fixtures available for `Plant`, `CareTask`, `PlantCareSchedule`
|
|
- Mock services: `MockPlantCollectionRepository`, `MockNetworkService`, etc.
|