{"id":50886496,"url":"https://github.com/enmanuelmag/rn-firebase-cli","last_synced_at":"2026-06-15T17:32:16.854Z","repository":{"id":364331291,"uuid":"1267332478","full_name":"enmanuelmag/rn-firebase-cli","owner":"enmanuelmag","description":"CLI to automate Firebase setup for Expo and bare React Native projects, generates google-services configs, env files, and native integration code","archived":false,"fork":false,"pushed_at":"2026-06-12T16:54:50.000Z","size":502,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T17:08:50.181Z","etag":null,"topics":["cli","developer-tools","env","expo","firebase","firebase-setup","google-services","react-native","react-native-config","typescript"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/enmanuelmag.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-12T12:50:45.000Z","updated_at":"2026-06-12T16:54:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/enmanuelmag/rn-firebase-cli","commit_stats":null,"previous_names":["enmanuelmag/rn-firebase-cli"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/enmanuelmag/rn-firebase-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enmanuelmag%2Frn-firebase-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enmanuelmag%2Frn-firebase-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enmanuelmag%2Frn-firebase-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enmanuelmag%2Frn-firebase-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enmanuelmag","download_url":"https://codeload.github.com/enmanuelmag/rn-firebase-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enmanuelmag%2Frn-firebase-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34374146,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","developer-tools","env","expo","firebase","firebase-setup","google-services","react-native","react-native-config","typescript"],"created_at":"2026-06-15T17:32:15.738Z","updated_at":"2026-06-15T17:32:16.847Z","avatar_url":"https://github.com/enmanuelmag.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @cardor/rn-firebase-cli\n\nAutomated Firebase setup for React Native (Expo \u0026 Bare)\n\n[![npm version](https://img.shields.io/npm/v/@cardor/rn-firebase-cli)](https://www.npmjs.com/package/@cardor/rn-firebase-cli)\n[![npm downloads](https://img.shields.io/npm/dm/@cardor/rn-firebase-cli)](https://www.npmjs.com/package/@cardor/rn-firebase-cli)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-yellow.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Node](https://img.shields.io/badge/node-%3E%3D22.5.0-brightgreen)](https://nodejs.org)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)\n\n---\n\n## Table of Contents\n\n- [@cardor/rn-firebase-cli](#cardorrn-firebase-cli)\n  - [Table of Contents](#table-of-contents)\n  - [What is this?](#what-is-this)\n  - [Features](#features)\n  - [Prerequisites](#prerequisites)\n  - [Installation](#installation)\n    - [Global install (recommended for CLI usage)](#global-install-recommended-for-cli-usage)\n    - [Local install (for programmatic types)](#local-install-for-programmatic-types)\n  - [Quick Start](#quick-start)\n  - [CLI Commands Reference](#cli-commands-reference)\n    - [`rn-firebase init`](#rn-firebase-init)\n      - [Flags](#flags)\n      - [What it does](#what-it-does)\n      - [Files created](#files-created)\n    - [`rn-firebase status`](#rn-firebase-status)\n      - [Flags](#flags-1)\n      - [What it does](#what-it-does-1)\n    - [`rn-firebase update`](#rn-firebase-update)\n      - [Flags](#flags-2)\n      - [What it does](#what-it-does-2)\n  - [Configuration](#configuration)\n    - [`rn-firebase.config.*`](#rn-firebaseconfig)\n      - [Environment (`FirebaseEnv`)](#environment-firebaseenv)\n      - [Root config (`RNFConfig`)](#root-config-rnfconfig)\n    - [`config/firebase.config.*`](#configfirebaseconfig)\n    - [`.env.{envName}`](#envenvname)\n      - [Accessing env vars in your app](#accessing-env-vars-in-your-app)\n  - [Multi-Environment Setup](#multi-environment-setup)\n    - [Overview](#overview)\n    - [Prefixed file naming](#prefixed-file-naming)\n    - [APP\\_ENV pattern and app.config.ts](#app_env-pattern-and-appconfigts)\n    - [Loading .env files in Expo](#loading-env-files-in-expo)\n  - [Auto-generated package.json scripts](#auto-generated-packagejson-scripts)\n    - [Requirement](#requirement)\n    - [Generated scripts](#generated-scripts)\n  - [Usage Examples](#usage-examples)\n    - [Interactive setup (full wizard)](#interactive-setup-full-wizard)\n    - [Non-interactive setup with all flags](#non-interactive-setup-with-all-flags)\n    - [Android-only configuration](#android-only-configuration)\n    - [Skip `.gitignore` update](#skip-gitignore-update)\n    - [Check configuration status](#check-configuration-status)\n    - [Update config files (re-download)](#update-config-files-re-download)\n    - [Update a specific environment](#update-a-specific-environment)\n  - [Project Structure](#project-structure)\n    - [Package structure](#package-structure)\n  - [API](#api)\n  - [Development](#development)\n    - [Setup](#setup)\n    - [Scripts](#scripts)\n    - [Running in development mode](#running-in-development-mode)\n    - [Testing](#testing)\n    - [Building](#building)\n  - [Limitations](#limitations)\n  - [License](#license)\n  - [About](#about)\n\n---\n\n## What is this?\n\nSetting up Firebase in a React Native project is repetitive and error-prone. You need to:\n\n1. Create Firebase apps in the Firebase Console\n2. Download `google-services.json` and `GoogleService-Info.plist`\n3. Configure `app.json` (Expo) or native build files (Bare RN)\n4. Create environment-specific config files\n5. Update `.gitignore` so you don't commit secrets\n\nDo this across multiple environments (dev, staging, prod) and it becomes a chore.\n\n**`@cardor/rn-firebase-cli` automates all of it.** One command downloads your config files, extracts the right values, wires them into your project, and generates reusable config for your app code.\n\n---\n\n## Features\n\n- **Interactive wizard** — Guided prompts for project selection, platforms, environments\n- **Non-interactive mode** — All options available as CLI flags for CI/CD pipelines\n- **Auto-detection** — Detects Expo vs Bare RN, reads bundle IDs from `app.json`\n- **Firebase API integration** — Lists projects, verifies apps, downloads config via `firebase-tools`\n- **Multi-environment** — Supports dev, staging, prod (or custom names) in a single config\n- **Web client ID extraction** — Automatically extracts the OAuth web client ID from `google-services.json`\n- **Env file generation** — Writes all Firebase vars to `.env.{envName}` with the correct prefix per project type\n- **Expo fully supported** — Writes `googleServicesFile` paths into `app.json`, generates `config/firebase.config.*`\n- **`.gitignore` management** — Adds the output directory and `.env.*` pattern to `.gitignore` automatically\n- **Status check** — See at a glance which Firebase files are configured\n- **Update command** — Re-download config files after adding apps or changing projects\n- **Auto-generated npm scripts** — Injects `ios:{env}`, `android:{env}`, and `start:{env}` scripts into your project's `package.json` using `dotenv-cli`\n\n---\n\n## Prerequisites\n\n| Requirement | Minimum | Notes |\n|-------------|---------|-------|\n| **Node.js** | `\u003e=22.5.0` | ESM support required |\n| **firebase-tools** | `\u003e=13` | Must be installed globally (`npm install -g firebase-tools`) |\n| **Project type** | — | ESM project (`\"type\": \"module\"` in `package.json`) |\n| **gcloud CLI** | any | Optional but recommended. Used to check and enable Firebase services (Authentication, Firestore, Storage) during `init`. If not installed, service detection is skipped gracefully. Install from [cloud.google.com/sdk](https://cloud.google.com/sdk/docs/install). |\n\nYou must also be able to run `firebase login` interactively at least once so the CLI can authenticate with Firebase.\n\n---\n\n## Installation\n\n### Global install (recommended for CLI usage)\n\n```bash\nnpm install -g @cardor/rn-firebase-cli\n```\n\n```bash\npnpm add -g @cardor/rn-firebase-cli\n```\n\n```bash\nyarn global add @cardor/rn-firebase-cli\n```\n\nAfter installation, the `rn-firebase` binary is available globally:\n\n```bash\nrn-firebase --version\n# 0.1.0\n```\n\n### Local install (for programmatic types)\n\n```bash\nnpm install --save-dev @cardor/rn-firebase-cli\n```\n\nThis gives you TypeScript types for the config schema (see [API](#api)). Run the CLI via `npx`:\n\n```bash\nnpx rn-firebase init\n```\n\n---\n\n## Quick Start\n\n```bash\n# 1. Install globally\nnpm install -g @cardor/rn-firebase-cli\n\n# 2. Navigate to your React Native project\ncd my-react-native-app\n\n# 3. Run the interactive setup\nrn-firebase init\n\n# 4. Check what got configured\nrn-firebase status\n```\n\nThe wizard will guide you through:\n- Choosing to use an existing Firebase project or create a new one\n- Selecting or creating a Firebase project\n- Enabling Firebase services (Authentication, Firestore, Storage)\n- Choosing platforms (Android, iOS, or both)\n- Picking an environment name (dev, staging, prod, or custom)\n- Downloading config files\n- Wiring everything into your project\n\n---\n\n## CLI Commands Reference\n\n### `rn-firebase init`\n\n**Interactive wizard** to configure Firebase in your React Native project.\n\n```\nrn-firebase init [options]\n```\n\n#### Flags\n\n| Flag | Type | Default | Description |\n|------|------|---------|-------------|\n| `--project \u003cid\u003e` | `string` | (interactive prompt) | Firebase project ID. Skips the interactive project selection. |\n| `--platform \u003cplatform\u003e` | `\"android\" \\| \"ios\" \\| \"both\"` | (interactive prompt) | Platform(s) to configure. Skips the platform selection prompt. |\n| `--out \u003cdir\u003e` | `string` | `\"keys\"` | Output directory for `google-services.json` and `GoogleService-Info.plist`. |\n| `--no-gitignore` | `boolean` | `true` (gitignore enabled) | Skip adding the output directory to `.gitignore`. |\n\n#### What it does\n\n1. Checks that `firebase-tools` is installed globally\n2. Ensures you are authenticated with Firebase (triggers `firebase login` if needed)\n3. Detects project type (Expo or Bare RN)\n4. Reads bundle IDs from `app.json` (or prompts for them)\n5. Prompts whether to **use an existing Firebase project** or **create a new one**\n   - If creating: prompts for a display name and project ID, then calls `firebase projects:create`\n   - If using existing: lists your projects and prompts you to select one\n6. Shows a **multi-select** for Firebase services to enable (Authentication, Cloud Firestore, Cloud Storage)\n   - Services already enabled on the project are shown as dimmed/pre-checked and cannot be toggled\n   - Newly selected services are enabled via `gcloud services enable`\n   - If Authentication is selected or already enabled, prints a reminder to activate Auth providers in the Firebase console\n7. Verifies matching Firebase apps exist (by package name / bundle ID)\n8. Downloads `google-services.json` (Android) and/or `GoogleService-Info.plist` (iOS)\n9. Extracts the OAuth web client ID from `google-services.json`\n10. Writes all config files\n11. Generates a `.env.{envName}` file with all Firebase environment variables\n12. Updates `app.json` with `googleServicesFile` paths (Expo)\n13. Updates `.gitignore` to exclude the output directory and `.env.*` files\n14. Prints a usage hint showing how to consume the env vars in your app\n\n\u003e **Note:** Steps 5 and 6 (project selection and service enablement) are skipped when `--project \u003cid\u003e` is passed — the CLI goes directly to app verification in non-interactive mode.\n\n#### Files created\n\n| File | Condition |\n|------|-----------|\n| `{outDir}/google-services.json` | Android or both platforms |\n| `{outDir}/GoogleService-Info.plist` | iOS or both platforms |\n| `config/firebase.config.{ts\\|mjs\\|js}` | Always (runtime config for your app) |\n| `rn-firebase.config.{ts\\|mjs\\|js}` | Always (CLI config, reusable for updates) |\n| `.env.{envName}` | Always (Firebase env vars for the selected environment) |\n\n---\n\n### `rn-firebase status`\n\n**Check** which Firebase config files are present and configured.\n\n```\nrn-firebase status\n```\n\n#### Flags\n\nNone.\n\n#### What it does\n\n1. Loads `rn-firebase.config.*` from the current directory\n2. Checks for the existence of:\n   - `{outDir}/google-services.json`\n   - `{outDir}/GoogleService-Info.plist`\n   - `config/` directory (for `config/firebase.config.*`)\n   - `rn-firebase.config` file\n3. Prints green checkmarks (`✔`) or red crosses (`✗`) for each file\n4. Displays current configuration: environments, platform, output directory\n\n---\n\n### `rn-firebase update`\n\n**Re-download** Firebase config files. Useful after adding new apps to a project, changing project settings, or switching environments.\n\n```\nrn-firebase update [options]\n```\n\n#### Flags\n\n| Flag | Type | Default | Description |\n|------|------|---------|-------------|\n| `--env \u003cname\u003e` | `string` | First environment in config | Target environment name (e.g. `dev`, `staging`, `prod`). |\n\n#### What it does\n\n1. Loads `rn-firebase.config.*` from the current directory\n2. Finds the target environment (by `--env` or first entry)\n3. Checks `firebase-tools` and ensures authentication\n4. Re-downloads `google-services.json` and/or `GoogleService-Info.plist`\n5. Re-extracts the web client ID\n6. Re-writes all config files (same locations as `init`)\n\n**Note:** You must have run `rn-firebase init` at least once before using `update` — it reads the existing `rn-firebase.config.*` to know what to download.\n\n---\n\n## Configuration\n\nThe CLI generates two config files during `init`. Both are auto-generated — do not edit them directly. Re-run `rn-firebase init` or `rn-firebase update` to make changes.\n\n### `rn-firebase.config.*`\n\nThis is the **CLI configuration file**. It tells `rn-firebase` what to download and where to put it. The CLI uses it for the `status` and `update` commands.\n\nThe file extension depends on your project:\n- `.ts` — if `tsconfig.json` exists\n- `.mjs` — if `package.json` has `\"type\": \"module\"`\n- `.js` — if `package.json` has `\"type\": \"commonjs\"` or no `type` field (default for Expo/RN projects)\n\n```typescript\n// rn-firebase.config.ts\nimport type { RNFConfig } from '@cardor/rn-firebase-cli'\n\nexport default {\n  platform: 'both',\n  outDir: 'keys',\n  envs: [\n    {\n      name: 'dev',\n      googleCloudProjectId: 'my-project-dev',\n      firebaseProjectId: 'my-project-dev',\n      android: { packageName: 'com.myapp.dev' },\n      ios: { bundleId: 'com.myapp.dev' },\n    },\n  ],\n} satisfies RNFConfig\n```\n\n#### Environment (`FirebaseEnv`)\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `name` | `string` | Yes | Environment name (e.g. `dev`, `staging`, `prod`) |\n| `googleCloudProjectId` | `string` | Yes | GCP project ID |\n| `firebaseProjectId` | `string` | No | Firebase project ID (defaults to `googleCloudProjectId`) |\n| `android.packageName` | `string` | No | Android package name |\n| `ios.bundleId` | `string` | No | iOS bundle identifier |\n\n#### Root config (`RNFConfig`)\n\n| Field | Type | Required | Default | Description |\n|-------|------|----------|---------|-------------|\n| `platform` | `\"android\" \\| \"ios\" \\| \"both\"` | Yes | — | Configured platforms |\n| `outDir` | `string` | No | `\"keys\"` | Output directory for downloaded config files |\n| `envs` | `FirebaseEnv[]` | Yes | — | Environment configurations |\n\n### `config/firebase.config.*`\n\nThis is a **runtime config file** for your application code. It contains static values (package names, bundle IDs) and references the Firebase web client ID via an environment variable rather than hardcoding it:\n\n```typescript\n// config/firebase.config.ts\nexport const FIREBASE_CONFIG = {\n  webClientId: process.env.EXPO_PUBLIC_FIREBASE_WEB_CLIENT_ID,\n  androidPackageName: 'com.myapp.dev',\n  iosBundleId: 'com.myapp.dev',\n}\n```\n\nUse it in your app like this:\n\n```typescript\nimport { FIREBASE_CONFIG } from '../config/firebase.config'\n```\n\n### `.env.{envName}`\n\nDuring `init`, the CLI generates a `.env.{envName}` file (e.g. `.env.dev`, `.env.staging`, `.env.prod`) in your project root. It contains all Firebase environment variables extracted from `google-services.json`.\n\nThe variable names include a prefix that matches your project type:\n\n**Expo** (`EXPO_PUBLIC_` prefix — required for Expo's client-side env var system):\n\n```\nEXPO_PUBLIC_FIREBASE_API_KEY=AIzaSy...\nEXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=my-project.firebaseapp.com\nEXPO_PUBLIC_FIREBASE_PROJECT_ID=my-project-dev\nEXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=my-project-dev.appspot.com\nEXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=123456789\nEXPO_PUBLIC_FIREBASE_APP_ID=1:123456789:android:abcdef\nEXPO_PUBLIC_FIREBASE_WEB_CLIENT_ID=123456789-xxxxx.apps.googleusercontent.com\n```\n\n**Bare React Native** (no prefix — `react-native-config` convention):\n\n```\nFIREBASE_API_KEY=AIzaSy...\nFIREBASE_AUTH_DOMAIN=my-project.firebaseapp.com\nFIREBASE_PROJECT_ID=my-project-dev\nFIREBASE_STORAGE_BUCKET=my-project-dev.appspot.com\nFIREBASE_MESSAGING_SENDER_ID=123456789\nFIREBASE_APP_ID=1:123456789:android:abcdef\nFIREBASE_WEB_CLIENT_ID=123456789-xxxxx.apps.googleusercontent.com\n```\n\nIf the env file already exists with different content, the CLI will prompt before overwriting. The `.env.*` pattern is automatically added to `.gitignore` so these files are not committed.\n\n#### Accessing env vars in your app\n\n**Expo:** Variables are available as `process.env.EXPO_PUBLIC_FIREBASE_*` anywhere in your app code.\n\n```typescript\nconst apiKey = process.env.EXPO_PUBLIC_FIREBASE_API_KEY\nconst webClientId = process.env.EXPO_PUBLIC_FIREBASE_WEB_CLIENT_ID\n```\n\n**Bare React Native:** Install `react-native-config` and access vars via `Config.*`:\n\n```bash\nnpm install react-native-config\n```\n\n```typescript\nimport Config from 'react-native-config'\n\nconst apiKey = Config.FIREBASE_API_KEY\nconst webClientId = Config.FIREBASE_WEB_CLIENT_ID\n```\n\n---\n\n## Multi-Environment Setup\n\n### Overview\n\nEvery time you run `rn-firebase init`, the CLI sets up one environment (e.g. `dev`, `staging`, or `prod`). When you run it a second time for a different environment, it writes a second set of Firebase config files alongside the first — using a prefixed naming scheme to keep them separate.\n\n### Prefixed file naming\n\nFirebase native config files are written with the pattern `{env}-{id}-{base}`:\n\n| Platform | Pattern | Example |\n|----------|---------|---------|\n| Android | `{env}-{packageName}-google-services.json` | `dev-com.myapp-google-services.json` |\n| iOS | `{env}-{bundleId}-GoogleService-Info.plist` | `prod-com.myapp-GoogleService-Info.plist` |\n\nThis means your `keys/` directory will look like:\n\n```\nkeys/\n├── dev-com.myapp-google-services.json\n├── dev-com.myapp-GoogleService-Info.plist\n├── prod-com.myapp-google-services.json\n└── prod-com.myapp-GoogleService-Info.plist\n```\n\n### APP_ENV pattern and app.config.ts\n\nExpo reads whichever path is currently set in `app.json` (or `app.config.*`) — switching an environment variable alone is not enough. To switch between environments at build time, use `app.config.ts` with dynamic paths driven by an `APP_ENV` environment variable.\n\nWhen you run `rn-firebase init` for a second environment and the CLI detects that `app.json` already has a `googleServicesFile` set (from the first run), it will offer to auto-generate an `app.config.ts`:\n\n```\nMultiple envs detected. Generate app.config.ts for dynamic Firebase paths (APP_ENV)?\n```\n\nIf you accept, the CLI writes an `app.config.ts` that maps each environment to its correct Firebase config file:\n\n```typescript\n// Auto-generated by @cardor/rn-firebase-cli\n// Commit this file. Do NOT commit your .env.* files.\nimport type { ExpoConfig } from 'expo/config'\nimport appJsonData from './app.json'\n\nconst env = (process.env.APP_ENV ?? 'dev') as string\n\nconst firebaseFiles: Record\u003cstring, { android?: string; ios?: string }\u003e = {\n  dev: {\n    android: './keys/dev-com.myapp-google-services.json',\n    ios: './keys/dev-com.myapp-GoogleService-Info.plist',\n  },\n  prod: {\n    android: './keys/prod-com.myapp-google-services.json',\n    ios: './keys/prod-com.myapp-GoogleService-Info.plist',\n  },\n}\n\nconst config = {\n  ...appJsonData.expo,\n  android: {\n    ...(appJsonData.expo?.android as object | undefined),\n    googleServicesFile: firebaseFiles[env]?.android,\n  },\n  ios: {\n    ...(appJsonData.expo?.ios as object | undefined),\n    googleServicesFile: firebaseFiles[env]?.ios,\n  },\n} as ExpoConfig\n\nexport default config\n```\n\nThen set `APP_ENV` before running your build:\n\n```bash\nAPP_ENV=prod npx expo build\nAPP_ENV=dev npx expo start\n```\n\nIf `app.config.ts` already exists (you created it manually), the CLI will print the snippet to add to your `firebaseFiles` map instead of overwriting.\n\n### Loading .env files in Expo\n\n**Expo SDK 49 and later** load `.env` files automatically — no extra setup needed. Set `APP_ENV` via your build tool or shell.\n\n**Expo SDK 48 and earlier** require `dotenv/config` to be loaded manually. Add this to the top of your `app.config.ts`:\n\n```typescript\nimport 'dotenv/config'\n```\n\n---\n\n## Auto-generated package.json scripts\n\nAfter running `init` or `update`, the CLI automatically injects convenience scripts into your project's `package.json` based on your platform and environment name.\n\n### Requirement\n\n`dotenv-cli` must be installed in your project:\n\n```bash\npnpm add -D dotenv-cli\n```\n\nIf it is missing, the CLI prints a warning but still writes the scripts.\n\n### Generated scripts\n\nFor `platform: 'ios'` and `envName: 'dev'`:\n\n```json\n{\n  \"scripts\": {\n    \"ios:dev\": \"APP_ENV=dev dotenv -e .env.dev -- expo start --ios\",\n    \"start:dev\": \"APP_ENV=dev dotenv -e .env.dev -- expo start\"\n  }\n}\n```\n\nFor `platform: 'android'`:\n\n```json\n{\n  \"scripts\": {\n    \"android:dev\": \"APP_ENV=dev dotenv -e .env.dev -- expo start --android\",\n    \"start:dev\": \"APP_ENV=dev dotenv -e .env.dev -- expo start\"\n  }\n}\n```\n\nFor `platform: 'both'`, all three scripts are injected (`ios:dev`, `android:dev`, `start:dev`).\n\nScripts that already exist in `package.json` are **never overwritten**.\n\n---\n\n## Usage Examples\n\n### Interactive setup (full wizard)\n\n```bash\ncd my-react-native-app\nrn-firebase init\n```\n\n### Non-interactive setup with all flags\n\n```bash\nrn-firebase init \\\n  --project my-firebase-project \\\n  --platform both \\\n  --out firebase-keys\n```\n\n### Android-only configuration\n\n```bash\nrn-firebase init --platform android\n```\n\n### Skip `.gitignore` update\n\n```bash\nrn-firebase init --no-gitignore\n```\n\n### Check configuration status\n\n```bash\nrn-firebase status\n```\n\nExample output:\n\n```\n  Firebase setup status\n\n  ✔ google-services.json\n  ✔ GoogleService-Info.plist\n  ✔ config/firebase.config.*\n  ✔ rn-firebase.config\n\n  Environments configured: dev, staging\n  Platform: both\n  Output dir: keys\n```\n\n### Update config files (re-download)\n\n```bash\nrn-firebase update\n```\n\n### Update a specific environment\n\n```bash\nrn-firebase update --env staging\n```\n\n---\n\n## Project Structure\n\n```\nmy-react-native-app/\n├── rn-firebase.config.ts         # CLI config (auto-generated)\n├── .env.dev                      # Firebase env vars — dev (gitignored)\n├── config/\n│   └── firebase.config.ts        # Runtime config (auto-generated)\n├── keys/                         # Output directory (gitignored)\n│   ├── google-services.json      # Android Firebase config (auto-generated)\n│   └── GoogleService-Info.plist  # iOS Firebase config (auto-generated)\n└── ...rest of your project\n```\n\n### Package structure\n\n```\n@cardor/rn-firebase-cli/\n├── bin/\n│   └── rfc.js                    # CLI entry point (#!/usr/bin/env node)\n├── src/\n│   ├── cli.ts                    # Commander setup, 3 commands\n│   ├── index.ts                  # Public API (type exports only)\n│   ├── types.ts                  # All type definitions\n│   ├── commands/\n│   │   ├── init.ts               # runInit() — full setup wizard (285 lines)\n│   │   ├── status.ts             # runStatus() — check config presence (42 lines)\n│   │   └── update.ts             # runUpdate() — re-download configs (83 lines)\n│   ├── core/\n│   │   ├── config/\n│   │   │   ├── load.ts           # Config loader\n│   │   │   ├── defaults.ts       # Default values\n│   │   │   └── templates.ts      # File content generators\n│   │   ├── materializer/\n│   │   │   ├── index.ts          # RNMaterializer interface + factory\n│   │   │   ├── expo.ts           # ExpoMaterializer (fully implemented)\n│   │   │   └── bare-rn.ts        # BareRNMaterializer (placeholder)\n│   │   ├── firebase/\n│   │   │   ├── auth.ts           # firebase-tools check \u0026 login\n│   │   │   ├── projects.ts       # List Firebase projects\n│   │   │   ├── apps.ts           # List Android/iOS apps\n│   │   │   ├── config-download.ts# Download google-services \u0026 GoogleService-Info\n│   │   │   └── web-client.ts     # Extract web OAuth client ID\n│   │   └── detector/\n│   │       ├── index.ts          # Project type detection\n│   │       ├── config-ext.ts     # Config extension detection (ts/mjs/js)\n│   │       └── bundle-ids.ts     # Bundle ID detection from app.json / native files\n│   ├── utils/\n│   │   └── envFile.ts            # Env file generation utilities\n│   └── tests/\n│       ├── config.test.ts        # Tests for defaults, templates, web client\n│       ├── detector.test.ts      # Tests for project type \u0026 config extension\n│       ├── materializer.test.ts  # Tests for materializers\n│       └── envFile.test.ts       # Tests for env file utilities\n├── dist/                         # Build output (compiled)\n├── tsup.config.ts                # Build config (ESM, ES2022)\n├── tsconfig.json\n└── package.json\n```\n\n---\n\n## API\n\nThe package exports **TypeScript types only** (no runtime code). Import them to type-check your configuration files.\n\n```typescript\nimport type {\n  ConfigExt,         // 'ts' | 'mjs' | 'cjs' | 'js'\n  FirebaseApp,       // { appId, displayName?, packageName?, bundleId? }\n  FirebaseEnv,       // { name, googleCloudProjectId, firebaseProjectId?, android?, ios? }\n  FirebaseProject,   // { projectId, displayName }\n  MaterializeParams, // Parameters for the materializer build method\n  Platform,          // 'android' | 'ios' | 'both'\n  ProjectType,       // 'expo' | 'bare'\n  RNFConfig,         // { platform, outDir, envs }\n} from '@cardor/rn-firebase-cli'\n```\n\nUse them in your `rn-firebase.config.ts`:\n\n```typescript\nimport type { RNFConfig } from '@cardor/rn-firebase-cli'\n\nexport default {\n  platform: 'both',\n  outDir: 'keys',\n  envs: [\n    {\n      name: 'prod',\n      googleCloudProjectId: 'my-project-prod',\n      android: { packageName: 'com.myapp' },\n    },\n  ],\n} satisfies RNFConfig\n```\n\n---\n\n## Development\n\n### Setup\n\n```bash\ngit clone https://github.com/enmanuelmag/rn-firebase-cli.git\ncd rn-firebase-cli\npnpm install\n```\n\n### Scripts\n\n| Script | Command | Description |\n|--------|---------|-------------|\n| `pnpm dev` | `tsx src/cli.ts` | Run the CLI without building (uses `tsx` for TS execution) |\n| `pnpm build` | `tsup \u0026\u0026 pnpm typecheck` | Build to `dist/` with TypeScript declarations |\n| `pnpm test` | `node --test --import tsx/esm src/tests/*.test.ts` | Run test suite (30+ tests) |\n| `pnpm typecheck` | `tsc --noEmit` | Type-check without emitting files |\n| `pnpm lint` | `eslint . --fix` | Lint and auto-fix |\n| `pnpm format` | `prettier --write src scripts` | Format source files |\n\n### Running in development mode\n\n```bash\npnpm dev init         # equivalent to: rn-firebase init\npnpm dev status       # equivalent to: rn-firebase status\npnpm dev update       # equivalent to: rn-firebase update\n```\n\n### Testing\n\n```bash\npnpm test\n```\n\nThe test suite uses Node's built-in test runner (`node:test`) with `tsx` for TypeScript transpilation. Tests cover:\n\n- Config defaults and templates\n- Web client ID extraction from `google-services.json`\n- Project type detection\n- Config extension detection\n\n### Building\n\n```bash\npnpm build\n```\n\nUses `tsup` to bundle two entry points:\n- `cli` (`src/cli.ts`) — the CLI binary\n- `index` (`src/index.ts`) — the type-only public API\n\nOutput goes to `dist/` as ESM modules targeting ES2022.\n\n---\n\n## Limitations\n\n| Area | Status |\n|------|--------|\n| **Expo (managed \u0026 bare)** | **Fully supported.** Auto-detects project type, reads `app.json`, writes `googleServicesFile` fields, generates config files. |\n| **Bare React Native** | **Placeholder — coming in v2.** The CLI detects Bare RN projects and runs through the interactive wizard, but file creation is stubbed with informational messages. You can still select a Firebase project and download config files, but native build file integration is not yet implemented. |\n| **Dynamic app.config** | Projects using `app.config.js` or `app.config.ts` (instead of `app.json`) are detected, but bundle IDs must be entered manually and `googleServicesFile` fields must be added by hand. |\n\n---\n\n## License\n\nApache 2.0 © [Enmanuel Magallanes](https://github.com/enmanuelmag)\n\n---\n\n## About\n\nCreated and maintained by [Enmanuel Magallanes](mailto:enmanuelmag@cardor.dev).\n\n**@cardor/rn-firebase-cli** — Automated Firebase setup for React Native projects.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenmanuelmag%2Frn-firebase-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenmanuelmag%2Frn-firebase-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenmanuelmag%2Frn-firebase-cli/lists"}