A mobile app to monitor your GitHub Copilot usage quota with native home screen widgets for iOS and Android.
- GitHub OAuth Authentication — Secure sign-in via OAuth 2.0 with PKCE, tokens stored in
expo-secure-store - Three Quota Tabs — Dedicated tabs for Premium Requests, Chat, and Completions
- Interactive Pie Chart — Tap to toggle between used and available quota views
- Daily Usage Insights — Budget used per day, budget left per day, and days remaining until reset
- Native Widgets — Home screen widgets for iOS (WidgetKit) and Android (Glance), powered by Voltra
- Dark / Light / System Theme — Appearance preference with automatic system theme support
- Offline-First — React Query persistence via MMKV for cached data when offline
- Pull-to-Refresh — Swipe down on any quota tab to refresh data
- Internationalization — i18n-ready with
i18nextandreact-i18next
- Node.js (LTS — see
.nvmrc) - iOS: Xcode 15+ (for iOS development)
- Android: Android Studio (for Android development)
git clone https://github.com/nearform/copilot-status.git
cd copilot-status
npm installCopy the example file and fill in your credentials:
cp .env.example .envGITHUB_CLIENT_ID=your_github_oauth_client_id
GITHUB_CLIENT_SECRET=your_github_oauth_client_secretTo get these credentials:
- Go to GitHub Developer Settings
- Create a new OAuth App
- Set the callback URL to:
com.nearform.copilotstatus://
For iOS widgets to work, you need to:
- Run
npx expo prebuildto generate the native project - Open the project in Xcode
- Enable the App Groups capability for both the main app and the widget extension
- Use the App Group:
group.com.nearform.copilotstatus
The widget configuration (ID, display name, supported families) is defined in the Voltra plugin section of app.json.
# Development
npx expo start
# iOS (requires Mac)
npx expo run:ios
# Android
npx expo run:android| Command | Description |
|---|---|
npm start |
Start Expo dev server |
npm run lint |
Run ESLint via Expo |
npm run typecheck |
Run TypeScript compiler check |
npm test |
Run Jest tests |
npm run test:watch |
Run Jest in watch mode |
npm run test:coverage |
Run Jest with coverage report |
copilot-status/
├── app/ # Expo Router screens
│ ├── _layout.tsx # Root layout with auth guard
│ ├── settings.tsx # Settings screen
│ ├── (auth)/ # Authentication flow
│ │ └── login.tsx # GitHub OAuth login
│ └── (tabs)/ # Main app tabs
│ ├── _layout.tsx # Tab bar configuration
│ ├── index.tsx # Premium Requests tab
│ ├── chat.tsx # Chat quota tab
│ └── completions.tsx # Completions quota tab
├── components/ # Reusable UI components
│ ├── CachedBanner.tsx # Last-updated timestamp banner
│ ├── CircularProgress.tsx # Interactive pie chart
│ ├── QuotaDisplay.tsx # Quota data display with loading/error states
│ ├── QuotaScreen.tsx # Screen wrapper with header
│ ├── QuotaValues.tsx # Stats cards and chart layout
│ ├── RadioButton.tsx # Themed radio button
│ ├── Separator.tsx # List separator
│ ├── StatsCard.tsx # Statistics card
│ └── settings/ # Settings sub-components
│ ├── SettingsCategory.tsx # Grouped settings section
│ ├── SettingsSection.tsx # Section container
│ └── SettingsVoice.tsx # Label + value row
├── constants/ # App constants
│ └── api.ts # GitHub OAuth endpoints and scopes
├── hooks/ # Custom React hooks
│ └── useGitHub.ts # React Query hooks for user & quota data
├── locales/ # i18n translation files
│ └── en.json # English translations
├── services/ # Business logic
│ ├── api.ts # GitHub Copilot API (via @octokit/rest)
│ ├── auth.ts # OAuth authentication with PKCE
│ ├── i18n.ts # i18next configuration
│ ├── queryClient.ts # React Query client with MMKV persistence
│ └── storage.ts # MMKV storage instance
├── src/
│ └── styles/
│ └── unistyles.ts # Unistyles theme and breakpoint configuration
├── stores/ # State management
│ ├── auth.ts # Authentication state (Zustand)
│ ├── quota.ts # Quota cache clearing
│ ├── secureStorage.ts # Secure token storage (expo-secure-store)
│ └── theme.ts # Theme preference state (Zustand + MMKV)
├── types/ # TypeScript type definitions
│ ├── api.ts # GitHub Copilot API response types
│ └── quota.ts # Quota domain types
├── utils/ # Utility functions
│ ├── colorUtils.ts # Color-by-percentage helpers
│ ├── dateTimeUtils.ts # Date formatting and daily quota insight
│ └── numberUtils.ts # Number formatting
├── widgets/ # Home screen widgets (Voltra)
│ ├── index.ts # Widget exports
│ ├── VoltraCopilotWidget.tsx # iOS and Android widget components
│ ├── voltraWidgetService.tsx # Widget update/clear logic
│ └── widgetStyles.ts # Widget theme-aware styles
└── __tests__/ # Test suites
- Framework: Expo SDK 55 + React Native
- Navigation: Expo Router
- State Management: Zustand with MMKV persistence
- Data Fetching: TanStack React Query with offline-first caching
- Authentication: expo-auth-session (OAuth 2.0 + PKCE)
- Secure Storage: expo-secure-store
- API Client: @octokit/rest
- Styling: react-native-unistyles with dark/light themes
- Widgets: Voltra — iOS WidgetKit + Android Glance
- Persistence: react-native-mmkv
- Charts: react-native-pie-chart
- i18n: i18next + react-i18next
- Date Utils: date-fns
MIT
This project is kindly sponsored by Nearform.

