# fbrcm documentation > Complete website documentation for fbrcm, generated from the same Markdown sources as the human-readable site. For a curated entry point, see [llms.txt](/llms.txt). --- Source: [/guide/index.md](/guide/index.md) # Getting started After these steps, fbrcm will have one working credential, a saved project list, and a cached Remote Config template. The last step previews a change without publishing it. Choose guided setup in the TUI or CLI, or configure the CLI manually. ## What you need Two Google Cloud project roles appear during setup: - **Firebase project.** This is the project whose Remote Config you want to manage. fbrcm discovers accessible Firebase projects, so you do not need to know all of their IDs in advance. - **Quota project.** This is the project Google should charge for API quota and billing. You must know this physical project ID before the first discovery, and your Google identity needs `serviceusage.services.use` on it. They may be the same physical Google Cloud project. The quota project does not grant access to Remote Config; your identity still needs the appropriate permissions on every Firebase project it manages. If you do not have a usable quota project, ask your Google Cloud administrator which project to use and for `serviceusage.services.use` on it. fbrcm cannot perform the first targetless project discovery without one. You also need one of these credential sources: - fbrcm's built-in Google OAuth client in an official release; - a Google OAuth Desktop app client JSON; - a service-account key JSON; or - Google Cloud CLI Application Default Credentials (ADC). If these terms are unfamiliar, read [Authentication and project discovery](/guide/authentication.md) before choosing a setup path. ## Install ### macOS Install with Homebrew: ```sh brew tap yumauri/tap brew install --cask fbrcm ``` Alternatively, run the installer directly: ```sh curl -sSfL https://raw.githubusercontent.com/yumauri/fbrcm/main/install.sh | sh ``` ### Linux Run the installer to download the latest release: ```sh curl -sSfL https://raw.githubusercontent.com/yumauri/fbrcm/main/install.sh | sh ``` If you use Homebrew on Linux, you can install from the tap instead: ```sh brew tap yumauri/tap brew install --cask fbrcm ``` ### Windows Run the installer in PowerShell: ```powershell irm https://raw.githubusercontent.com/yumauri/fbrcm/main/install.ps1 | iex ``` Or install with Scoop: ```powershell scoop bucket add yumauri https://github.com/yumauri/scoop-bucket scoop install fbrcm ``` ### From source Install from source with Go 1.27.3 or newer: ```sh go install github.com/yumauri/fbrcm@latest ``` A plain source build omits fbrcm's official Google OAuth client. The other three authentication methods remain available. Follow the repository README to build the `google` method with a local client. The macOS and Linux installer verifies the release archive against `checksums.txt` before extraction, using `sha256sum` or `shasum`. Confirm that the binary is available: ```sh fbrcm --version ``` ## Option 1: guided setup in the TUI Start fbrcm without arguments: ```sh fbrcm ``` On a new profile, the setup screen asks you to: 1. Choose built-in Google sign-in, imported OAuth, service-account, or gcloud ADC authentication. 2. Import or validate the selected credentials. 3. Enter the physical Google Cloud project ID to use as the quota project. 4. Complete browser authorization when OAuth requires it. 5. Let fbrcm discover and save the accessible Firebase projects. After the workspace opens, select a project in the left panel and select a parameter in the main panel. Press `?` anywhere to find available actions without memorizing shortcuts. Run the diagnostic from another terminal if setup reports an error: ```sh fbrcm doctor ``` Continue with the [TUI overview](/tui/index.md) when you want to edit or compare data interactively. ## Option 2: guided setup in the CLI Run the line-oriented setup wizard when you want guided onboarding without opening the full TUI: ```sh fbrcm setup ``` It chooses an authentication method, asks for an identity name and quota project, imports a JSON credential when the method needs one, completes or validates authentication, and discovers accessible Firebase projects. Add `--noopen` to print an OAuth authorization URL instead of opening it automatically. Rerunning the command resumes a partially configured profile; an already configured profile exits without making a network request. ## Manual CLI setup The examples below use these concrete names: | Example value | Meaning | | --- | --- | | `example-auth-name` | The local name fbrcm uses for the credential | | `example-quota-project-id` | The Google Cloud project ID used for quota and billing | | `example-project-id` | The Firebase project ID you want to manage | `example-auth-name` is not a command or a Google account name. It is the name fbrcm uses to refer to this credential. ### 1. Add one authentication identity Choose exactly one of the following methods. #### Continue with Google Official fbrcm releases include the application's shared OAuth client. Add an identity without creating a Google Cloud client or downloading a client JSON: ```sh fbrcm auth add google example-auth-name \ --quota-project example-quota-project-id fbrcm auth login example-auth-name ``` The final command opens Google's consent flow when authorization is needed. #### Google Cloud CLI If you already use the Google Cloud CLI, run: ```sh gcloud auth application-default login fbrcm auth add gcloud example-auth-name \ --quota-project example-quota-project-id fbrcm auth login example-auth-name ``` The final command validates that fbrcm can load the ADC credentials. It does not start another fbrcm-managed OAuth flow. #### OAuth Desktop app Create a Desktop app client in [Google Cloud OAuth clients](https://console.cloud.google.com/auth/clients), download its JSON file, and run: ```sh fbrcm auth add oauth example-auth-name \ --from /path/to/client-secret.json \ --quota-project example-quota-project-id fbrcm auth login example-auth-name ``` `auth login` opens the Google consent flow when no usable cached token exists. Add `--noopen` if you want fbrcm to print the authorization URL without opening the browser automatically. #### Service account Use a service-account key when your environment requires one: ```sh fbrcm auth add service-account example-service-account-auth \ --from /path/to/service-account.json \ --quota-project example-quota-project-id fbrcm auth login example-service-account-auth ``` The login command validates the stored key; it does not open a browser. ### 2. Discover projects Discover accessible Firebase projects and save them in the active profile: ```sh fbrcm projects update ``` The command uses every configured identity. At this point, that is the identity you just added. Later, `fbrcm projects list` reads the saved list and `fbrcm projects list --update` refreshes it before printing. ### 3. Inspect Remote Config First list the saved projects: ```sh fbrcm projects list ``` Then replace `example-project-id` with one Firebase project ID from that output: ```sh fbrcm get --project '=example-project-id' ``` This lists parameters from exactly that project. To inspect one parameter, add its key: ```sh fbrcm get feature_enabled --project '=example-project-id' ``` The leading `=` means exact project matching. It prevents a short name from accidentally matching several projects. ### 4. Check the complete setup ```sh fbrcm doctor ``` The report checks local files, credentials, quota-project resolution, project discovery, Remote Config access, and Firebase app read access. It checks `serviceusage.services.use`, `cloudconfig.configs.get`, `cloudconfig.configs.update`, `firebase.clients.list`, and `firebase.clients.get`. ## Preview your first change Remote Config publication replaces a complete template. Start with a dry run, which fetches and validates the candidate but does not publish or save it: ```sh fbrcm update feature_enabled \ --project '=example-project-id' \ --type boolean \ --value true \ --dry-run ``` Inspect the matched-item count and diff. When the result is correct, either rerun without `--dry-run` for an immediate reviewed publication or replace it with `--draft` to save the change locally. ## Where to go next - [Authentication and project discovery](/guide/authentication.md) explains auth IDs, quota projects, multiple identities, and project bindings. - [How fbrcm works](/guide/mental-model.md) explains profiles, aliases, caches, drafts, and client/server templates. - [Safe changes](/guide/safe-changes.md) walks through dry runs, drafts, conflict handling, and publication. - [CLI overview](/cli/index.md) explains command syntax, selectors, and output modes. - [Automation and agents](/automation/index.md) covers stable JSON execution. --- Source: [/guide/authentication.md](/guide/authentication.md) # Authentication and project discovery fbrcm stores authentication identities in the active profile. Project discovery then binds each Firebase project to one of those identities. ## Do not confuse these identifiers | Term | Example | What it identifies | | --- | --- | --- | | fbrcm profile | `personal` | An isolated local workspace | | Auth ID | `example-auth-name` | The local name fbrcm uses for one credential | | Google principal | `user@example.com` | The user or service account authenticated by Google | | Quota project ID | `example-quota-project-id` | The Google Cloud project charged for API usage | | Firebase project ID | `example-project-id` | The project whose Remote Config is accessed | | Repository alias | `staging` | An optional local-repository name for a Firebase project ID | In this command: ```text fbrcm auth quota-project set ``` `auth`, `quota-project`, and `set` are commands. The last two values are positional arguments. For example: ```sh fbrcm auth quota-project set example-auth-name example-quota-project-id ``` Here, `example-auth-name` is the auth ID and `example-quota-project-id` is the quota project ID. ## Required permissions The relevant permissions are: | Permission | Resource | Used for | | --- | --- | --- | | `serviceusage.services.use` | Quota project | Charging API quota and billing to that project | | `resourcemanager.projects.get` | Firebase project | Making the project visible during discovery | | `cloudconfig.configs.get` | Firebase project | Reading Remote Config | | `cloudconfig.configs.update` | Firebase project | Validating and publishing Remote Config | | `firebase.clients.list` | Firebase project | Listing registered Firebase apps | | `firebase.clients.get` | Firebase project | Reading app details and SDK configuration | The quota permission does not grant Remote Config access to that or any other project. Managed-feature operations such as deleting an experiment or rollout may require additional Firebase permissions. Use `fbrcm doctor` after setup to test the effective credential, quota project, Cloud Resource Manager access, Remote Config permissions, and both Firebase app permissions. A deliberately read-only identity can read Remote Config while `doctor` still reports the missing `cloudconfig.configs.update` permission. ## OAuth scope Interactive OAuth and Google Cloud CLI Application Default Credentials use `https://www.googleapis.com/auth/cloud-platform`. The Firebase Management API accepts that scope for app listing, details, and SDK configuration. It also accepts narrower read-only scopes for those app operations alone. fbrcm uses one credential for app reads and Remote Config reads and writes. The narrower `firebase.remoteconfig` scope fails in Google's interactive consent flow, and the grantable `firebase` scope is insufficient for Remote Config. Adding `apps` therefore does not add another scope. See the [privacy policy](/privacy-policy.md#why-the-broad-oauth-scope-is-requested) for the complete rationale and data-use limits. ## Authentication methods ### Google sign-in Official fbrcm release binaries include fbrcm's OAuth Desktop client. You do not need to create a Google Cloud OAuth client or download a client JSON. ```sh fbrcm auth add google example-auth-name \ --quota-project example-quota-project-id fbrcm auth login example-auth-name ``` The login command opens Google's authorization flow and caches the resulting token locally. A plain source build omits the built-in client. Use one of the other three methods, or follow the repository README to build with a local client. ### Google Cloud CLI ADC Create Application Default Credentials outside fbrcm: ```sh gcloud auth application-default login ``` Then register and validate them under a local auth ID: ```sh fbrcm auth add gcloud example-auth-name --quota-project example-quota-project-id fbrcm auth login example-auth-name ``` If the ADC JSON already contains a `quota_project_id`, fbrcm can use it when no environment, project, or auth-level setting takes precedence. Passing `--quota-project` makes the intended fbrcm default explicit. ### OAuth Desktop app Create a Desktop app OAuth client, download its JSON, and register it: ::: details Where to get client-secret.json 1. Open [Google Auth Platform → Clients](https://console.cloud.google.com/auth/clients) and select the Google Cloud project that will own the OAuth client. 2. If Google asks you to register the application first, complete the displayed setup for the app name, user-support email, audience, and developer contact. This is the current Google Auth Platform version of configuring an OAuth consent screen. 3. If you select an **External** audience and the publishing status is **Testing**, open **Google Auth Platform → Audience** and add the Google account that you will use with `fbrcm auth login` under **Test users**. fbrcm requests the Cloud Platform scope, so authorization is not covered by Google's basic-profile exception. 4. Click **Create client**, choose **Desktop app**, give the client a recognizable name, and click **Create**. 5. Download the JSON when the client is created. You may rename the downloaded file to `client-secret.json`; fbrcm does not require that exact filename. For an External app in Testing, Google expires the authorization after seven days, including an offline refresh token. You must then run `fbrcm auth login` again. See Google's [app registration](https://support.google.com/cloud/answer/15544987) and [audience and test-user](https://support.google.com/cloud/answer/15549945) documentation for the current rules. Google only exposes newly created client secrets in full at creation time, so keep the downloaded JSON somewhere private. If it is lost, create or rotate the client credentials. Never commit this file to a repository. See Google's [OAuth client instructions](https://support.google.com/cloud/answer/15549257) for the current console workflow. ::: ```sh fbrcm auth add oauth example-auth-name \ --from /path/to/client-secret.json \ --quota-project example-quota-project-id ``` Complete authorization separately: ```sh fbrcm auth login example-auth-name ``` fbrcm caches tokens locally for later commands. Use `fbrcm auth path example-auth-name` to inspect the exact client-secret and token paths. This bring-your-own method stores its imported client separately from the built-in `google` method. ### Service-account key Register and validate an existing JSON key: ::: details Where to get service-account.json 1. Open [IAM & Admin → Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts) and select the project that owns the service account. 2. Create a service account, or open the email address of an existing one. 3. Grant the service account roles containing the permissions listed in [Required permissions](#required-permissions) on the relevant quota and Firebase projects. 4. Open **Keys**, choose **Add key → Create new key**, select **JSON**, and click **Create**. 5. The browser downloads the key. You may rename it to `service-account.json`; fbrcm does not require that exact filename. The private key can be downloaded only when it is created. Store it securely and never commit it to a repository. If key creation is unavailable, an organization policy may prohibit service-account keys; ask the Google Cloud administrator rather than weakening that policy without review. See Google's [service-account key instructions](https://cloud.google.com/iam/docs/keys-create-delete) for details. ::: ```sh fbrcm auth add service-account example-service-account-auth \ --from /path/to/service-account.json \ --quota-project example-quota-project-id fbrcm auth login example-service-account-auth ``` fbrcm copies the key into the active profile's private configuration directory. Protect both the original and the stored copy. ## Why discovery needs a quota project When fbrcm already knows the target Firebase project, that project can be the last-resort quota project. The first project-discovery request is different: it lists accessible projects before a target exists. fbrcm therefore requires an environment, auth-level, or gcloud ADC quota project before sending that targetless request. The simplest setup is to save it while adding the identity: ```sh fbrcm auth add google example-auth-name --quota-project example-quota-project-id ``` For an existing identity, inspect or change it with: ```sh fbrcm auth quota-project show example-auth-name fbrcm auth quota-project set example-auth-name example-quota-project-id fbrcm auth quota-project unset example-auth-name ``` See [Quota and billing project](/reference/configuration.md#quota-and-billing-project) for the complete precedence order. ## Discover and save projects Synchronize one identity explicitly during setup: ```sh fbrcm projects update --auth example-auth-name ``` After you configure more identities, synchronize all of them with either: ```sh fbrcm projects update fbrcm projects list --update ``` Synchronization keeps existing projects that are temporarily inaccessible and marks them disabled instead of silently deleting their local state. ## Multiple identities and project bindings List the configured identities and their saved quota projects: ```sh fbrcm auth list ``` Discovery records which identities can see each project and chooses a binding. To bind selected saved projects to a different identity: ```sh fbrcm auth bind --auth example-service-account-auth --project '=example-project-id' ``` The exact selector limits the operation to one physical project. Binding does not change IAM at Google; it only selects which configured credential fbrcm uses for that project. ## Profiles The default profile is sufficient for one environment. Use separate profiles when credentials, organizations, or local caches should be isolated: ```sh fbrcm profile switch personal fbrcm profile switch customer-a fbrcm profile list ``` `profile switch` changes the persisted active profile. Root `--profile ` selects an existing profile for one invocation without changing the active one. ## Remove an identity Before deleting an identity, rebind or forget projects that depend on it. Then run: ```sh fbrcm auth delete example-auth-name ``` This removes the local auth entry and its fbrcm-managed credential files. It does not revoke an OAuth grant, delete a Google service account, or remove Google Cloud CLI ADC. --- Source: [/guide/mental-model.md](/guide/mental-model.md) # How fbrcm works fbrcm calls the Firebase Remote Config and Firebase Management APIs from your machine. Published templates and registered apps stay in Firebase. fbrcm stores credentials, project registrations, caches, and drafts locally. It has no intermediary backend. ## Projects and template targets A Firebase project can expose two independent Remote Config templates: - `client@project-id` is the template used by Firebase client SDKs; - `server@project-id` is the server template. An unqualified project name uses the project's configured primary template, which defaults to the client template. Use a qualified target whenever the distinction matters: ```sh fbrcm get --project 'client@=example-project-id' fbrcm get --project 'server@=example-project-id' ``` Client and server targets have separate caches, drafts, and version histories. ## Profiles A profile is an isolated fbrcm workspace. It contains: - registered authentication identities; - discovered and selected projects; - cached templates, version snapshots, and Firebase app data; - active drafts. fbrcm stores the active-profile preference in global configuration. The preference points to one of these workspaces. Use separate profiles for unrelated organizations, credentials, or project sets. Switch interactively with `Ctrl+P`, or use: ```sh fbrcm profile list fbrcm profile switch personal ``` ## Repository aliases Aliases give stable environment names to physical Firebase project IDs. Native aliases live in the nearest `.fbrcm.toml`: ```toml [projects.aliases] staging = "example-staging-project-id" prod = "example-production-project-id" ``` fbrcm also resolves Firebase CLI aliases from `.firebaserc`. Aliases belong to the repository instead of a profile, so teams can commit them and use the same names locally and in CI. ```sh fbrcm projects aliases import --from .firebaserc --dry-run fbrcm projects diff staging prod ``` Firebase requests, caches, and drafts continue to use canonical project IDs. ## Published state, cache, and drafts fbrcm distinguishes three states: | State | Meaning | | --- | --- | | Published | The template currently stored by Firebase | | Cached | A local snapshot used for fast reads and offline work | | Draft | Local edit intent that has not been published | Normal reads use a valid draft when one exists; otherwise they use cached published state and refresh it when requested. A draft contains the edited template and the base used to calculate local intent and detect conflicts. ## TUI and CLI The TUI and CLI read the same profiles, projects, caches, drafts, themes, and configuration. - Use the TUI when discovery, comparison, or visual review is the main task. - Use human-readable CLI output for focused terminal operations. - Add `--json` for scripts and agents that need a stable machine contract. - Add root `--stateless` when automation must operate directly from an access token without reading or writing application-managed local state. ## Remote Config writes are complete-template writes Firebase validates and publishes a complete Remote Config template even when you intend to change one parameter. fbrcm therefore turns targeted operations into a complete candidate template, shows the diff, validates the candidate, and publishes it with ETag protection. Even a one-parameter change produces a full candidate template. Use a [dry run or draft](/guide/safe-changes.md) to inspect that candidate before publication. --- Source: [/guide/safe-changes.md](/guide/safe-changes.md) # Safe changes Use a dry run to preview one command without saving it. Use a draft to collect several edits before publication. The examples use `example-project-id` as a physical Firebase project ID. ## Choose dry run or draft Use `--dry-run` when you want to answer "what would this command do?" without persisting anything: ```sh fbrcm update checkout_enabled \ --project '=example-project-id' \ --type boolean \ --value true \ --dry-run ``` The command prepares the candidate, validates it with Firebase, prints the diff, and suppresses publication and local writes. Use `--draft` when you want to collect related edits: ```sh fbrcm update checkout_enabled \ --project '=example-project-id' \ --type boolean \ --value true \ --draft fbrcm update checkout_title \ --project '=example-project-id' \ --type string \ --value 'Try the new checkout' \ --draft ``` Once a target has a draft, immediate publication commands refuse to bypass it. Continue editing the draft or publish or discard it explicitly. ## Review local intent Compare the draft with the immutable base it started from: ```sh fbrcm draft diff example-project-id --against base ``` This operation is local. It answers "what did I change?" To preview what publication would do against the latest Firebase state: ```sh fbrcm draft diff example-project-id --against current ``` This fetches the current template, performs the same three-way merge used by publication, and shows `current → candidate`. Add `--cached` only when you explicitly want to avoid the network and accept that the snapshot may be stale. ## Add a change note Firebase versions can carry a single-line change note: ```sh fbrcm draft change-note example-project-id 'Enable checkout experiment' ``` You can also use `--change-note` on a mutation or override the stored note at publish time. ## Publish ```sh fbrcm draft publish example-project-id ``` For each draft, fbrcm: 1. fetches current Firebase state; 2. rebases local intent with a three-way merge; 3. stops if local and remote changes conflict; 4. shows the exact candidate diff; 5. validates the candidate with Firebase; and 6. publishes it with ETag protection. Conflicts and failed validation preserve the draft. If Firebase already contains the intended result, fbrcm avoids creating a redundant version and cleans up the draft after a live publish. ## Work across projects Batch publication is intentionally non-atomic. fbrcm fetches, reviews, validates, and publishes each target independently: ```sh fbrcm draft publish --all ``` A failure in one project does not hide the results for the others. Treat the final report as a set of per-target outcomes and retry only failed targets. ## Discard a draft Discarding removes local draft state and never contacts Firebase: ```sh fbrcm draft discard example-project-id ``` Human mode shows the local base-to-draft diff before confirmation. Use `fbrcm draft show example-project-id --raw` first when you need to recover or archive a damaged draft envelope. ## Which one to use For one obvious edit, start with `--dry-run`, inspect the diff, then rerun the command normally. For multiple edits, use a draft from the start and publish it only after reviewing `--against current`. --- Source: [/tui/index.md](/tui/index.md) # Terminal UI Run `fbrcm` without arguments to open the interactive interface: ```sh fbrcm ``` On a new profile, this opens guided authentication and project discovery before the workspace. See the [guided setup steps](/guide/index.md#option-1-guided-setup-in-the-tui) or [Authentication and project discovery](/guide/authentication.md) if you need to prepare credentials and a quota project first. The minimum supported terminal size is 80 columns by 20 rows. A wider terminal shows more of a project comparison or promotion at once. ## Workspace layout The interface has four main areas: - **Projects** selects the Firebase projects and template targets in view. - **Parameters**, **Conditions**, **History**, **A/B Tests**, **Personalizations**, and **Rollouts** share the main data workspace. - **Details** inspects and edits the selected item. - **Logs** shows live activity and errors. The active profile appears in the upper-right corner. Promotion temporarily replaces the normal tabs with a dedicated source-to-target workspace. ## Find actions instead of memorizing keys Press `?` anywhere to open the searchable action palette. It shows only actions relevant to the current panel, uses your configured key bindings, and explains why unavailable actions are disabled. The global defaults are: | Key | Focus | | --- | --- | | `1` | Projects | | `2` | Parameters | | `3` | Conditions | | `4` | History | | `5` | Details | | `6` | A/B Tests | | `7` | Personalizations | | `8` | Rollouts | | `9` | Promote workspace | | `0` | Logs | | `Tab` | Next panel | | `\` | Hidden workspace tabs | Lists use arrow keys or `j`/`k`. `Home` and `End` jump to the first and last items. Every selectable row supports left-click selection; double-clicking it performs the same action as `Enter`. ## Select projects and templates Selecting one project shows its parameters. Mark several projects with `Space` to compare their trees. If a workspace opens with only one visible, accessible project target, fbrcm selects it automatically, collapses Projects, and focuses Parameters. This includes a workspace limited to one project by visibility rules. Later refreshes preserve your focus and layout. | Key | Project action | | --- | --- | | `Enter` | Select the focused project | | `Space` | Mark or unmark a project | | `u` | Synchronize projects | | `o` | Open Remote Config in Firebase Console | | `b` | Bind projects to another identity | | `t` | Show or hide client/server template rows | | `p` | Make the focused template primary | | `i` / `e` | Import or export Remote Config | | `d` | Download application defaults | | `v` | Promote to another project or template | The client template is primary by default. Expand a project with `t` to expose its `client@` and `server@` targets, then use `p` to change the default target. ## Work offline At startup, fbrcm performs a short proxy-aware connectivity probe. If it fails, the TUI enters offline mode and uses available cached data. Define `FBRCM_OFFLINE` to skip the probe and start offline immediately: ```sh FBRCM_OFFLINE=1 fbrcm ``` Standard requests honor `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY`, including their lowercase forms. ## Accounts, profiles, and themes | Key | Popup | | --- | --- | | `Ctrl+A` | Accounts | | `Ctrl+P` | Profiles | | `Ctrl+T` | Themes | Accounts manage identities and their project bindings. Profiles isolate credentials, projects, caches, and drafts. The theme picker applies each valid theme as a live preview before you save it. Continue with [Editing and drafts](/tui/editing.md) for parameter, group, condition, and publication workflows. --- Source: [/tui/editing.md](/tui/editing.md) # Editing and drafts in the TUI The Details panel shows the selected item and contains its edit form. Its title changes to **Parameter**, **Group**, or **Condition** for those entity types. Select a parameter, group, condition, or value and press `Enter` to open it. ## Parameters and groups The Parameters tree preserves the Remote Config hierarchy: groups contain parameters, and parameters contain a default plus any conditional values. Empty and description-only groups remain visible. | Key | Action | | --- | --- | | `Space` | Expand or collapse | | `a` | Add a parameter | | `A` | Add an empty group | | `c` | Duplicate a parameter | | `b` | Show the latest retained change for the selected parameter | | `e` | Edit the selected value | | `E` | Edit text or JSON externally | | `r` | Rename a parameter or group | | `m` | Move a parameter or group | | `x` | Delete the selected item | | `y` / `Y` | Copy the name or full path | Press `b` on either a parameter or one of its expanded values to find its newest direct change in retained Firebase history. The side-by-side diff shows the publishing user and local publication time below the parameter heading. This popup is titled **Blame**; ordinary History popups remain titled **Diff** and omit that attribution. Press `Esc` to close the diff or `q` to quit fbrcm. Group deletion is an explicit group-level operation and removes every parameter inside it. Other parameter mutations preserve empty groups and descriptions. ## Conditions Conditions appear in Firebase evaluation order. Open one to inspect its raw expression, display color, priority, and every parameter value that refers to it. | Key | Action | | --- | --- | | `a` | Add a condition | | `e` | Edit the Firebase expression | | `c` | Change the display color | | `r` | Rename the condition and its references | | `m` | Change evaluation priority | | `x` | Delete the condition and its conditional values | Priority changes are Remote Config changes, not cosmetic sorting, because Firebase evaluates conditions in order. ## Save an edit Inside Details: | Key | Action | | --- | --- | | `Esc` | Close or cancel the current editor | | `Right` / `e` | Edit the selected field | | `a` | Add a conditional value | | `d` | Toggle the in-app-default source | | `Ctrl+Enter` | Save Details | | `Ctrl+Y` | Copy the selected value or expression | If the target has no draft, saving opens a choice to publish immediately or save a draft. Once a draft exists, later edits stage into it automatically. Every mutation review includes an optional change note. A saved draft remembers the note; publishing sends it to Firebase as the new version description. ## Edit large text and JSON Press `E` to pause the TUI and edit a private staged file with an external editor. fbrcm resolves the command from `FBRCM_EDITOR`, `VISUAL`, then `EDITOR`. GUI editors must wait for the file to close: ```sh FBRCM_EDITOR="code --wait" fbrcm ``` After the editor exits, fbrcm validates and compacts JSON. It rejects invalid content and keeps the recovery file so you can reopen it. The built-in JSON editor uses `Ctrl+F` to format and `Ctrl+S` or `Ctrl+Enter` to save. Large values automatically use the external-editor path. ## Review and publish drafts The project row indicates when the displayed template includes draft state. | Key | Action | | --- | --- | | `p` | Publish the current draft | | `P` | Publish all drafts | | `d` | Discard the current draft | | `D` | Discard all drafts | Publication fetches current Firebase state, rebases local intent with a three-way merge, shows the exact candidate, validates it, and publishes with ETag protection. Conflicts and validation failures keep the draft intact. ## Import, export, and promotion In Projects, `i`, `e`, and `d` operate on the project under the cursor, not the set of marked projects. - Import supports merge or replacement, item selection, filtering, condition cleanup, and per-conflict choices. - Export writes the effective Remote Config template. - Application defaults downloads platform-specific defaults from Firebase. - Promotion compares one source target with another. You select the parameters, groups, and conditions to transfer. All resulting writes rejoin the same review, draft, and publication workflow. --- Source: [/cli/index.md](/cli/index.md) # Command-line interface Run a command to use fbrcm from the CLI: ```sh fbrcm projects list fbrcm get feature_enabled fbrcm draft list ``` With no arguments, fbrcm opens the [TUI](/tui/index.md). `fbrcm mcp` starts the [MCP server](/automation/mcp.md) for an AI application. If you have not configured credentials and discovered projects yet, run `fbrcm setup` or follow the [manual CLI setup](/guide/index.md#manual-cli-setup) first. Use `fbrcm help ` for flags accepted by the installed version and the [command index](/reference/commands.md) for a map of the complete command set. ## How to read command examples Angle-bracket names describe positional arguments; do not type the brackets. For example, the command syntax is: ```text fbrcm auth quota-project set ``` In a concrete invocation: ```sh fbrcm auth quota-project set example-auth-name example-quota-project-id ``` - `auth`, `quota-project`, and `set` are nested commands. - `example-auth-name` is a local auth ID chosen when the credential was added. - `example-quota-project-id` is a physical Google Cloud project ID. Examples throughout this site use `example-project-id` as a physical Firebase project ID, `staging` and `prod` as optional repository aliases, and `feature_enabled` as a parameter key. Replace them with your own values. ## Global behavior Global options may appear before or after the command: ```sh fbrcm --profile personal get feature_enabled fbrcm --json projects list fbrcm projects list --json ``` `--profile personal` requires that profile to exist already. Create or select it persistently with `fbrcm profile switch personal`. Important global controls include: | Option | Purpose | | --- | --- | | `--profile ` | Select an fbrcm profile for this invocation | | `--json` | Emit the versioned machine envelope | | `--stateless` | Operate directly from an access token without local state | | `--no-local-config` | Ignore repository `.fbrcm.toml` configuration | ## Select projects precisely Most multi-project commands accept repeatable `--project` / `-p` filters. ```sh fbrcm get feature_enabled --project prod fbrcm get feature_enabled --project '^acme-' fbrcm get feature_enabled --project '=example-project-id' ``` Filter prefixes are: | Prefix | Match mode | | --- | --- | | none or `~` | Fuzzy | | `^` | Starts with | | `/` | Contains | | `=` | Exact | Repeated project filters are ORed. Use `client@` or `server@` before a project query to select a specific template type: ```sh fbrcm get --project 'server@=example-project-id' ``` ## Human and machine output Human mode may use tables, color, diffs, and confirmations. `--json` returns one versioned envelope on success or failure and never opens prompts, editors, browsers, or file pickers. ```sh fbrcm --json get feature_enabled --project '=example-project-id' ``` Machine consumers should inspect structured problem codes and semantic exit statuses rather than parsing error text. See the [JSON contract](/automation/json-contract.md). ## Reads and writes Read commands use drafts when appropriate and otherwise use cached published state. Add `--update` to revalidate a cache before reading. Write commands normally: 1. load each selected target; 2. apply the targeted mutation in memory; 3. print the complete Remote Config diff; 4. ask for confirmation; 5. validate with Firebase; and 6. publish with ETag protection. Common write controls are: | Option | Behavior | | --- | --- | | `--dry-run` | Validate and preview without publishing or writing local state | | `--draft` | Save the mutation into a local draft | | `--plan-out ` | Write an immutable validated publication plan instead of publishing | | `--change-note ` | Attach a single-line Firebase version note | | `--yes` / `-y` | Accept the human confirmation non-interactively | Batch mutations are per-target and non-atomic. fbrcm continues after a project-scoped failure and reports every result. Use a [draft](/cli/drafts.md) to compose and revise several edits in the active profile. Use a [plan](/cli/plans.md) to preserve one exact candidate for review, handoff, or later application. ## Stateless mode Stateless mode runs in CI or a disposable environment without fbrcm-managed local state: ```sh GOOGLE_CLOUD_QUOTA_PROJECT=example-quota-project-id \ FBRCM_GOOGLE_ACCESS_TOKEN="$(gcloud auth application-default print-access-token)" \ fbrcm --stateless --json get feature_enabled \ --project '=example-project-id' ``` It does not read or write the project registry, caches, drafts, profiles, or publication hooks. fbrcm keeps the short-lived token in memory. Draft operations are unavailable because there is nowhere to persist them. See [Automation and agents](/automation/index.md) for stateless permissions and capability discovery. --- Source: [/cli/apps.md](/cli/apps.md) # Firebase applications Firebase apps are separate from Remote Config templates. They still matter to Remote Config because a condition can target a Firebase App ID. fbrcm provides read-only commands for finding those IDs, checking app registration details, and downloading SDK configuration. ## List registered apps List Android, iOS, and Web apps across every configured project: ```sh fbrcm apps list ``` Limit the result to one project or platform: ```sh fbrcm apps list example-project-id --platform ios fbrcm apps list --project '=example-project-id' --filter '^checkout' ``` The app filter matches display name, namespace, or Firebase App ID. Repeat `--filter` to combine queries with OR. Use `--show-deleted` to include apps that Firebase has marked for permanent deletion. ## Inspect one app ```sh fbrcm apps show com.example.checkout --project example-project-id ``` Selection checks the Firebase App ID, full resource name, namespace, and display name in that order. These comparisons are exact and case-sensitive. A complete Firebase App ID includes its project number, so it does not need `--project`: ```sh fbrcm apps show '1:1234567890:android:abc123' ``` ## Download SDK configuration Write the platform configuration to stdout: ```sh fbrcm apps config com.example.checkout --project example-project-id ``` Or save it to a private file: ```sh fbrcm apps config com.example.checkout \ --project example-project-id \ --to google-services.json ``` An existing destination requires confirmation. Use `--yes` only when replacing it is intentional. JSON mode returns a typed artifact. With `--to`, that artifact records the destination and digest instead of embedding the content. ## Cache behavior The app inventory, app details, and SDK configuration have separate cache entries with a one-hour lifetime. Normal reads use fresh entries first. `--update` forces a Firebase read. For `apps show` and `apps config`, `--cached` requires existing cached data and makes no Firebase request. For `apps list`, `--cached` accepts existing inventory even when stale, but fetches and saves it when the cache is missing. Use `FBRCM_OFFLINE=1` when the whole command must avoid network access. Stateless mode reads Firebase directly and does not accept either cache flag. Application data uses its own cache and never changes a Remote Config snapshot or draft. See the [command index](/reference/commands.md) for the command map and the [complete CLI reference](https://github.com/yumauri/fbrcm/blob/main/docs/CLI.md#firebase-applications) for every selection rule, output field, and error contract. --- Source: [/cli/drafts.md](/cli/drafts.md) # Drafts A draft stores unpublished edits in the active profile. Client and server templates have separate drafts. Later mutation commands add their edits to the same target's draft. Examples use `example-project-id` as a physical Firebase project ID. ## List drafts ```sh fbrcm draft list fbrcm draft list --filter '^prod' ``` The list includes the canonical target, base version, update time, change counts, status, and optional change note. fbrcm keeps invalid draft envelopes visible so you can recover or discard them. ## Create or extend a draft Any supported mutation can use `--draft`: ```sh fbrcm update payments_enabled \ --project '=example-project-id' \ --type boolean \ --value true \ --draft fbrcm groups add payments \ --project '=example-project-id' \ --description 'Payment configuration' \ --draft ``` Later mutations compose onto the same target-specific draft. ## Inspect and export ```sh fbrcm draft show example-project-id fbrcm draft show example-project-id --to candidate.json fbrcm draft show example-project-id --raw --to draft-envelope.json ``` Normal output is the validated working Remote Config candidate. `--raw` emits the stored envelope including its immutable base and can recover content even when normal draft decoding fails. ## Review changes ```sh # Purely local: base → stored draft. fbrcm draft diff example-project-id --against base # Live preview: current Firebase → rebased candidate. fbrcm draft diff example-project-id --against current ``` Add parameter, group, expression, or search filters to focus a large diff. A diff command returns status 1 when the filtered result contains differences and status 0 when it does not. ## Set the Firebase change note ```sh fbrcm draft change-note example-project-id 'Prepare payments launch' fbrcm draft change-note example-project-id --clear ``` fbrcm stores the note with the draft and sends it as the published Firebase version description. `draft publish --change-note` can override it for one invocation. ## Publish ```sh fbrcm draft publish example-project-id fbrcm draft publish --all --dry-run ``` Publication fetches current state, merges local intent, displays the effective candidate, validates with Firebase, and publishes with ETag protection. Conflicts preserve the draft. Batch operations continue after independent target failures and report every outcome. ## Discard ```sh fbrcm draft discard example-project-id fbrcm draft discard --all ``` Discarding is a local deletion. Human mode shows the base-to-draft diff before confirmation; `--yes` accepts the confirmation non-interactively. When the draft is ready for an approval or execution handoff, create an exact [publication plan](/cli/plans.md) with `draft publish --plan-out `. --- Source: [/cli/history.md](/cli/history.md) # History and managed features These commands read Remote Config version history and the Firebase-managed features bound to published client templates. Examples use `example-project-id` as a physical Firebase project ID. Version, experiment, rollout, and personalization IDs come from the corresponding list command. ## List and inspect versions ```sh fbrcm versions list example-project-id fbrcm versions show example-project-id 42 ``` Version lists combine Firebase history with locally retained snapshots when available. A cached historical template may outlive Firebase's retention window, so consider exporting important versions before clearing the cache. ## Compare versions ```sh fbrcm versions diff example-project-id 41 42 ``` Omit the second version to compare a historical version with the current effective state. Parameter, group, condition, expression, and search filters can narrow the diff. ## Trace one parameter ```sh fbrcm versions blame example-project-id checkout_enabled fbrcm versions blame example-project-id checkout_enabled --all ``` Blame walks adjacent retained Firebase publications and prints only the ones that directly changed the exact parameter. Each vertical-log entry identifies the older and newer version, author, time, change note, and a side-by-side parameter diff. The default stops after the latest change; use `--limit` for a larger change count, `--all` for the complete retained history, or `--at` to start at a particular version. Unchanged publications are still inspected, so `--limit` does not cap Firebase requests. Version metadata is paginated lazily, however, so fbrcm requests the next page only when the scan needs to continue. When the parameter predates the oldest retained version, fbrcm marks that history boundary instead of claiming the oldest template created it. ## Export a version ```sh fbrcm versions export example-project-id 42 --to remote-config-v42.json ``` Export is useful for audit artifacts, recovery, or review outside fbrcm. ## Roll back or restore ```sh fbrcm versions rollback example-project-id 42 --dry-run fbrcm versions restore example-project-id 42 --dry-run ``` - **Rollback** asks Firebase to roll the project back to a retained version. - **Restore** republishes a locally cached historical snapshot as a new version, which remains possible after Firebase no longer retains the source version. Both are complete-template writes and use the standard preview, validation, confirmation, and ETag safeguards. ## A/B tests ```sh fbrcm experiments list example-project-id fbrcm experiments show example-project-id experiment-id fbrcm experiments delete example-project-id experiment-id ``` List and show combine experiment metadata with bindings found in the published client template. Delete is a remote Firebase operation and follows the normal confirmation and machine-contract rules. ## Rollouts ```sh fbrcm rollouts list example-project-id fbrcm rollouts show example-project-id rollout-id fbrcm rollouts delete example-project-id rollout-id ``` Rollout views combine the public rollout API with parameter-value bindings from the published template. ## Personalizations ```sh fbrcm personalizations list example-project-id fbrcm personalizations show example-project-id personalization-id ``` Firebase exposes personalization bindings through the template but does not provide candidate values or result metrics through this API. Personalization commands are therefore read-only. Managed-feature commands apply to client templates. fbrcm omits server targets because Firebase exposes these features under the client Remote Config namespace. --- Source: [/cli/parameters.md](/cli/parameters.md) # Parameters, groups, and conditions The parameter commands operate on selected client or server templates. With no project filter, multi-project commands process every enabled configured target. Examples use `example-project-id` as a physical Firebase project ID. The leading `=` on `--project` requests an exact match. ## Read parameters Get one parameter across projects: ```sh fbrcm get feature_enabled --project '^acme-prod' ``` List parameters selected by search or an expression: ```sh fbrcm get --search 'checkout' fbrcm get --expr 'value == true' ``` Useful selectors include: ```text --project, -p select template targets; repeatable --filter, -f filter parameter keys; repeatable --group include parameters in named groups; repeatable --search search keys, descriptions, groups, and values --expr apply a typed expression --update revalidate caches before reading ``` When selection resolves to one visible template target, human output omits the redundant Project column. This also applies with no project filter when only one project is configured or a whitelist or blacklist leaves one visible project. Machine output retains complete target context. ## Add and duplicate ```sh fbrcm add checkout_enabled \ --project '=example-project-id' \ --type boolean \ --value false \ --description 'Enable the new checkout' \ --draft fbrcm duplicate checkout_enabled checkout_enabled_v2 \ --project '=example-project-id' \ --draft ``` Parameter types are string, boolean, number, and JSON. JSON values must be valid JSON: ```sh fbrcm add checkout_config \ --type json \ --value '{"enabled":false,"variant":"control"}' \ --project '=example-project-id' \ --dry-run ``` ## Update Update a known parameter: ```sh fbrcm update checkout_enabled \ --project '=example-project-id' \ --type boolean \ --value true \ --dry-run ``` Omit the positional key only when filters deliberately select several parameters: ```sh fbrcm update \ --project '^example-staging-' \ --filter '^checkout_' \ --type boolean \ --value false \ --dry-run ``` Always inspect the matched-item count and diff before applying a broad update. ## Delete ```sh fbrcm delete old_checkout_flag \ --project '=example-project-id' \ --dry-run ``` Deleting a parameter does not remove an empty group. fbrcm preserves empty and description-only groups unless you run an explicit group delete. It also blocks parameter deletion for Firebase-managed and unknown future values. ## Manage groups ```sh fbrcm groups list --project '=example-project-id' fbrcm groups add checkout --description 'Checkout controls' --project '=example-project-id' --draft fbrcm groups edit checkout \ --description 'Checkout and payment controls' \ --project '=example-project-id' \ --draft fbrcm groups rename checkout checkout_v2 --project '=example-project-id' --draft fbrcm groups delete checkout_v2 --project '=example-project-id' --dry-run ``` Group names selected for edit, rename, or delete match exactly and case-sensitively. Deleting a group removes all parameters inside it. ## Inspect conditions ```sh fbrcm conditions list example-project-id fbrcm conditions show example-project-id "iOS users" fbrcm conditions validate example-project-id ``` The list follows Firebase evaluation order. `show` includes the parameters and conditional values that reference the selected condition. When a condition uses `app.id`, use [`apps list`](/cli/apps.md) to match its Firebase App ID to a registered Android, iOS, or Web app. ## Change conditions ```sh fbrcm conditions add example-project-id "Beta users" \ --expression 'percent <= 10' \ --color ORANGE \ --draft fbrcm conditions edit example-project-id "Beta users" \ --expression 'percent <= 20' \ --draft fbrcm conditions move example-project-id "Beta users" 1 --draft fbrcm conditions rename example-project-id "Beta users" "Early access" --draft fbrcm conditions delete example-project-id "Early access" --dry-run fbrcm conditions add "Beta users" \ --project '=example-staging' \ --project '=example-preview' \ --expression 'percent <= 10' \ --draft fbrcm conditions delete \ --project '^example-' \ --expr 'usage_count == 0' \ --dry-run ``` Rename updates every conditional-value reference. Delete removes the condition and its conditional values. `add` and `delete` accept repeatable project filters; without a positional project or project filters, they select every configured project and enabled template. Delete also supports the same name, search, and condition-expression filters as `conditions list`. Moving a condition can change value resolution, so fbrcm treats it as a reviewed Remote Config mutation. See [Filtering](/reference/filtering.md) for filter composition, expression contexts, value typing, and JSON queries. --- Source: [/cli/plans.md](/cli/plans.md) # Plans A publication plan is a private, integrity-protected file containing the exact Remote Config candidates that fbrcm prepared and validated. Create one when a change must be reviewed, approved, handed off, or applied later without recalculating it. Examples use `example-project-id` as a physical Firebase project ID and `release.fbrcm-plan.json` as a local plan file. ## Plans and drafts solve different problems | | Draft | Plan | | --- | --- | --- | | Purpose | Compose and revise several edits | Preserve one exact publication decision | | Storage | Active fbrcm profile | Caller-selected private file | | Later changes | Mutations extend the draft | Create a new plan | | Publication | Rebase local intent with `draft publish` | Require the recorded base with `apply` | | Portability | Tied to local profile state | Can be handed off securely | | Stateless mode | Unavailable | Supported when the producing command supports it | Use a draft while you are still editing. Create a plan when the candidate and target selection are ready for approval or later execution. You can create a plan from a draft without publishing it. ## Create a plan Commands whose capability reports `supports.plan: true` accept `--plan-out `: ```sh fbrcm update feature_enabled \ --project '=example-project-id' \ --type boolean \ --value true \ --plan-out release.fbrcm-plan.json ``` Planning performs the normal target selection, fetches fresh base templates, builds the candidates, validates changed candidates with Firebase, and runs effective trusted pre-publish hooks. It does not publish Remote Config or change drafts. If any selected target cannot be prepared or validated, fbrcm does not create the plan. The destination is created as a private file and is never overwritten. `--plan-out` cannot be combined with `--dry-run`, `--draft`, or `--yes`, and `-` is not accepted as an output path. Supported producers include parameter, group, and condition mutations, `project import`, `projects promote`, `draft publish`, and `versions restore`. Discover the installed binary's exact set instead of hard-coding it: ```sh fbrcm capabilities --json | jq -r '.data.commands[] | select(.supports.plan) | .path | join(" ")' ``` ## Prepare a draft for approval Compose a multi-step change as a draft, then capture its effective publication candidate in a plan: ```sh fbrcm draft diff example-project-id --against current fbrcm draft publish example-project-id \ --plan-out release.fbrcm-plan.json ``` Creating the plan does not remove the source draft. A live apply removes it only if it still matches the draft recorded by the plan. If the draft changed after planning, fbrcm preserves it and reports a warning. ## Inspect and validate ```sh fbrcm plan show release.fbrcm-plan.json fbrcm plan validate release.fbrcm-plan.json ``` `plan show` verifies the file and prints its identity, execution policy, targets, actions, validation provenance, and complete base-to-candidate diffs. With `--json`, it returns a non-secret typed summary instead of embedding the templates. `plan validate` verifies the document shape, snapshot digests, invariants, and content-derived plan ID. It is an offline integrity check; it does not check whether Firebase still matches the recorded base. Both commands accept `-` to read one plan document from stdin. ## Apply the exact candidates Preview execution with a full preflight, then apply after authorization: ```sh fbrcm apply release.fbrcm-plan.json --dry-run fbrcm apply release.fbrcm-plan.json ``` Apply verifies the plan and execution environment, reads every changed target, and preflights the entire plan before the first publication. A target must still equal the recorded base, or already equal the candidate. Any other state fails with `plan.stale`; fbrcm never silently rebases or replans. After one confirmation for the whole plan, fbrcm validates every changed candidate and runs trusted pre-publish hooks before writing. `--dry-run` performs those checks without publication or draft cleanup. Use `--yes` for an explicitly authorized non-interactive invocation. Plans with several targets are non-atomic once publication starts. Successful targets are not rolled back if a later target fails. Inspect every result item; statuses distinguish unchanged, would-publish, published, already-applied, conflict, and post-publication failures. ## Execution environment and retries A stateful plan must be applied statefully with the same effective hook configuration. A plan created with `--stateless` must be applied with `--stateless` and a suitable access token. A plan containing only unchanged targets can be applied entirely offline. If a target already matches the candidate, apply does not publish it again. Retrying a plan is declared safe only when no trusted hook ran, because repeating a hook command may have additional effects. If a plan is stale, review the current state and create a new plan. ## Protect plan files A plan contains complete base and candidate Remote Config templates, ETags, digests, change notes, and provenance. Treat it as sensitive configuration: keep it out of logs and source control, restrict who can read it, transfer it through an approved secure channel, and remove it according to your retention policy after use. In JSON mode, plan creation returns only the plan ID, counts, and artifact metadata including the output path, byte size, and SHA-256 digest. The plan contents are never copied into stdout. --- Source: [/cli/projects.md](/cli/projects.md) # Projects and templates Projects are local registrations of physical Firebase projects and the identity used to access them. Forgetting one removes local fbrcm state; it does not delete or change the Firebase project. This page assumes authentication is already configured. For the first synchronization, follow [Authentication and project discovery](/guide/authentication.md). ## Discover and inspect projects ```sh fbrcm projects list --update fbrcm project show example-project-id ``` `projects list` reads the local registry and optionally synchronizes accessible projects. `project show` displays one resolved project and its local metadata. The initial discovery request is targetless, so fbrcm must resolve a quota project before it can synchronize anything. Guided setup stores an auth-level default. For an identity added through the CLI, supply `--quota-project` during `auth add`: ```sh fbrcm auth add gcloud example-auth-name --quota-project example-quota-project-id ``` For an existing identity, the syntax and a concrete example are: ```text fbrcm auth quota-project set ``` ```sh fbrcm auth quota-project set example-auth-name example-quota-project-id ``` `example-auth-name` is the local auth ID; `example-quota-project-id` is the physical Google Cloud quota project ID. The authenticated principal needs `serviceusage.services.use` on that project. See [Quota and billing project](/reference/configuration.md#quota-and-billing-project) for the full resolution order. Use `fbrcm doctor` when discovery fails. It checks credentials, connectivity, API access, permissions, and local storage in one report. ## Keep only the projects you work with Hide a few projects with a blacklist, or explicitly choose a workspace with a whitelist: ```sh fbrcm projects blacklist add legacy-project sandbox-project fbrcm projects whitelist add development-project production-project fbrcm projects whitelist enable fbrcm projects list --include-hidden ``` Both groups support `list`, `add`, `remove`, `clear`, `enable`, and `disable`. The blacklist starts enabled; the whitelist starts disabled. Blacklist exclusions take precedence. An enabled empty whitelist hides every project; `clear` keeps activation, while `disable` retains membership without restricting the workspace. Use repeatable `--filter` instead of literal IDs for bulk membership changes. Filters resolve the local inventory once and save IDs. Visibility is profile-scoped, covers both template kinds, and survives discovery, forgetting, and registry reset. Hidden projects keep their caches and drafts. Ordinary CLI and TUI selection excludes hidden projects. Add `--include-hidden` to a CLI invocation or press `H` in the TUI Projects panel to temporarily show them. Stateless execution ignores local visibility rules. ## Use repository aliases ```sh fbrcm projects aliases set staging example-staging-project-id fbrcm projects aliases set prod example-production-project-id fbrcm projects aliases list ``` Import aliases from a Firebase CLI project file: ```sh fbrcm projects aliases import --from .firebaserc --dry-run fbrcm projects aliases import --from .firebaserc ``` fbrcm stores native aliases in the nearest `.fbrcm.toml`; Firebase aliases remain in `.firebaserc`. fbrcm rejects conflicting definitions. The remaining examples use `staging` and `prod` after you define these aliases. ## Choose client or server templates Inspect available template types and the current primary: ```sh fbrcm project templates show staging ``` Set the primary template used by unqualified project selectors: ```sh fbrcm project templates set staging --primary server ``` An explicit target always wins over the saved preference: ```sh fbrcm get --project 'client@=staging' fbrcm get --project 'server@=staging' ``` ## Compare environments ```sh fbrcm projects diff staging prod ``` The comparison includes parameter values, groups, descriptions, conditions, and condition ordering. Use filters to narrow a large diff to the configuration you are reviewing. ## Promote selected configuration Preview a promotion before writing: ```sh fbrcm projects promote client@staging client@prod --all --dry-run ``` Promotion is selective: it transfers chosen parameters, groups, and conditions from the source candidate to the target candidate. The source is never modified. Use `--draft` to stage the target-side result for a later review. Explicitly qualify targets when promoting between client and server templates: ```sh fbrcm projects promote client@staging server@prod --all --dry-run ``` ## Import a template ```sh fbrcm project import staging --from remote-config.json --dry-run ``` Import supports merge and replacement workflows, parameter or group selection, filters, condition cleanup, and conflict choices. The final candidate always goes through the normal diff and validation path. Use stdin when another command produces the template: ```sh generate-config | fbrcm project import staging --from - --dry-run ``` ## Export and application defaults ```sh fbrcm project export staging --to remote-config.json fbrcm project defaults staging --format plist --to RemoteConfigDefaults.plist ``` Export writes the effective Remote Config template. Defaults asks Firebase for the selected platform format. Existing destinations require an explicit human confirmation; JSON mode reports that interaction requirement instead of prompting. ## Open and forget ```sh fbrcm project open staging fbrcm projects forget --filter '=staging' ``` `project open` launches the Remote Config page in Firebase Console. JSON mode returns the URL without opening a browser. `projects forget` removes registrations, caches, snapshots, and drafts for the selected local projects without touching Firebase. --- Source: [/automation/index.md](/automation/index.md) # Automation and agents Use the [MCP server](/automation/mcp.md) to expose Remote Config tools to an MCP-compatible AI application. For agents and scripts running one-shot CLI commands, follow the workflow below and add `--json` to each call. Commands then return one versioned JSON envelope instead of terminal tables, colors, diffs, or prompts. The stateful examples assume you have already configured a profile through the [manual CLI setup path](/guide/index.md#manual-cli-setup). The guided `fbrcm setup` command is intentionally interactive and is not available in JSON mode. ## Discover the installed binary Do not hard-code an assumed command set. Ask the binary what it supports: ```sh fbrcm capabilities --json fbrcm capabilities project import --json fbrcm schema list --json ``` Capability records describe arguments, flags, schemas, side effects, interaction, and support for stateless, dry-run, draft, and plan execution. ## Read before writing Resolve the exact target and inspect current state first: ```sh fbrcm projects list --json fbrcm get feature_enabled --project '=example-project-id' --json ``` Use exact selectors in automation. A fuzzy name that is convenient at a terminal can become ambiguous as projects are added. ## Preview and prepare for review When a capability reports dry-run support, validate the real candidate without publishing it: ```sh fbrcm update feature_enabled \ --project '=example-project-id' \ --type boolean \ --value true \ --dry-run \ --json ``` Use a draft while several edits still need to be composed or revised: ```sh fbrcm update feature_enabled \ --project '=example-project-id' \ --type boolean \ --value true \ --draft \ --json fbrcm draft diff example-project-id --against current --json ``` Use a plan when an agent must hand off one exact, validated candidate for approval or later execution. A plan can be created directly by a supported mutation or from a draft: ```sh fbrcm draft publish example-project-id \ --plan-out release.fbrcm-plan.json \ --json fbrcm plan validate release.fbrcm-plan.json --json fbrcm plan show release.fbrcm-plan.json --json fbrcm apply release.fbrcm-plan.json --dry-run --yes --json fbrcm apply release.fbrcm-plan.json --yes --json ``` Plan creation fetches fresh bases, validates the exact changed candidates, and runs effective trusted pre-publish hooks without publishing. Apply accepts only targets that still match the recorded base or already match the candidate. It does not recalculate the change. Treat the plan file as sensitive because it contains complete base and candidate templates. See [Plans](/cli/plans.md) for integrity, concurrency, stateless, cleanup, and retry behavior. `--yes` authorizes a documented confirmation. It does not disable Firebase validation, make a retry safe, or turn a destructive action into an authorized one. ## Handle results structurally Inspect all of these together: - envelope `outcome` and `exit_code`; - top-level `errors` and `warnings`; - each `data.items[].status` in a batch result; and - structured remediation `strategy` and `argv`. Never branch on human-readable `message` wording. A successful diff with changes uses status 1, and a batch can partially succeed with status 12. Earlier successful targets are not rolled back after another target fails. ## Interaction never blocks JSON mode JSON mode never opens a prompt, editor, file picker, or browser. If an operation needs human input, fbrcm returns an `interaction.required` problem with status 10. Show that request to a human, or retry only after the caller explicitly supplies the required choice. ## Run without local state Supported commands can operate from a short-lived access token: ```sh GOOGLE_CLOUD_QUOTA_PROJECT=example-quota-project-id \ FBRCM_GOOGLE_ACCESS_TOKEN="$(gcloud auth application-default print-access-token)" \ fbrcm --stateless get feature_enabled \ --project '=example-project-id' \ --json ``` Stateless mode skips fbrcm-managed profiles, project registrations, caches, drafts, and hooks. It still permits explicit caller-selected input and output files, including publication plans. A stateless plan must later be applied with `--stateless`. fbrcm keeps the token in memory and never writes it. The token's principal needs `serviceusage.services.use` on `example-quota-project-id` and Remote Config access on `example-project-id`. Check `supports.stateless` in the capability record before running a command this way. Continue with the [JSON contract](/automation/json-contract.md) for the envelope, exit statuses, schemas, and artifact results. --- Source: [/automation/json-contract.md](/automation/json-contract.md) # JSON contract Contract `1.0.0` is the released baseline for fbrcm 1.0.0. See the [compatibility guarantees](/reference/compatibility.md) for schema versioning, upgrade rules, and the exclusion of human layouts from automation interfaces. With `--json`, each one-shot CLI invocation writes one JSON document and one trailing newline to stdout. This includes argument and startup failures. Parse stdout only. Explicitly enabled logs and trusted hooks may write to stderr. For protocol-based tool calls, use the [MCP server](/automation/mcp.md#read-tool-results) without `--json`. ## Envelope Every response contains the same top-level fields: ```json { "schema": "urn:fbrcm:schema:cli:1.0.0:command:projects.list:response", "contract_version": "1.0.0", "command": "projects.list", "requested_command": "projects.list", "outcome": "success", "exit_code": 0, "producer": { "name": "fbrcm", "version": "1.0.0" }, "context": { "profile": "default", "offline": false, "dry_run": false, "draft": false }, "data": { "count": 0, "items": [] }, "errors": [], "warnings": [] } ``` `data` is the command DTO, an artifact DTO, or `null` when no usable result exists. Collections use `{ "count", "items" }`; singular resources use an object. `producer.version` is the installed fbrcm release and therefore differs from the example as new versions are published. ## Outcomes and exit statuses | Status | Meaning | | ---: | --- | | `0` | Success; no changes for a diff | | `1` | Differences found, invalid validation report, or failed diagnostics | | `2` | Invalid arguments, flags, or command path | | `3` | Configuration or profile failure | | `4` | Authentication failure | | `5` | Permission denied | | `6` | Project or other resource not found | | `7` | Conflict, including ETag failures | | `8` | Input or Remote Config validation failure | | `9` | Deadline exceeded | | `10` | Explicit interaction required | | `11` | Network, offline, rate-limit, or service unavailable | | `12` | Partial batch success | | `13` | Local file or stream I/O failure | | `14` | Publication hook failure | | `15` | Internal or contract-encoding failure | | `130` | Interrupted or canceled | Status 1 is not necessarily failure. Always read `outcome` as well as the process status. ## Structured problems Each error has stable `code`, `category`, `retryable`, `target`, `stage`, `details`, and `remediation` fields in addition to its message. Branch on `code` or `category`, never on message text. Each remediation includes one of these strategies: - `retry_with_arguments` augments the original invocation; - `replace_selector` replaces an ambiguous selector; and - `run_command` is a complete fbrcm subcommand argument list. A remediation describes a technically valid recovery. Callers must still check scope, side effects, and authorization before executing it. ## Artifacts Commands returning Remote Config, defaults, drafts, or exports use an artifact DTO. It describes media type, encoding, destination, byte size, SHA-256 digest, and whether an existing destination was overwritten. Content is either inline or written to the destination, never both. ## Discover schemas ```sh fbrcm capabilities update --json fbrcm schema list --json fbrcm schema show \ urn:fbrcm:schema:cli:1.0.0:command:update:response \ --json ``` Schemas use JSON Schema Draft 2020-12 and include fbrcm annotations for selection, side effects, effective flags, and invariants that JSON Schema cannot calculate by itself. ## Time limits Use the global timeout for a complete operation: ```sh fbrcm projects list --json --timeout 30s ``` It covers target resolution, authentication, network pacing and retries, validation, hooks, and local persistence. Expiration returns status 9; an interrupt returns 130. --- Source: [/automation/mcp.md](/automation/mcp.md) # MCP server From 1.0.0, public MCP tool names, contracts, results, launch options, and authorization policy are covered by the [compatibility guarantees](/reference/compatibility.md). Discovery remains conditional on launch configuration and negotiated host capabilities. Use the built-in MCP server to work with Firebase Remote Config from an MCP-compatible AI application. The application launches `fbrcm mcp` and calls its tools over stdio. You do not need to start a separate server before chatting. MCP exposes Remote Config workflows, including inspection, editing, drafts, plans, and publication. It uses the same operations and result envelopes as the CLI, with permissions fixed when the server starts. ## Connect your AI application Install fbrcm and configure a profile using the [guided CLI setup](/guide/index.md#option-2-guided-setup-in-the-cli). Authentication identities and discovered projects belong to that profile; see [Authentication and discovery](/guide/authentication.md). Add the binary to your application's MCP server configuration. For hosts that accept the common `mcpServers` format: ```json { "mcpServers": { "firebase": { "command": "/absolute/path/to/fbrcm", "args": ["mcp", "--profile", "personal", "--no-local-config"] } } } ``` Replace the binary path and profile name. The selected profile must already exist. The host starts and stops the process; do not add `--json` to this configuration, because stdout carries MCP protocol messages. `--no-local-config` ignores repository `.fbrcm.toml` settings. Omit it when you want repository configuration and aliases to apply. Tool discovery does not require Google credentials; authentication happens when a call needs Firebase. ## Make a first tool call Ask the agent to inspect a parameter in a specific project, or call `parameters.get` directly from your host's tool interface: ```json { "arguments": {"parameter": "feature_enabled"}, "options": {"project": ["=example-project-id"]} } ``` The `=` prefix selects an exact project ID. Use exact selectors for agent workflows; see [Filtering](/reference/filtering.md) for other query modes. Use each tool's discovered input schema when constructing calls: - `arguments` contains named positional arguments. - `options` contains long flag names without `--`. Repeatable values, such as `project`, are JSON arrays; booleans are JSON booleans. - `stdin` contains a JSON document for tools that accept document input, not a JSON-encoded string. Optional `arguments` and `options` default to `{}` where valid, and optional `stdin` defaults to `null`. Required values must still be supplied. For example, `conditions.add` requires `arguments.name` and `options.expression`. Condition list and filtered delete calls may omit `arguments.project` and select targets through `options.project` or the default project scope. The agent cannot pass `yes`, switch profiles, or change server permissions through a tool call. ## Choose tools and permissions `--toolsets` selects groups. The default is `inspect,edit,drafts,plans,publish`; diagnostics is opt-in. Discovery lists only tools allowed by the selected groups, execution mode, and write permission. | Toolset | Workflows | | --- | --- | | `inspect` | Read parameters, projects, Firebase apps, groups, conditions, versions, experiments, rollouts, and personalizations; compare configurations and read defaults | | `edit` | Add, update, duplicate, and delete parameters; manage groups and conditions | | `drafts` | List, inspect, compare, annotate, and discard local drafts | | `plans` | Inspect and validate publication plans | | `publish` | Apply plans, publish drafts, import/export templates, promote between projects, restore/rollback versions, and delete experiments or rollouts | | `diagnostics` | Run `diagnostics.doctor` | All `edit` and `publish` tools require `--allow-writes`, as do `draft.change-note`, `draft.discard`, and explicit `to` or `plan-out` output. Mutation tools require write permission even for a dry run. `plan.apply` belongs to `publish`, not `plans`. The `versions.blame` inspection tool traces direct changes to one exact parameter key. Supply `arguments.project` and `arguments.parameter`; optional `options.at`, `options.limit`, and `options.all` match the CLI command, with `all` and `limit` mutually exclusive. Results include adjacent version transitions, publication metadata, and typed parameter diffs. For inspection only, use these host arguments: ```json ["mcp", "--profile", "personal", "--no-local-config", "--toolsets", "inspect"] ``` For read/write workflows with user approval: ```json ["mcp", "--profile", "personal", "--no-local-config", "--allow-writes"] ``` ::: warning Write authorization The default `--confirmation=host` requires the host to present an approval form for the exact tool and inputs. This uses MCP form elicitation. Without that support, the call returns an interaction-required error. `--confirmation=none` authorizes enabled writes without per-call approval. Use it only when you intend to run unattended. ::: Use [drafts](/cli/drafts.md) to compose changes and [plans](/cli/plans.md) to hand off an exact publication candidate. Multi-target publication is not atomic. Inspect every target's result before retrying a failed batch. Hooks are disabled unless `--allow-hooks` is set, and must pass the normal [trust checks](/reference/hooks.md). Inspection can refresh caches, synchronize the project registry, and persist refreshed credentials. `diagnostics.doctor` can create and remove local probe files. There are no tools for managing profiles, credentials, fbrcm configuration, aliases, hook trust, themes, or shell completion. The `apps.list`, `apps.show`, and `apps.config` tools can read Firebase app records and SDK configuration, but cannot create, change, or delete an app. They use the same one-hour app cache as the CLI. For `apps.show` and `apps.config`, `cached` requires a cache entry and forbids network access. For `apps.list`, `cached` accepts stale inventory but fetches it when absent. File paths refer to the machine running fbrcm and use its filesystem permissions. The server has no HTTP MCP endpoint, resources, prompts, or background-task API. ## Read tool results Completed calls return the [JSON envelope](/automation/json-contract.md#envelope) in `structuredContent`, with identical JSON in text `content`. Inspect `outcome`, `errors`, `warnings`, and `data` together. `success` maps to `isError: false`, including a changed diff with exit code `1`. `failure` and `partial_success` map to `isError: true`; partial results retain completed and failed target information. A tool failure does not stop the server. The envelope identifies the underlying operation rather than the public MCP name. Parameter tools use unprefixed operation IDs, so `parameters.get` returns `command: "get"`. `plan.apply` uses `apply`, and `diagnostics.doctor` uses `doctor`. Other tool names match their operation IDs. ## Authentication recovery OAuth access tokens normally refresh silently. When browser authorization is needed, a host with URL elicitation can offer sign-in: 1. fbrcm starts a temporary localhost callback listener and gives the host the sign-in URL. 2. The user approves navigation and signs in through the browser. 3. fbrcm receives the callback, exchanges the authorization code directly with Google, saves credentials, and closes the listener. 4. The suspended operation continues. Sign-in does not grant mutation approval. Tokens and authorization secrets do not pass through chat or tool arguments. Canceling, timing out, or disconnecting cleans up the sign-in attempt. With `--browser-auth=never`, or a host without URL elicitation, follow the returned remediation and sign in externally: ```sh fbrcm auth login example-auth-name --profile personal ``` Then retry the tool call. Credentials are reloaded for each operation, so reconnecting is not normally necessary. If fbrcm runs through SSH or in a container, the browser must be able to reach its localhost callback; external login may be more practical. ## Run without local state Use `--stateless` and supply `FBRCM_GOOGLE_ACCESS_TOKEN` securely through the host environment for Firebase calls. Do not paste the token into chat or commit it in a configuration file. Stateless execution uses no profiles, application configuration, caches, drafts, or hooks. You can still read and write files whose paths you supply. Remote mutations require the same write permission and approval as stateful execution. Discovery excludes the `drafts` and `plans` groups, `draft.publish`, `versions.restore`, and `diagnostics.doctor`. `plan.apply` supports stateless plans. `--stateless` cannot be combined with `--profile` or `--allow-hooks`. Environment tokens are not refreshed. Renew them externally and restart the subprocess with the updated environment; there is no profile or browser fallback. ## Timeouts and logs | Setting | Default | Scope | | --- | --- | --- | | `--request-timeout` | `5m` | One operation, including queueing and user interaction | | `--auth-timeout` | `2m` | One browser sign-in attempt | | `--timeout` | Unlimited | Entire server lifetime | Explicit durations must be positive; the earliest applicable deadline wins. Your host may impose a shorter timeout. Tool operations execute one at a time, while discovery stays responsive. Disconnecting cancels work; inspect Firebase state before retrying an interrupted mutation. Logs go to stderr as plain text without terminal escape codes. Set `FBRCM_LOG_LEVEL` to control verbosity and `FBRCM_LOG_NO_TIMESTAMP` to omit timestamps. Inspector shows these logs in its Server Console; they are not MCP logging notifications. External hook output is not sanitized by the logger. ## Test with Inspector No agent or Firebase credentials are needed for this smoke test. With `fbrcm` available on your `PATH` and Node.js 22.19 or newer installed, run: ```sh npx @modelcontextprotocol/inspector fbrcm mcp -- --stateless --toolsets inspect ``` Open Inspector's local URL and connect. Select `parameters.get`, switch to **Edit as JSON**, and execute: ```json { "stdin": { "parameters": { "smoke_test": {"defaultValue": {"value": "hello"}} } } } ``` Expect `structuredContent.outcome: "success"`, `exit_code: 0`, and `data.count: 1`. The call reads the supplied document without contacting Firebase. In the generated form, enter only the document starting with `{"parameters": ...}` inside the `stdin` field, not the enclosing tool input. Inspector's web launcher consumes the `--` separator. When launching fbrcm directly, use `fbrcm mcp --stateless --toolsets inspect` without that separator. Inspector's **Legacy** and **Modern** protocol modes both support this test; protocol selection is independent of fbrcm's `--stateless` execution policy. For the complete tool catalog and schema-validation checks, see the [MCP reference](https://github.com/yumauri/fbrcm/blob/main/docs/MCP.md). --- Source: [/reference/commands.md](/reference/commands.md) # Command index Use this page to find a command. Run `fbrcm help ` for its full set of flags, or `fbrcm capabilities --json` for a machine-readable definition from the installed binary. Run `fbrcm setup` for guided CLI setup, or follow the [manual CLI setup](/guide/index.md#manual-cli-setup) before using project or Remote Config commands for the first time. ## Parameters and structure | Command | Purpose | | --- | --- | | `add` | Add one parameter to selected targets | | `duplicate` | Copy a parameter under a new key | | `get` | Read and filter parameters | | `update` | Change selected parameters | | `delete` | Delete selected parameters | | `groups list` | List parameter groups | | `groups add` | Create an empty or described group | | `groups edit` | Change a group description | | `groups rename` | Rename a group | | `groups delete` | Delete a group and its parameters | ## Conditions | Command | Purpose | | --- | --- | | `conditions list` | List conditions in evaluation order | | `conditions show` | Inspect one condition and its usages | | `conditions add` | Add a condition | | `conditions edit` | Change the expression or display color | | `conditions rename` | Rename a condition and its references | | `conditions move` | Change evaluation priority | | `conditions delete` | Remove a condition and conditional values | | `conditions validate` | Validate condition expressions and references | ## Drafts | Command | Purpose | | --- | --- | | `draft list` | List healthy and recoverable drafts | | `draft path` | Print the draft directory | | `draft show` | Inspect or export a draft candidate | | `draft change-note` | Set or clear its Firebase version note | | `draft diff` | Compare against the base or current Firebase state | | `draft publish` | Validate and publish drafts | | `draft discard` | Remove local draft state | ## Plans | Command | Purpose | | --- | --- | | `plan show` | Verify a publication plan and show its targets and diffs | | `plan validate` | Verify publication plan structure and integrity | | `apply` | Preflight and apply the exact candidates in a publication plan | ## Projects and templates | Command | Purpose | | --- | --- | | `projects list` / `update` | Inspect or synchronize accessible projects | | `projects forget` / `reset` | Remove selected or all local project state | | `projects diff` | Compare two template targets | | `projects promote` | Transfer selected configuration to another target | | `projects aliases ...` | List, set, remove, or import repository aliases | | `projects path` | Print the project registry path | | `project show` | Inspect one project registration | | `project templates show/set` | Inspect or change enabled template types | | `project quota-project show/set/unset` | Inspect or override one project's quota project | | `project open` | Open or return the Firebase Console URL | | `project export` / `import` | Move Remote Config documents | | `project defaults` | Download application defaults | ## Firebase applications | Command | Purpose | | --- | --- | | `apps list` | List registered Android, iOS, and Web apps | | `apps show` | Inspect one app and its platform-specific details | | `apps config` | Download an app's Firebase SDK configuration | These are read-only Firebase Management operations. See [Firebase applications](/cli/apps.md) for selection and cache behavior. ## History and managed features | Command | Purpose | | --- | --- | | `versions list/show` | Inspect Remote Config history | | `versions blame` | Trace direct changes to one parameter | | `versions diff` | Compare historical or current templates | | `versions export` | Export one historical template | | `versions rollback` | Ask Firebase to roll back to a retained version | | `versions restore` | Republish a locally cached snapshot | | `experiments list/show/delete` | Inspect or delete A/B tests | | `rollouts list/show/delete` | Inspect or delete rollouts | | `personalizations list/show` | Inspect personalization bindings | ## Local environment | Command | Purpose | | --- | --- | | `setup` | Guide authentication and Firebase project discovery | | `doctor` | Diagnose credentials, APIs, connectivity, and storage | | `cache list/path/clear` | Inspect or remove cached templates and Firebase app data | | `config path/show/set/reset/validate/edit` | Manage configuration | | `hooks status/fingerprint/trust/untrust` | Manage repository hook trust | | `auth list/add/login/path/delete` | Add, validate, inspect, or remove identities | | `auth quota-project show/set/unset` | Manage an identity's default quota project | | `auth bind` | Select the identity used by saved projects | | `profile list/switch/rename/path/delete` | Manage isolated workspaces | | `theme list/switch/reset/path/rename/delete/import` | Manage palettes | | `completion` | Generate shell completion scripts | ## Machine discovery | Command | Purpose | | --- | --- | | `mcp` | Start the [MCP server](/automation/mcp.md) for an AI application | | `capabilities` | Describe commands, inputs, schemas, and side effects | | `schema list` | List published JSON schemas | | `schema show` | Return one JSON Schema document | --- Source: [/reference/compatibility.md](/reference/compatibility.md) # Compatibility from 1.0.0 fbrcm 1.0.0 establishes a stable application interface and a released CLI JSON contract `1.0.0`. The release, JSON contract, negotiated MCP protocol, and file formats have separate versions. Existing integer file-format versions stay at `1`; the pre-1.0 in-place breaking-change exception has ended. | Surface | Stability promise | | --- | --- | | Documented CLI syntax and behavior | Compatible throughout fbrcm 1.x: commands, arguments, flags, defaults, selection, effects, confirmations, environment variables, and exit meanings | | JSON envelopes and schemas | Versioned compatibility for DTOs, codes, details, capability metadata, semantic rules, and artifacts | | MCP tools | Stable public names, operation mappings, launch policy, discovered contracts, results, and authorization behavior for the same server configuration | | Durable data | 1.0.0 configuration, identities, preferences, custom key configurations, themes, hook trust, drafts, retained snapshots, and plans remain readable on 1.x upgrades, directly or through a documented migration | Breaking a supported interface requires an application major release. Incompatible JSON changes also require a contract major version. Compatible additions use minor versions; fingerprinted clarifications with no validation or semantic change may use a contract patch version. Closed enums are not implicitly extensible. Use the installed binary's advertised `schema` and `contract_version` with its schemas. Published schema IDs are immutable. There is no CLI output-version negotiation flag; pin a binary release if you require an exact contract version. MCP protocol negotiation is separate from the shared JSON envelope version. ## What is not a stable integration interface - **Human tables:** columns, widths, labels, borders, colors, logs, progress, help wording, and prompts may change. Use JSON or MCP for automation. - **Default TUI bindings and layouts:** shortcuts, panels, and mouse flows may evolve. Supported custom key-configuration syntax and saved action identifiers remain durable configuration and require compatibility or a documented migration. - **Exported Go packages:** fbrcm is an application, not a supported Go library. Exported symbols may change in any release. Transient rebuildable caches may be invalidated. Drafts and retained version snapshots are protected durable data even under a cache root. The promise covers upgrades from 1.0.0, not arbitrary pre-1.0 data, future files, or downgrades. Explicit user deletion and credential replacement keep their documented effects. The released CLI lock rejects a changed generated fingerprint at the same contract version, and the release workflow refuses an unreleased lock. That fingerprint does not replace MCP or persisted-format compatibility review. See the full [compatibility policy](https://github.com/yumauri/fbrcm/blob/main/docs/compatibility.md) for versioning, migration, and release requirements. --- Source: [/reference/configuration.md](/reference/configuration.md) # Configuration fbrcm combines built-in defaults, global user configuration, and an optional repository configuration file. Valid 1.0.0 configuration and durable data remain readable during 1.x upgrades, directly or through a documented migration. Existing integer format versions remain `1`. See [compatibility guarantees](/reference/compatibility.md) for the distinction between durable data and rebuildable caches. ## Configuration layers Global settings live in `config.toml` under the operating system's user config directory. At startup, fbrcm searches the current directory and its parents for the nearest `.fbrcm.toml`. Nested tables merge; repository scalars and arrays replace the global value. Inspect the effective result and file locations: ```sh fbrcm config show fbrcm config path fbrcm config path --scope local fbrcm config validate ``` Use `--no-local-config` or `FBRCM_NO_LOCAL_CONFIG=1` to ignore `.fbrcm.toml` for one process. ## Change settings ```sh fbrcm config set network.max_concurrent_requests 3 fbrcm config set theme nord --scope local fbrcm config reset theme --scope local fbrcm config edit ``` Set the logging level with `FBRCM_LOG_LEVEL`. It is not a persisted `config set` key. `config edit` validates the staged file before replacing the active one. The editor comes from `--editor`, `FBRCM_EDITOR`, `VISUAL`, then `EDITOR`. ## Repository aliases Commit stable project names with the repository: ```toml [projects.aliases] staging = "example-staging-project-id" prod = "example-production-project-id" ``` The aliases are profile-independent. fbrcm also reads Firebase CLI aliases from the `.firebaserc` associated with the nearest Firebase project root. ## Useful environment variables | Variable | Purpose | | --- | --- | | `FBRCM_PROFILE` | Select an existing profile for one process | | `FBRCM_CONFIG_DIR` | Override the fbrcm config root | | `FBRCM_CACHE_DIR` | Override the fbrcm cache root | | `FBRCM_OFFLINE` | Disable network use whenever the variable is defined | | `FBRCM_LOG_LEVEL` | Set `debug`, `info`, `warn`, `error`, `fatal`, or `silent` | | `FBRCM_EDITOR` | Select an editor command and arguments | | `FBRCM_NO_LOCAL_CONFIG` | Ignore repository configuration | | `FBRCM_HOOK_TRUST` | Trust the exact [repository hook](/reference/hooks.md) fingerprint in CI | | `NO_COLOR` | Disable color for any non-empty value | | `GOOGLE_CLOUD_QUOTA_PROJECT` | Select the Google Cloud quota/billing project | | `HTTPS_PROXY`, `HTTP_PROXY`, `NO_PROXY` | Configure the HTTP transport | ## Quota and billing project Every authenticated Firebase and Cloud Resource Manager request carries `X-Goog-User-Project`. fbrcm resolves it in this order: 1. `GOOGLE_CLOUD_QUOTA_PROJECT` 2. the selected project's persisted override 3. the selected auth identity's persisted default 4. ADC `quota_project_id`, for gcloud auth only 5. the physical target Firebase project If a targetless request cannot resolve a value, fbrcm stops before network access. The syntax for persisted values is: ```text fbrcm auth quota-project show fbrcm auth quota-project set fbrcm auth quota-project unset fbrcm project quota-project set fbrcm project quota-project unset ``` For example: ```sh fbrcm auth quota-project show example-auth-name fbrcm auth quota-project set example-auth-name example-quota-project-id fbrcm auth quota-project unset example-auth-name fbrcm project quota-project set example-project-id example-quota-project-id fbrcm project quota-project unset example-project-id ``` `example-auth-name` is a local auth ID. The other values are Google Cloud project IDs. See [Authentication and project discovery](/guide/authentication.md) for the first-run setup and the distinction between these identifiers. The authenticated principal needs `serviceusage.services.use` on the effective quota project. The guided first-run setup also asks for an auth-level quota project. ## Network controls Authenticated requests share concurrency, pacing, rate-limit cooldown, and retry policies. The main keys are: ```text network.max_concurrent_requests network.requests_per_minute network.rate_limit_cooldown network.retry.max_attempts network.retry.base_delay network.retry.max_delay network.retry.jitter_percent ``` Defaults allow five concurrent requests, disable proactive per-minute pacing, and make up to five replayable attempts with bounded exponential delay. A Firebase `Retry-After` header takes precedence over calculated waits. --- Source: [/reference/filtering.md](/reference/filtering.md) # Filtering and expressions Use `--project` and `--filter` to match project names and parameter keys. Use `--search` to search text fields, or `--expr` to select typed Remote Config data. ## Query modes Flags named `--project` or `--filter` accept a mode prefix: | Prefix | Mode | | --- | --- | | none or `~` | Fuzzy match | | `^` | Starts with | | `/` | Contains | | `=` | Exact, case-insensitive | ```sh fbrcm get --project '^acme-prod' --filter '^checkout_' fbrcm get --project '=example-project-id' --filter '=feature_enabled' ``` Repeated values of the same selector are ORed. Different selector sources are ANDed: for example, a parameter must satisfy `--filter`, `--group`, `--search`, and `--expr` when all four are supplied. Project queries match display names, project IDs, and repository aliases. Parameter filters match keys. Positional resource names are different: they match canonical names or IDs exactly and case-sensitively. ## Search Parameter search covers keys, descriptions, groups, and values. Condition search covers names, expressions, colors, and usage data. Search and expressions compose with the other filters rather than replacing them. ## Expression language `--expr` uses expr-lang and must evaluate to a boolean: ```sh fbrcm get --expr 'value == true' fbrcm get --expr 'default > 10' fbrcm get --expr 'name startsWith "checkout_"' fbrcm get --expr 'conditionals["Beta users"] == true' ``` Invalid expressions are errors. They never silently become an empty result. ## Parameter context Parameter expressions expose `project_id`, `project`, `conditions`, `groups`, `parameters`, `name`, `group`, `default`, `value`, and `conditionals`. - `default` is only the default slot. - `value` matches the default or any conditional slot. - `conditionals` selects a value for one named condition. - root-group parameters compare as `group == "(root)"` in normal parameter contexts. Firebase values are typed from `valueType`: BOOLEAN becomes boolean, NUMBER becomes numeric, and STRING and JSON remain strings. Compatibility comparisons allow a stored boolean or number to match its string representation. ## Condition context `conditions list --expr` and `conditions delete --expr` expose `name`, `priority`, `expression`, `color`, `usage_count`, and `usages`, plus the project fields: ```sh fbrcm conditions list example-project-id --expr 'usage_count == 0' fbrcm conditions list example-project-id --expr 'priority <= 5' fbrcm conditions list example-project-id \ --expr 'any(usages, #.parameter startsWith "legacy_")' fbrcm conditions delete --expr 'expression contains "deprecated.property"' --dry-run ``` ## Project context Project expressions expose `project_id`, `project`, `conditions`, `groups`, and the complete `parameters` map: ```sh fbrcm projects list --expr 'project_id startsWith "test-"' fbrcm projects list --expr '"feature_enabled" in keys(parameters)' fbrcm projects list --expr 'parameters["feature_enabled"].value == true' ``` ## Helpers and JSON values fbrcm adds `is_number`, `is_string`, `is_json`, `is_boolean`, `is_empty`, and an embedded gojq implementation: ```sh fbrcm get --expr 'is_string(value) && is_empty(value)' fbrcm get --expr 'value | jq(.enabled == true)' fbrcm get --expr '(default | jq(.limit)) > 10' ``` No external `jq` executable is required. Invalid JSON values simply do not match a `jq(...)` predicate. --- Source: [/reference/hooks.md](/reference/hooks.md) # Publication hooks Hooks run local commands before or after fbrcm publishes Remote Config. A `pre_publish` hook can reject a candidate. A `post_publish` hook can notify another system after Firebase accepts the publication. fbrcm does not run hooks unless you configure them. ## Configure hooks Add hooks to the global `config.toml` or a repository `.fbrcm.toml`. Use `fbrcm config edit` for the global file or this command for the repository file: ```sh fbrcm config edit --scope local ``` ```toml [hooks] timeout = "2m" pre_publish = [ "./scripts/validate-parameter-names.sh", "go run ./tools/validate-remote-config", ] post_publish = ["./scripts/notify-remote-config-published.sh"] ``` Commands run in order through `/bin/sh -c` on Unix-like systems and `cmd.exe /S /C` on Windows. The timeout applies separately to each command and defaults to five minutes. Repository hook arrays replace the corresponding global arrays instead of extending them. Run `fbrcm config validate` after editing the file. Empty commands, invalid durations, and non-positive timeouts make the configuration invalid. ## When hooks run | Hook | Runs | Failure result | | --- | --- | --- | | `pre_publish` | After Firebase validates the final candidate and before publication | Stops publication | | `post_publish` | After Firebase accepts a real publication | Reports failure, but cannot undo publication | `pre_publish` also runs during a publication dry run. This lets CI check the same policy without writing to Firebase. `post_publish` does not run for dry runs or failed publications. Saving or previewing a draft does not run hooks. Publishing a draft does. Direct changes, imports, promotions, restores, rollbacks, and their TUI equivalents use the same lifecycle. No-op operations do not run hooks. For commands that select several targets, fbrcm runs each target's hooks in order. A failure does not prevent it from processing independent targets. ## Files available to a hook For each publication, fbrcm creates a private temporary directory containing JSON files. It passes each file path to the hook in an environment variable: | Environment variable | Value | | --- | --- | | `FBRCM_CURRENT_FILE` | Path to `current.json`, containing Remote Config before the change | | `FBRCM_CANDIDATE_FILE` | Path to `candidate.json`, containing the validated candidate | | `FBRCM_CONTEXT_FILE` | Path to `context.json`, containing hook and publication metadata | | `FBRCM_PUBLISHED_FILE` | Path to `published.json` after publication; empty before publication | For example, a Unix shell hook can read the candidate with: ```sh jq . "$FBRCM_CANDIDATE_FILE" ``` The template files are read-only. Changing them does not change the candidate sent to Firebase. fbrcm removes the temporary directory after the operation. fbrcm also adds these metadata environment variables to the hook process: ```text FBRCM_HOOK_EVENT pre_publish or post_publish FBRCM_OPERATION originating operation FBRCM_TARGET canonical client or server template target FBRCM_PROJECT_ID Firebase project ID FBRCM_TEMPLATE_KIND client or server FBRCM_PROFILE selected profile FBRCM_DRY_RUN true or false FBRCM_CHANGE_NOTE publication change note, possibly empty FBRCM_CONFIG_FILE config file that supplied the hook FBRCM_PROJECT_DIR directory containing that config file ``` `GCLOUD_PROJECT` contains the same value as `FBRCM_PROJECT_ID`, and `PROJECT_DIR` contains the same value as `FBRCM_PROJECT_DIR`. The command runs with the directory containing its source configuration file as the working directory. ## Trust repository hooks Global hooks are trusted automatically because they come from your user configuration. Repository hooks execute code from the checked-out project, so fbrcm requires explicit trust before running them. Review the effective commands first: ```sh fbrcm hooks status fbrcm hooks fingerprint ``` Then trust the current repository definition: ```sh fbrcm hooks trust ``` fbrcm stores trust outside the repository. The record includes the canonical configuration path and a SHA-256 fingerprint of the effective commands and timeout. Changing the path, commands, or timeout invalidates trust. Remove stored trust with: ```sh fbrcm hooks untrust ``` For CI, set `FBRCM_HOOK_TRUST` to the exact value printed by `fbrcm hooks fingerprint`. A missing or mismatched value stops the operation before any Firebase write. ## Failures and output A nonzero exit, timeout, signal, or shell error fails the current hook stage. CLI mode writes hook output to stderr, which keeps JSON stdout valid. The TUI writes it to the Logs panel. A `pre_publish` failure means Firebase was not changed. A `post_publish` failure means Firebase accepted the publication before the hook failed. Inspect the hook and the published version before retrying, because another publication may create another Remote Config version. JSON mode reports hook failures with status 14 and structured error details. After a successful Firebase write, a post-hook failure appears as a post-publication warning or a result such as `published-hook-failed`. ## Stateless mode `--stateless` disables configured hooks. Stateless commands do not read global or repository hook configuration and do not use stored hook trust. --- Source: [/reference/themes.md](/reference/themes.md) # Themes One theme controls human-readable CLI output, prompts, logs, and the TUI. Press `Ctrl+T` in the TUI to preview installed themes live. ## Select and manage themes ```sh fbrcm theme fbrcm theme list fbrcm theme switch nord fbrcm theme switch nord --scope local fbrcm theme reset --scope local fbrcm theme path nord ``` fbrcm stores a local selection in `.fbrcm.toml`. Custom theme files live in the user-wide `themes` directory next to global `config.toml`. Import one file, a directory, stdin, a raw HTTPS URL, or a repository browser URL: ```sh fbrcm theme import ./nord.toml fbrcm theme import ./theme-pack/ fbrcm theme import --name nord < ./nord.toml fbrcm theme import https://example.com/themes/nord.toml fbrcm theme import https://github.com/yumauri/fbrcm/tree/main/themes fbrcm theme import https://github.com/yumauri/fbrcm/blob/main/themes/aurora.toml fbrcm theme import https://gitlab.com/company/team/theme-pack/-/tree/main/themes ``` fbrcm validates imports before writing. A single-file import rejects an existing destination. A directory import skips existing names and reports warnings. GitHub.com and GitLab.com browser links support branches, tags, and commit SHAs. Repository directories import top-level regular `.toml` files, with all files read from one resolved commit. Symlinks, submodules, and nested directories are skipped. If a ref containing slashes is ambiguous, use `--ref feature/colors` to identify the exact revision prefix already in the URL. Private GitHub repositories use `GH_TOKEN`, falling back to `GITHUB_TOKEN`, with Contents read permission. Private GitLab repositories use `GITLAB_TOKEN` with `read_api` access. Tokens are never persisted or passed to generic HTTP sources. Repository browser imports support the two public service hosts; self-hosted instances and automatic `gh`/`glab` authentication are not supported. Each file is limited to 1 MiB. Repository batches select at most 256 themes and download at most 16 MiB of theme data; existing themes are skipped before their contents are downloaded. Download and validation failures install no themes. Offline mode suppresses network imports. JSON results include the requested ref and resolved commit in `repository_source`. See [CLI reference](/reference/commands.md) for URL syntax, source errors, and all resource limits. ## Theme file A file may override any subset of the built-in palette: ```toml [colors] primary = "#88C0D0" selection = "#4C566A" text = "#ECEFF4" text_muted = "#A3ABB8" error = "#BF616A" ``` Colors accept `#RGB`, `#RRGGBB`, or a quoted ANSI index from `"0"` through `"255"`. Unknown top-level fields or color tokens invalidate the theme. ## Inheritance Themes can inherit another installed theme: ```toml inherits = "base" [colors] primary = "#88C0D0" ``` Resolution starts from the built-in palette, applies the oldest ancestor, then the selected child. Missing parents, cycles, and chains deeper than 16 files invalidate the selected theme. ## Failure behavior Normal startup warns and falls back to the complete built-in palette when a selected theme is invalid. Explicit configuration commands such as `config validate` remain strict so configuration problems can be caught in CI. `NO_COLOR` disables color and skips theme application. JSON and stateless modes also skip startup theme loading. --- Source: [/reference/troubleshooting.md](/reference/troubleshooting.md) # Troubleshooting Start with the integrated diagnostic: ```sh fbrcm doctor fbrcm doctor --json ``` It checks credentials, connectivity, Firebase and Cloud Resource Manager API access, permissions, quota-project configuration, and local storage. `doctor` expects `cloudconfig.configs.get`, `cloudconfig.configs.update`, `firebase.clients.list`, and `firebase.clients.get` on cached Firebase projects. A deliberately read-only identity can still use read commands even though the Remote Config update-permission check fails. ## No projects appear Synchronize the registry: ```sh fbrcm projects list --update ``` If discovery still fails, verify that the selected identity can list projects and read Remote Config. A configured quota project also requires `serviceusage.services.use` for the authenticated principal. ## Authentication needs attention Inspect identities and log in again: ```sh fbrcm auth list fbrcm auth login example-auth-name fbrcm auth quota-project show example-auth-name ``` Replace `example-auth-name` with the auth ID shown by `fbrcm auth list`. OAuth may require a browser in human mode. JSON mode never opens one and returns structured interaction details instead. Service-account and gcloud identities validate their existing credentials without an OAuth browser flow. If project discovery reports that a quota project is required, set an auth-level default. The two positional arguments are the local auth ID and the physical quota project ID: ```sh fbrcm auth quota-project set example-auth-name example-quota-project-id ``` For a single cached Firebase project, inspect or override the selection with: ```sh fbrcm project quota-project show example-project-id fbrcm project quota-project set example-project-id example-quota-project-id fbrcm project quota-project unset example-project-id ``` ADC `quota_project_id` is considered only for gcloud identities. `fbrcm doctor` verifies both resolution and `serviceusage.services.use` access. ## Reads look stale Force a live cache revalidation: ```sh fbrcm get --project '=example-project-id' --update ``` Check whether a local draft is active, because normal effective reads include draft state. Use `draft diff` to inspect it, or `draft discard` only when that local intent is no longer needed. ## Offline mode appeared unexpectedly The TUI enters offline mode after its startup connectivity probe fails. The CLI enters offline mode whenever `FBRCM_OFFLINE` is defined, even as an empty value or `0`. Check proxy variables and unset the override when live access is intended: ```sh unset FBRCM_OFFLINE ``` ## A write reports a conflict Another client changed Firebase after fbrcm loaded the template, or a draft rebase found overlapping local and remote edits. Refresh current state and review again. Do not blindly retry a complete-template publication. Draft conflicts preserve the draft. Use: ```sh fbrcm draft diff example-project-id --against current ``` ## An editor does not return GUI editors must wait for the staged file to close: ```sh FBRCM_EDITOR="code --wait" fbrcm ``` For CLI configuration editing, the same setting applies to `fbrcm config edit`. ## The TUI is too small The minimum supported terminal size is 80 columns by 20 rows. Enlarge the window or reduce terminal font size. Human CLI tables adapt to narrow widths independently. ## JSON automation did not perform an action Inspect `outcome`, `exit_code`, and the structured problems. Status 10 means the operation requires explicit interaction such as `--yes`, an import merge choice, OAuth authorization, or overwrite approval. Follow the published remediation strategy only after checking authorization and target scope.