Free · Open Source · Local-First · No Subscriptions
A workout tracker for iPhone, Apple Watch, and Android.
Skulpt is a workout planner and training log built with React Native, Expo, SQLite, and native platform integrations. Its working database lives on the device, so planning a workout, logging sets, and reviewing history do not depend on a server connection.
Sync is an optional layer over that local database. The App Store and Google Play builds use the Skulpt-operated SyncLayer. A custom build can connect to another compatible provider or omit sync entirely.
The repository contains the mobile client that ships through the stores. It is licensed under GPL-3.0.
- Free to use, with no subscription
- Open source under GPL-3.0
- Local-first SQLite storage
- Works offline for the core workout flow
- Optional sync through the Skulpt provider or another compatible implementation
- Apple Watch workout control
- Live Activities and Dynamic Island on supported iPhones
- HealthKit on iOS and Health Connect on Android
The store builds are free and do not require a subscription. They include the Skulpt SyncLayer. Analytics and diagnostics depend on the release configuration, and developers can build the same client without any of these services.
- Workout planning, live logging, and history
- Working, warm-up, drop, failure, time, and distance sets
- Supersets, trisets, and circuits
- Body measurements and charts
- Automatic measurement import from Apple Health or Google Health Connect
- Configurable rest timers with sound and haptics
- Apple Watch workout control and heart-rate zones
- Configurable maximum-heart-rate formulas: Nes, Fox, Tanaka, Inbar, Gulati, Gellish, or manual
- Live Activity and Dynamic Island support on iOS 16.1 and later
- Exercise history, volume, and personal records
- English, Spanish, Hindi, Russian, and Chinese localisations
- Light, dark, and system themes
- Configurable units: kg or lb, km or mi, cm or in, and Celsius or Fahrenheit
SQLite is the source of truth for the mobile app. Product writes complete locally first. If a sync provider is enabled, eligible changes are then added to sync_queue and sent in the background.
| Build mode | Configuration | Behaviour |
|---|---|---|
| Skulpt store build | Skulpt provider configured at build time | Local database plus optional cross-device sync |
| Custom provider build | Set EXPO_PUBLIC_SYNC_HOST to a compatible provider |
Local database plus sync through that provider |
| Local-only build | Leave EXPO_PUBLIC_SYNC_HOST unset |
Local database with no authentication, push, or pull through SyncLayer |
Provider selection is currently a build-time setting. The public app does not expose a server URL field in Settings.
SyncLayer is separate from other optional network integrations. PostHog and Sentry each have their own environment variable. Leave those variables unset when building without analytics or diagnostics. See Build a local-only client for the exact configuration and current exercise-catalogue limitation.
Skulpt can copy authorised body measurements from HealthKit or Health Connect into its own measurement table. When SyncLayer is enabled, imported measurements follow the same optional sync path as measurements entered by hand. Skulpt does not copy or upload the complete contents of either health store.
The mobile client talks to a provider through a small HTTP contract:
POST /auth/token
GET /sync
POST /sync
POST /sync sends compacted local changes. GET /sync pulls records changed after the last stored timestamp. The same pull route also distributes the maintained Skulpt exercise catalogue under a separate scope.
The Skulpt-operated service is one implementation. Anyone can implement a compatible server and point a custom build at it with:
EXPO_PUBLIC_SYNC_HOST=https://sync.example.comThe current request and response shapes are documented in Sync provider protocol.
Polish and harden the full workout experience, from planning and logging to reviewing workout history. This is the foundation everything else builds on.
Deep tracking of recovery, readiness, and training load on par with dedicated wearables. Metrics come from Apple Health on iOS and Google Health Connect on Android. Both collect data from connected devices such as Apple Watch, Garmin, Whoop, Oura, and Polar, so Skulpt works with the hardware the user already owns.
A set of composable, privacy-first tools designed for AI agents: each tool computes a specific metric or insight (volume load, recovery score, HRV trend, strain index, etc.) and returns the result without ever exposing the underlying raw data to an external system. Source data flows from the user's wearables into Apple Health / Google Health Connect, and only derived, aggregated values leave the device.
An open, vendor-neutral protocol for connecting AI agents to Skulpt. An agent can query the tool layer, reason over computed metrics, and surface personalised recommendations regardless of its model or platform. The protocol is deliberately model-agnostic: it defines a contract rather than an implementation, so it can work with a local on-device model, a self-hosted LLM, or a cloud AI service.
A native interface for managing and interacting with connected agents inside the app. Users will be able to configure agent access, inspect what each agent can see, and have conversations grounded in their training data without leaving Skulpt.
screens, hooks, and native targets
|
v
CRUD and services
|
v
Drizzle ORM + SQLite
|
+------ local queries ------> history, charts, next workout
|
+------ optional queue -----> SyncLayer provider
The main implementation areas are:
| Path | Responsibility |
|---|---|
src/routes/ |
Expo Router entry points and application providers |
src/screens/ |
Product screens |
src/crud/ |
Local database operations and optional queue writes |
src/db/ and drizzle/ |
SQLite schema and migrations |
src/api/ and src/sync/ |
SyncLayer transport and sync engine |
src/services/ |
Health, authentication, diagnostics, and product services |
modules/ |
Native Expo modules, including Watch connectivity and Live Activities |
targets/watch/ |
SwiftUI watchOS application |
targets/workout-widget/ |
Live Activity and widget target |
Read Architecture for the data flow and platform boundaries.
- Node.js 20 or newer
- Bun 1.3 or newer
- Xcode for iOS development
- Android Studio and the Android SDK for Android development
- EAS CLI for remote device builds and store submissions
Skulpt uses custom native modules. Expo Go cannot run this project; use a native development build.
git clone https://github.com/skulptapp/skulpt.git
cd skulpt
cp .env.local.example .env.local
bun install --frozen-lockfileThe example file uses a development bundle identifier. Set APP_APPLE_TEAM_ID to your own Apple Developer team before building the iOS targets. Contributors do not need Skulpt production credentials.
bun run ios
bun run androidbun run verifyThis runs ESLint, TypeScript, and the Jest suite. The same commands run for pull requests on GitHub. EAS remains the build and store-release system; GitHub Actions does not build or submit the mobile applications.
After changing a Drizzle schema:
bun run db:generateReview and commit the generated migration and metadata. The app applies bundled migrations at startup.
| Command | Purpose |
|---|---|
bun start |
Start the Expo development server |
bun run ios |
Build and run the iOS client locally |
bun run android |
Build and run the Android client locally |
bun run verify |
Run lint, TypeScript, and tests |
bun run lint |
Run Expo ESLint |
bun run typecheck |
Run TypeScript without emitting files |
bun run test |
Run Jest in development mode |
bun run db:generate |
Generate a Drizzle migration |
bun run locale |
Update translation resources |
bun run prebuild |
Regenerate the local iOS project |
The repository includes eas.json.example. Copy it to the ignored eas.json and add account-specific values before using EAS.
| Command | Purpose |
|---|---|
bun run build:ios |
iOS development build through EAS |
bun run build:android |
Android development build through EAS |
bun run release:ios |
Production iOS build and submission through EAS |
bun run release:android |
Production Android build and submission through EAS |
bun run update:all |
Production OTA update and source-map upload |
Maintainer steps are documented in Release process.
You can contribute code, tests, documentation, translations, accessibility fixes, or reproducible bug reports. Start with CONTRIBUTING.md.
- Use GitHub Issues for reproducible bugs and scoped work.
- Use GitHub Discussions for questions, ideas, and architecture proposals.
- Follow SECURITY.md for private vulnerability reports.
- Follow SUPPORT.md for app support and private data questions.
- Architecture
- Build a local-only client
- Sync provider protocol
- Release process
- Contributing
- Governance
- Security
- Support
- Code of Conduct
Skulpt is licensed under the GNU General Public License v3.0.