Control your AI coding sessions from your phone
Features • Installation • Development • Architecture • Security
ForkOff is a React Native mobile app that connects to Claude Code running on your laptop via the ForkOff CLI. Monitor sessions, approve tool use, and track usage — all from your phone.
Open Source — MIT licensed. Contributions welcome!
Open Beta — Join the iOS TestFlight
- Monitor live sessions — See Claude Code output as it streams in real-time
- Interactive approvals — Approve or deny file edits, bash commands, and other tool use
- Configurable permissions — Auto-approve safe tools, require approval for destructive ones
- Send prompts — Start new sessions or continue existing ones from mobile
- Pair via QR code — Scan to link your laptop in seconds
- Multiple devices — Connect several machines, switch between them
- Device status — See which devices are online in real-time
- Project hub — Browse projects, view CLAUDE.md, launch quick actions
- Token usage tracking — Daily, weekly, monthly breakdowns
- Multi-device aggregation — Stats summed across all connected CLIs
- Usage streaks — Track your coding consistency
- Real-time updates — Token counts update as you code
- Unlock badges for usage milestones
- Showcase achievements on your profile
| Technology | Purpose |
|---|---|
| React Native 0.81 | Cross-platform mobile framework |
| Expo SDK 54 | Development, builds, OTA updates |
| Expo Router | File-based navigation (typed routes) |
| Zustand | State management |
| TanStack Query | Server state & caching |
| Socket.io | Real-time communication |
| TweetNaCl | End-to-end encryption (X25519, XSalsa20-Poly1305) |
| Supabase | Authentication |
| NativeWind | Tailwind CSS for React Native |
| PostHog | Product analytics |
| Sentry | Error tracking |
- Node.js 18+
- iOS Simulator (Mac) or Android Emulator
- ForkOff CLI (
npm install -g forkoff)
git clone https://github.com/Forkoff-app/forkoff-react-native.git
cd forkoff-react-native
npm installCreate a .env file:
# Required
EXPO_PUBLIC_WS_URL=wss://api.forkoff.app # or ws://YOUR_IP:3000 for local dev
EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
# Optional
EXPO_PUBLIC_POSTHOG_API_KEY=your-posthog-key
EXPO_PUBLIC_SENTRY_DSN=your-sentry-dsnnpx expo start # Start dev server
npx expo start --ios # iOS simulator
npx expo start --android # Android emulatorapp/
├── (onboarding)/ # First-run setup flow
├── (tabs)/ # Bottom tab navigation
│ ├── projects.tsx # Projects list
│ ├── devices.tsx # Paired devices
│ ├── analytics.tsx # Usage analytics
│ └── settings.tsx # Settings
├── claude/
│ └── session/[sessionKey].tsx # Live session view (streaming, approvals)
├── device/
│ ├── [id].tsx # Device detail
│ └── pair.tsx # QR pairing
├── project-hub.tsx # Per-project command center
├── achievements/ # Achievement badges
├── settings/
│ └── permissions.tsx # Tool permission rules
└── _layout.tsx # Root layout
components/
├── ui/ # Reusable UI (AlertModal, OfflineBanner, etc.)
├── claude/ # Session components (PermissionQueue, ToolUseBlock)
│ └── tools/ # Tool renderers (Bash, Edit, Read, Write, etc.)
├── analytics/ # Charts & summary cards
├── achievements/ # Achievement badges & unlock modal
└── tutorial/ # Guided tutorial overlay
stores/
├── claude.store.ts # Claude sessions per device
├── device.store.ts # Paired devices & status
├── approval.store.ts # Pending approval requests
├── analytics.store.ts # Token usage & multi-device aggregation
├── connection.store.ts # WebSocket connection state
├── permission-rules.store.ts # Tool approval rules
└── ...
services/
├── websocket.service.ts # Socket.io client, E2EE, event routing
├── crypto/ # E2EE implementation (NaCl)
│ ├── e2eeManager.ts # Key exchange, encryption, TOFU
│ ├── encryption.ts # XSalsa20-Poly1305
│ ├── keyGeneration.ts # X25519 key pairs
│ └── keyStorage.ts # SecureStore persistence
├── api.client.ts # Axios HTTP client
├── notification.service.ts # Push notifications
├── analytics.service.ts # PostHog
└── sentry.service.ts # Error tracking
npx expo start # Dev server
npx expo start --clear # Clear cache and restart
npm test # Run tests
npx tsc --noEmit # Type check
eas build --platform ios # Production build (iOS)
eas build --platform android # Production build (Android)- Zustand stores in
stores/*.store.tswithcreate<State>((set, get) => ({...})) - Module-level WebSocket listeners for global events (analytics sync, achievements)
- AsyncStorage for persistence, SecureStore for cryptographic keys
- Optimistic updates — Messages appear instantly, replaced when server confirms
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Mobile App │<───>│ Relay │<───>│ CLI Tool │
│ (E2EE) │ │ (opaque) │ │ (E2EE) │
└─────────────┘ └─────────────┘ └─────────────┘
The relay server only sees encrypted payloads. All session content, approvals, file contents, and terminal output are end-to-end encrypted between the mobile app and CLI.
The mobile app configures tool permission rules that sync to the CLI:
- User configures rules in Settings > Permissions (which tools auto-approve vs require approval)
- On session takeover, rules sync to CLI via
permission_rules_syncevent - CLI installs a PreToolUse hook into Claude Code's settings
- Hook script reads rules and auto-approves or prompts mobile for approval
- Approval requests appear in a queued modal on mobile with approve/deny controls
All communication between the mobile app and CLI is end-to-end encrypted:
| Layer | Implementation |
|---|---|
| Key exchange | X25519 ECDH with Ed25519 identity signatures |
| Encryption | XSalsa20-Poly1305 authenticated encryption (NaCl) |
| Identity | TOFU (Trust On First Use) with key pinning |
| Replay protection | Per-peer monotonic message counters |
| Key storage | Expo SecureStore (iOS Keychain / Android Keystore) |
| Enforcement | Sensitive events never sent in plaintext; enforced at both ends |
| Validation | Encrypted payloads validated for structure before dispatch |
E2EE is established automatically on device pairing. No configuration required.
npm install -g eas-cli
eas login
eas build:configure
eas build --platform allProduction builds use EAS Secrets:
eas secret:create --name EXPO_PUBLIC_SUPABASE_URL --value "https://..."
eas secret:create --name EXPO_PUBLIC_SUPABASE_ANON_KEY --value "..."- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit changes (
git commit -m 'Add my feature') - Push to branch (
git push origin feature/my-feature) - Open a Pull Request
- ForkOff CLI — CLI tool (
npm install -g forkoff) - ForkOff Website — Landing page
