Overrun#
An iOS app for trimming and managing HealthKit workouts. Built for the common problem of forgetting to stop recording — leaving you with an 8-hour "run" that wrecks your stats.
Features#
Workout List#
- Animated gradient header with icon colors (cyan, lime green, hot pink)
- Workouts grouped by month/year with section headers
- Search by activity type name (case-insensitive)
- Sort by date (default), longest duration, or shortest duration — useful for quickly finding forgot-to-stop workouts or accidental recordings
- Paginated loading (50 at a time) with infinite scroll
- Pull-to-refresh and automatic refresh via HealthKit observer (updates when workouts are added or deleted externally)
Guided Trim Flow#
The workout detail view walks you through a step-by-step process:
- Trim and save — Activity graph showing heart rate, active energy, or distance over time. Range slider to select the portion to keep, with live-updating start/end times, duration, and activity type picker. Explainer text describes what data is preserved and what is lost.
- Upload to Strava (optional) — Upload the trimmed workout directly to Strava via OAuth. Shown after saving, with connect/upload/status inline.
- Remove the original — Instructions to delete the original in Apple Fitness (swipe left → "Delete Workout & Data"), with an "Open Fitness" button. If the original was created by Overrun, it is automatically deleted.
Steps 2 and 3 are visible but dimmed before step 1 is complete, so you know the full process before you begin.
Data-Preserving Trim#
When you trim a workout, Overrun creates a new workout and migrates all associated data within the trimmed time range:
- Heart rate, active/basal energy, distance, step count samples
- Running dynamics — speed, power, stride length, vertical oscillation, ground contact time
- VO2 max and physical effort samples
- Workout effort scores (iOS 18+, user-entered only)
- Workout routes (GPS/location data)
- Workout events (laps, segments, etc.)
- Metadata (indoor/outdoor flag, weather, timezone, METs, etc.)
- Configuration — activity type, indoor/outdoor location type, swimming config
Strava Integration#
- OAuth authentication via the Strava app (falls back to Safari if not installed)
- Direct upload of workouts as TCX files with heart rate and GPS data
- Upload status tracking with polling (uploading → processing → success)
- Connect/disconnect from anywhere in the trim flow
Known Limitations#
HealthKit / Apple Platform#
- Cannot modify workouts in place. HealthKit provides no API to change a workout's start/end dates, samples, or metadata. Trimming must create a new workout and delete the original.
- Cannot delete workouts from other apps. HealthKit only allows an app to delete objects it created. Workouts from Apple Watch, Fitness+, or other apps must be deleted manually by the user (e.g., swipe left in Apple Fitness and choose "Delete Workout & Data").
- Estimated workout effort is not copyable.
estimatedWorkoutEffortScoreis computed by Apple's algorithms and cannot be written by third-party apps. It may or may not be recomputed by the system for the new workout. User-entered effort scores (workoutEffortScore, iOS 18+) are migrated viarelateWorkoutEffortSample. - Physical effort samples are system-generated.
physicalEffortsamples are computed by the OS and cannot be created or associated by third-party apps. - Activity icons in Apple Fitness are source-dependent. Even though we correctly set
locationType(e.g.,.indoor) and carry overHKMetadataKeyIndoorWorkout, Apple Fitness may display a generic icon for workouts from third-party sources instead of the specialized icon (e.g., indoor run icon) shown for Apple Watch workouts. - Apple Fitness may crash when sharing copied workouts. This is a known Apple bug where Fitness crashes when trying to view interval details or share workouts created by third-party apps via
HKWorkoutBuilder. This is not specific to Overrun. - No deep link to specific workouts. Apple provides no URL scheme to open a specific workout in Fitness or Health.
activitytoday://opens Fitness to the activity rings view only. - Splits are not shown for third-party workouts. Since iOS 14, Apple Fitness only displays per-kilometer/mile splits for workouts created by Apple's native Workout app. The underlying distance samples exist in HealthKit, but Fitness will not render the splits table for workouts from any third-party source. There is no API or workaround.
- Running dynamics may not be present. Running speed, power, stride length, vertical oscillation, and ground contact time are only recorded by Apple Watch Series 6+ / Ultra with watchOS 9+. Older devices or non-running workouts will not have these samples.
Strava#
- Strava only imports workouts from Apple's native Workout app. Strava checks the
sourceRevisionbundle identifier on each HealthKit workout and only accepts workouts from Apple's Workout app and Apple Fitness+. Workouts written by any third-party app (including Overrun) are intentionally excluded from Strava's HealthKit import list, regardless of how complete the data is. - This is a Strava policy, not a data issue. The workout data we write is fully valid and appears correctly in Apple Health and Apple Fitness.
- Direct upload works. Overrun bypasses the HealthKit import limitation by uploading directly to Strava's API via OAuth + TCX file upload.
Requirements#
- iOS 17+
- Xcode 15+
- HealthKit entitlement
Building#
Open WorkoutEditor.xcodeproj in Xcode and run on a device or simulator. The app requires HealthKit authorization to read and write workouts and associated samples.
Strava Setup#
- Register an API application at strava.com/settings/api
- Set the Authorization Callback Domain to
localhost - Copy
Secrets.xcconfig.templatetoSecrets.xcconfigand fill in your Client ID and Client Secret Secrets.xcconfigis gitignored and will not be committed
In debug builds, 200 sample workouts are auto-generated on first launch for testing.
Localization#
The app is set up for internationalization using Xcode String Catalogs (.xcstrings). All user-facing strings in SwiftUI views are automatically extracted by Xcode.
Contributing a Translation#
- Open the project in Xcode
- Go to Project Settings → Info → Localizations and add your language
- Xcode will create localized entries in
Localizable.xcstringsandInfoPlist.xcstrings - Open
Localizable.xcstringsin Xcode's String Catalog editor and translate each string InfoPlist.xcstringscontains the app name and HealthKit usage descriptions — translate those too- Activity type names (Running, Cycling, etc.) and all step/button labels are included in the catalog
Files#
WorkoutEditor/Localizable.xcstrings— all app UI stringsWorkoutEditor/InfoPlist.xcstrings— Info.plist strings (app name, permission descriptions)