This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Optimizely Flutter SDK - Cross-platform plugin wrapping native Optimizely SDKs (iOS, Android) for A/B testing, feature flags, CMAB, and ODP integration.
Main Branch: master
# Setup
flutter pub get
# Testing
flutter test # All tests
flutter test test/cmab_test.dart # Specific test
flutter test --coverage # With coverage
# Linting
flutter analyze
# Run example app
cd example && flutter runDart API (OptimizelyFlutterSdk)
↓
Wrapper (OptimizelyClientWrapper) + MethodChannel
↓
Native Plugins (Swift/Java)
↓
Native Optimizely SDKs (check Package.swift/build.gradle for current versions)
1. Response Object Pattern
- ALL methods return
BaseResponsederivatives (never throw exceptions) - Check
successboolean andreasonstring for errors
2. Multi-Instance State Management
- SDK instances tracked by
sdkKey - User contexts:
sdkKey → userContextId → context - Notification listeners:
sdkKey → listenerId → callback - Call
close()for cleanup
3. Platform-Specific Type Encoding (CRITICAL)
- iOS: Attributes need type metadata:
{"value": 123, "type": "int"} - Android: Direct primitives:
{"attribute": 123} - Conversion in
Utils.convertToTypedMap()(lib/src/utils/utils.dart) - Test override:
forceIOSFormatparameter
4. Dual MethodChannel Architecture
optimizely_flutter_sdk- Main API operationsoptimizely_flutter_sdk_logger- Native → Dart log forwarding
- Add data models in
lib/src/data_objects/if needed - Update
lib/src/optimizely_client_wrapper.dartwith MethodChannel call - Android: Add case in
OptimizelyFlutterClient.java, parse args, call native SDK - iOS: Add case in
SwiftOptimizelyFlutterSdkPlugin.swift, parse args, call native SDK - Handle type conversions (iOS requires metadata wrapping)
- Write tests in
test/ - Update public API in
lib/optimizely_flutter_sdk.dart
Three locations must stay synchronized (SDK version):
pubspec.yaml→version: X.Y.Zlib/package_info.dart→version = 'X.Y.Z'README.md→ Installation example^X.Y.Z
Native iOS SDK version lives in one place (SPM only):
ios/optimizely_flutter_sdk/Package.swift→.package(url: "...swift-sdk.git", exact: "A.B.C")
Simply ask Claude to create a release:
"Create release 3.4.2 with ticket FSSDK-12345"
"Bump patch version with ticket FSSDK-12345"
Claude will execute the full workflow:
- ✅ Pre-flight checks (master branch, clean working tree)
- ✅ Create release branch (prepare-X.Y.Z)
- ✅ Update all 3 version files (pubspec.yaml, package_info.dart, README.md)
- ✅ Generate CHANGELOG.md template
- ✅ Commit and push
- ✅ Create PR
release.ymlvalidates the version (pubspec.yaml, package_info.dart, README.md, CHANGELOG section) on the PR, and on merge pushes tagvX.Y.Zpublish.ymlruns on the tag: publishes to pub.dev (waits for approval in thepub.devenvironment), then creates the GitHub release from the CHANGELOG section- Versions with a
-suffix (e.g.4.0.0-rc.1) are released as prereleases - If a workflow fails, use "Re-run failed jobs" in the Actions tab. A failed GitHub release step is retried without publishing again
# 1. Create release branch
git checkout -b prepare-X.Y.Z
# 2. Update versions (pubspec.yaml, package_info.dart, README.md)
# 3. Update CHANGELOG.md (add release notes at top)
# 4. Commit with standard format
git commit -m "chore: prepare for release X.Y.Z
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
# 5. Push and create PR
git push -u origin prepare-X.Y.Z
gh pr create --title "[FSSDK-XXXXX] prepare for release X.Y.Z"
# 6. After merge, the tag, pub.dev publish and GitHub release are automated (see above)## X.Y.Z
Month Day, Year
### New Features / Enhancements / Bug Fixes
* Description ([#PR](link))All code changes MUST comply with the project constitution at .specify/memory/constitution.md. This document defines the team's non-negotiable standards for correctness, testing, security, observability, naming, PR discipline, and architectural simplicity.
When to consult the constitution:
- Before implementing any feature (large or small)
- During code reviews to validate adherence
- When making architectural decisions
- For day-to-day changes that don't require full SDD workflow
Read the constitution before proposing changes.
Follow Angular guidelines:
feat:- New featuresfix:- Bug fixeschore:- Maintenancedocs:- Documentationrefactor:- Code restructuringtest:- Test additions
- Never commit directly to
master - Feature branches:
feature/name,prepare-X.Y.Z,fix/name - All PRs target
masterbranch
- Tests required for all code changes
- All CI checks must pass (5 parallel workflows)
- Apache 2.0 license header on new files
- Sign CLA (Contributor License Agreement)
unit_test_coverage(macOS) - Dart tests + Coveralls uploadbuild_test_android(Ubuntu) - Android build validationbuild_test_ios(macOS) - iOS build validationintegration_android_tests(Ubuntu) - Triggersoptimizely-flutter-testapprepointegration_ios_tests(Ubuntu) - Triggersoptimizely-flutter-testapprepo
Flutter/Dart:
- Dart: >=2.16.2 <4.0.0
- Flutter: >=3.44.0
Android:
- minSdk: 21 (Android 5.0)
- compileSdk: 35 (Android 15)
- Kotlin: 2.1.0
- Native SDK: android-sdk (see android/build.gradle for current version)
iOS:
- Minimum: iOS 15.0
- Swift: 5.0
- Native SDK: OptimizelySwiftSDK (see ios/optimizely_flutter_sdk/Package.swift for current version)
Dart Layer:
lib/optimizely_flutter_sdk.dart- Public API (initialize, decide, track)lib/src/optimizely_client_wrapper.dart- Platform bridge (545 LOC)lib/src/user_context/optimizely_user_context.dart- User context operationslib/src/data_objects/- 21 response/request models
Android Layer:
android/src/.../OptimizelyFlutterSdkPlugin.java- MethodChannel handlerandroid/src/.../OptimizelyFlutterClient.java- Core client wrapper (921 LOC)android/build.gradle- Dependencies & SDK versions
iOS Layer:
ios/optimizely_flutter_sdk/Sources/optimizely_flutter_sdk/SwiftOptimizelyFlutterSdkPlugin.swift- Plugin implementation (786 LOC)ios/optimizely_flutter_sdk/Sources/optimizely_flutter_sdk/OptimizelyFlutterLogger.swift- Logger bridge (main-thread dispatch)ios/optimizely_flutter_sdk/Package.swift- SPM dependencies
For additional context about technologies to be used, project structure, shell commands, and other important information, read the current plan