Home CLI guides

CLI guides

Use the CLI guides to understand which Firestruct and Firebase workflows can be performed from a terminal and which currently require the native macOS app. The articles cover project selection, local emulator configuration, Firestore reads and administrative commands, Firebase Authentication operations, Cloud Storage automation, imports and exports, index inspection, seed data, task execution, migration files, workspace configuration, push workflows, support, and purchase-related boundaries. Each guide documents the available command shape where terminal support exists and clearly identifies app-only or planned behavior where it does not. Safety guidance is included for production targets, destructive operations, path validation, overwrite handling, explicit confirmation, queued work, progress reporting, and actionable failures. Use this category before scripting a workflow so you can verify the supported interface, preserve Firestruct guardrails, and avoid assuming that a macOS workspace feature already has CLI parity.
By Tomas Radvansky
14 articles

Foundation and App Shell CLI

Purpose The CLI mirrors core workspace concepts for automation: project selection, module selection, JSON output, and shared access to FirestructCore services. Executable Layout - Sources/FirestructCLI/main.swift is the thin executable. - Sources/FirestructCLIKit parses arguments, loads local state, dispatches commands, and encodes JSON output. - Sources/FirestructCore provides the same project, query, and write services used by GUI flows. Global Behavior - help and --help print usage. - Missing commands, missing actions, invalid flags, and unknown commands exit with code 1. - Successful command payloads are JSON unless the command is help text. - --project <name|firebaseProjectID|uuid> overrides the selected project for supported commands. Current Command Groups project connect project list project select project databases list project databases add project databases select module list module select firestore query firestore export firestore backup firestore import firestore transfer firestore schema firestore run-js firestore saved-query firestore saved-script firestore embedding-config firestore embedding-generate firestore create firestore update firestore delete tasks list tasks show tasks retry tasks cancel auth list auth search auth create auth update auth delete auth disable auth enable auth export auth import auth transfer auth run auth tenants list auth tenants select auth tenants current auth routes list auth routes set auth routes enable auth routes disable auth routes delete auth routes resolve-auth auth routes resolve-firestore storage buckets storage list storage upload storage upload-folder storage download storage download-batch storage zip storage zip-folder storage inspect storage copy storage move storage delete-folder storage copy-folder storage move-folder storage rename-folder storage duplicate-folder storage delete storage url storage signed-url release preflight index-advisor analyze index-advisor parse-error index-advisor load-indexes seed import-template seed generate seed export-template seed apply seed diff workspace link workspace status workspace diff workspace deploy pitr load pitr diff pitr restore push validate push resolve-tokens push send migrations status migrations show migrations record-applied migrations apply run <selected-module-action> Release Preflight release preflight is an operator-oriented command that classifies local release evidence and returns JSON with an overall pass, warning, or fail status plus individual checks and remediation. release preflight release preflight --skip-storekit --ui-smoke-output-file smoke.log --ui-smoke-exit-code 0 --ui-smoke-result-bundle build/smoke.xcresult release preflight --require-full-ui --full-ui-output-file full-ui.log --full-ui-exit-code 0 --full-ui-result-bundle build/full-ui.xcresult release preflight --require-storekit-transaction --storekit-transaction-output-file storekit.log --storekit-transaction-exit-code 0 --storekit-transaction-evidence build/storekit.xcresult The command can run local StoreKit tooling checks, classify captured focused UI smoke output, require full emulator UI/E2E evidence, and require captured StoreKit purchase/restore evidence. It also reports the current no-endpoint boundary for app-owned update/license checks. Supplying captured output classifies that evidence; it does not run the UI or StoreKit transaction suites itself. Module Selection module select <module> saves the selected module. run <action> dispatches to the selected first-class CLI module when supported. Known module names accepted by module select: firestore auth storage index-advisor seed-studio workspace-link pitr push migrations The CLI module list is narrower than the GUI module list. Support, Purchases, and Settings do not currently expose first-class CLI command groups. Tasks has a first-class CLI for current-process task inspection and durable completed-task history. release preflight is a standalone operator command and is not selectable as a workspace module. Source Anchors - Sources/FirestructCLI/main.swift - Sources/FirestructCLIKit/FirestructCLI.swift - Sources/FirestructCLIKit/CLIArguments.swift - Sources/FirestructCLIKit/CLIStateStore.swift - Sources/FirestructCLIKit/ModuleCommand.swift

Last updated on Jul 12, 2026

Project Registry CLI

Purpose The project CLI manages local project links and the selected project used by other CLI commands. Use it to prepare repeatable emulator, development, or production targets before running Firestore, Auth, or Storage commands. The registry keeps local metadata only; connecting a project does not create, modify, or delete Firebase resources. That separation lets teams script local setup while preserving Firestruct's production confirmation rules in the modules that actually mutate data. Connect a Project project connect --name Local --project-id demo-firestruct --environment emulator --host localhost --port 8080 Aliases: project add ... projects connect ... projects add ... Options: - --name is required. - --project-id is required. - --environment accepts emulator, development, or production; default is emulator. - --read-only marks the project read-only. - --host sets the emulator host. - --port sets the Firestore emulator port. - --auth-port sets the Auth emulator port. - --storage-port sets the Storage emulator port. - --database sets the selected Firestore database ID; default is the Firestore default database. On success the command saves the project, selects it, and returns JSON under connected. For emulator projects, include host and port values so downstream commands can send requests to the local Firebase Emulator Suite without extra flags. For live projects, store the project ID and environment label, then pass authorization to the individual service commands that need live Firebase access. List Projects project list Returns JSON: { "projects": [] } Each project payload includes selection state. Select Project project select Local project select --project demo-firestruct The identifier can be the local name, Firebase project ID, or UUID. Selection is stored in CLI state for future commands. The selected project is the default target, but supported commands can still override it with --project <name|firebaseProjectID|uuid>. Prefer explicit overrides in automation and CI-like scripts so a previous interactive selection does not send a command to the wrong Firebase project. For production runbooks, print or inspect the selected project before any mutation command and keep the environment label visible in the captured output. Discover And Select Firestore Databases project databases list project databases list --configured project databases add customer-data project databases add customer-data --select project databases select customer-data project databases list refreshes the configured database IDs. For development and production projects it calls the Firestore database-management API and requires --access-token or --authorization "Bearer <token>". Emulator projects use their locally configured database list. Pass --configured for a read-only local view with no network request. project databases add validates and persists a database ID without calling Firebase. --select makes it active immediately. project databases select only accepts a discovered or previously added database. The selected database is stored in the project registry and becomes the default for Firestore commands. Database IDs must be (default) or a valid Firestore database ID using lowercase letters, numbers, and hyphens. Route-specific Auth-to-Firestore commands restore their configured database explicitly, even when a different database is selected interactively. If a project link is no longer needed, remove it through the app or reset the local CLI state as part of a controlled cleanup. Removing local registry data does not remove remote Firebase data, service accounts, emulator data, or App Store entitlements. Source Anchors - Sources/FirestructCLIKit/ProjectCommand.swift - Sources/FirestructCLIKit/CLIStateStore.swift - Sources/FirestructCLIKit/JSONOutput.swift - Sources/FirestructCore/FirestoreDatabaseDiscoveryService.swift

Last updated on Jul 12, 2026

Firestore CLI

Purpose The Firestore CLI covers queries, embeddings, export/import/backup/transfer workflows, saved queries and scripts, schema analysis, local JavaScript execution, and guarded document writes through shared FirestructCore services. Query Documents firestore query --collection users --limit 50 firestore query --collection users --where "role == admin" --order-by "createdAt desc" firestore query --project demo-firestruct --collection users --limit 0 firestore query --collection products --limit 12 --vector-field embedding --vector "[0.1,0.2,0.3]" --distance-measure cosine --distance-result-field vector_distance Options: - --collection is required and accepts a collection path. - --limit defaults to 50; 0 means no explicit limit where supported by the service. - --where accepts Firestruct simple-query syntax. - --order-by accepts comma-compatible parsed order clauses from the query service. - --vector-field and --vector switch the query into Firestore REST findNearest request-shape mode. - --distance-measure accepts euclidean, cosine, or dot-product; it defaults to cosine. - --distance-result-field and --distance-threshold pass through to the vector query options. - --project optionally overrides selected project. Output contains: - selected project JSON - query metadata, including vector dimension count and distance options when supplied - documents - logs Current automated vector coverage proves CLI argument parsing, invalid-vector rejection before network, findNearest REST body construction through the real FirestoreSimpleQueryService, returned distance-field decoding, and machine-readable query.vector.requiresFirebaseVectorVerification. It does not prove Firebase vector ranking behavior. That still needs a Firebase emulator or approved live Firebase target that supports vector search before completion can be claimed. Embedding Provider Configuration firestore embedding-config set --provider openai --model text-embedding-3-small --vector-field embedding --source-fields title,body --credentials-reference env:OPENAI_API_KEY firestore embedding-config set --provider custom-http --model custom-embedder --vector-field vectors.search --source-fields title,body --endpoint https://embeddings.example.test/v1/embed --credentials-reference keychain://firestruct/embeddings firestore embedding-config show firestore embedding-config delete --confirm firestore embedding-generate --collection articles --limit 100 --confirm Options: - --provider accepts openai, vertex-ai, or custom-http; it defaults to openai. - --model, --vector-field, and --source-fields are required for set. - --source-fields accepts comma-separated or newline-separated field paths. - --batch-size defaults to 100 and must be between 1 and 500. - --credentials-reference must be a local reference such as env:OPENAI_API_KEY, keychain://..., or file://...; raw provider API keys are rejected. - --endpoint is required for custom-http and must be an absolute HTTP or HTTPS URL. Output includes selected project JSON, the project/database-scoped config key, normalized config metadata, providerAPICalled: false, batchGenerationStarted: false, and executionMode: local-embedding-provider-config. embedding-config only manages local per-project configuration. It does not call OpenAI, Vertex AI, or custom embedding endpoints, and it does not generate or write embedding vectors. embedding-generate currently supports selected Firestore emulator projects with saved custom-http provider config. It requires --confirm, rejects read-only or non-emulator projects, queries the requested collection, POSTs { "model": "...", "inputs": [...] } batches to the configured endpoint, writes returned numeric embedding arrays to the configured field through Firestore REST arrayValue, and returns selected project JSON, embedding-generation counters, firestoreValueEncoding, writesNativeFirestoreVectorValues: false, logs, and a task snapshot. Current automated proof starts a real Firebase emulator and a real loopback HTTP embedding provider, runs the CLI command, asserts the provider request body, verifies task success/counters, and reads Firestore back to prove numeric arrays were written. Native Firestore vector-value writes, OpenAI/Vertex execution, live Firestore embedding writes, and Firebase vector ranking behavior still require approved verification before completion can be claimed. Export Query Results firestore export --collection users --format json --output users.json firestore export --collection users --format jsonl --output users.jsonl --include-path firestore export --collection users --format csv --output users.csv --include-path firestore export --collection users --format archive --output users.zip --include-path firestore export --collection firestruct_verification/run1/users --format json --output live-users.json --include-path --access-token "$TOKEN" Options: - --collection is required and uses the same query path rules as firestore query. - --format accepts json, jsonl, csv, or archive; it defaults to json. - --output is required and points to the destination file. - --limit, --where, and --order-by use the same parsing as firestore query. - --include-path writes __path__ into exported rows. - --no-document-id omits __id__; document IDs are included by default. - --access-token or --authorization is required for live projects. Output contains selected project JSON, query metadata, export metadata, combined query/export logs, and a task snapshot with status, operation counters, duration, attempt count, and error. Emulator-backed coverage validates JSON, JSONL, CSV, and archive output. Live request-shape and artifact coverage validates authorization, database routing, file output, and task counters; approved disposable live export and cleanup evidence remain open. Backup Collection firestore backup --collection users --output users-backup.zip firestore backup --collection users --where "role == owner" --output owners-backup.zip firestore backup --all-collections --output database-backup.zip firestore backup is a first-class archive command for selected collections or the discovered database tree. It writes archive format, includes both __id__ and __path__, and runs through the task queue. Collection backups default to no explicit query limit unless --limit is supplied. Whole-database backups discover root collections, query each collection path, recursively list subcollections below every discovered document, and archive every discovered document path. Options: - --collection backs up one collection path and uses the same query path rules as firestore query. - --all-collections backs up every discovered root collection and nested subcollection document path. - --output is required and points to the destination .zip file. - --limit, --where, and --order-by use the same parsing as firestore query for collection backups only. Whole-database backups reject --collection, --limit, --where, and --order-by when used with --all-collections so the command cannot silently create a partial database backup. Emulator-backed coverage validates collection and whole-database archive creation, task output, manifests, root documents, and recursively discovered subcollections. Import Documents firestore import --format json --file users.json --collection users --id-mode field-value --id-field docID --confirm firestore import --format json --file users.json --collection users --id-mode object-keys --confirm firestore import --format jsonl --file users.jsonl --collection users --id-field docID --confirm firestore import --format csv --file users.csv --collection users --id-column docID --type-hints '{"score":"int"}' --confirm firestore import --format archive --file users.zip --allow-overwrite --confirm firestore import --format archive --file users.zip --target-prefix archive_restore/run1 --confirm firestore import --format json --file live-users.json --collection firestruct_verification/run1/users --access-token "$TOKEN" --confirm Options: - --format accepts json, jsonl, csv, or archive; it defaults to json. - --file is required. - --collection is required for JSON, JSONL, and CSV imports unless CSV uses --absolute-path-column. - --confirm is required for every import. - --access-token or --authorization is required for live projects. - --production-confirm "IMPORT <project-id>" is required for production projects. - --allow-overwrite permits replacing existing emulator documents. - JSON supports --id-mode auto-generated|object-keys|field-value and --id-field. - JSONL supports --id-field. - CSV supports --id-column, --delimiter, --no-header, --absolute-path-column, --type-hints, and --column-mappings. - Archive accepts --target-prefix <parent-document-path> to import archived document paths under a parent document, for example archive_restore/run1/users/cli-alice. Output contains selected project JSON, import metadata, logs, and a task snapshot with status, operation counters, duration, attempt count, and error. Imports fail for read-only projects before file parsing or network work. Emulator-backed coverage validates JSON, JSONL, CSV, overwrite, archive restore, and target-prefix behavior through read-back. Live imports have guarded JSON/CSV request-shape coverage, but approved disposable live read-back and cleanup remain open. Transfer Collections firestore transfer --project SourceProject --target TargetProject --collection users --confirm firestore transfer --project SourceProject --target TargetProject --collections users,orders --include-subcollections --allow-overwrite --confirm firestore transfer --project SourceProject --target TargetProject --collection users --clean-target --confirm Options: - --target is required and resolves a linked Firebase project by name, Firebase project ID, or UUID. - --project optionally selects the source project; otherwise the current selected project is used. - --collection transfers one collection path. --collections accepts a comma-separated list. - --confirm is required for every transfer. - --include-subcollections recursively copies document subcollections. - --allow-overwrite permits replacing existing target documents. - --clean-target deletes existing target documents in the target collection before copying. - --source-access-token and --target-access-token provide distinct OAuth tokens for live source reads and target writes; the corresponding --source-authorization and --target-authorization options accept complete authorization header values. - A transfer involving production also requires --production-confirm "TRANSFER <source-project-id> TO <target-project-id>". Output contains source/target project JSON, transfer metadata, logs, and a task snapshot with status, operation counters, duration, attempt count, and error. Transfers fail when either project is read-only. Emulator-backed coverage validates confirmation, recursive copy, read-back, and target cleanup. Live request shape and credential propagation are covered locally; approved disposable live transfer and cleanup proof remain open. JavaScript Query Scripts firestore run-js --collection users --file scripts/query-users.js firestore run-js --collection users --where "role == admin" --limit 100 --file scripts/query-users.js firestore run-js --collection users --file scripts/mutate-users.js --write-through --confirm firestore js --collection users --script 'async function run(ctx, admin) { return admin.firestore().query({ path: ctx.queryPath }); }' firestore run-js first loads real Firestore documents through the selected emulator or live query path, then injects those documents into the local JavaScript runtime as admin.firestore() data. It returns structured documents, raw runtime JSON, logs, and a completed task snapshot. Options: - --collection is required and defines the Firestore data loaded before the script runs. - --where, --order-by, and --limit match firestore query. - --file <path> reads a script from disk. - --script <text> runs an inline script for small automation checks. - --timeout <seconds> defaults to 15. - --write-through applies Firestore mutations emitted by the local runtime to the selected Firestore emulator. - --confirm is required with --write-through. Without --write-through, script mutations affect only the local runtime snapshot. With --write-through --confirm, emitted set, update, and delete mutations are applied to the selected emulator. Output identifies the emulator write-through mode and applied mutation count. Write-through JavaScript execution currently supports emulator projects only. Live JavaScript writes require a separate approved live verification slice before they can be claimed. Emulator-backed coverage validates real document loading, script results, console logs, task output, confirmation guards, and read-back after update/create/delete mutations. Saved Queries And Scripts firestore saved-query save --name "Owner Users" --collection users --where "role == owner" --limit 10 firestore saved-query list firestore saved-query show --name "Owner Users" firestore saved-query run --name "Owner Users" firestore saved-query delete --name "Owner Users" --confirm firestore saved-script save --name "Owner Report" --collection users --file scripts/query-users.js firestore saved-script list firestore saved-script show --name "Owner Report" firestore saved-script run --name "Owner Report" firestore saved-script run --name "Owner Report" --write-through --confirm firestore saved-script delete --name "Owner Report" --confirm Saved workflows are stored in firestore-saved-workflows.json under the CLI support directory, or in the directory pointed to by FIRESTRUCT_CLI_HOME for command-line runs. Output includes persistence.mode and persistence.crossProcessPersistent so automation can distinguish file-backed storage from in-memory test contexts. Saved query options: - save requires --name and --collection. - --where, --order-by, and --limit use the same parsing as firestore query. - --replace overwrites an existing saved query with the same name. - run reuses the persisted query definition against the selected project or --project override. - delete requires --confirm. Saved script options: - save requires --name, --collection, and either --file or --script. - --where, --order-by, --limit, and --timeout are persisted with the script. - show includes the stored script source text; list omits it for compact output. - run loads real Firestore documents from the saved query definition before executing the stored script. - run --write-through --confirm uses the same emulator-only write-through guardrails as firestore run-js. - delete requires --confirm. Emulator-backed coverage validates persistence across CLI contexts, duplicate rejection, query/script execution, logs, confirmation, and deletion. Analyze Schema firestore schema --collection users --format json --output schema.json firestore schema --collection users --format csv --output schema.csv firestore schema --collection users --format typescript --output schema.ts firestore schema --collection users --format json-schema --output schema.schema.json Options: - --collection is required and uses the same query path rules as firestore query. - --format accepts json, csv, typescript, dart, kotlin, java, swift, objc, or json-schema; it defaults to json. - --output is optional; when provided, the generated schema/type output is written to that path. - --limit, --where, and --order-by use the same parsing as firestore query. Output contains selected project JSON, query metadata, schema analysis JSON, generated output text, optional destination path, and a task snapshot with status, operation counters, duration, attempt count, and error. The current emulator-backed CLI test runs every supported schema format against a real Firestore emulator query and validates the generated artifact contents. Create Document firestore create --collection users --document-id alice --data '{"name":"Alice"}' --confirm firestore create --collection users --document-id alice --data '{"name":"Alice"}' --allow-overwrite --confirm firestore create --collection firestruct_verification/run1/users --document-id alice --data '{"name":"Alice"}' --access-token "$TOKEN" --confirm Required options: - --collection - --document-id - --data - --confirm - --access-token or --authorization is required for live projects. - --production-confirm "WRITE <project-id>" is required for production projects. --allow-overwrite permits replacing an existing target when the core service supports it. Creates fail for read-only projects. The shared core write service and CLI now have live REST request-shape support for single-document create/update/delete when an explicit authorization header is supplied. Approved disposable live read-back/cleanup verification is still required before live success is claimed. Update Document firestore update --document users/alice --data '{"name":"Alice"}' --confirm firestore update --document firestruct_verification/run1/users/alice --data '{"name":"Alice"}' --access-token "$TOKEN" --confirm Required options: - --document - --data - --confirm - --access-token or --authorization is required for live projects. - --production-confirm "WRITE <project-id>" is required for production projects. Updates fail for read-only projects. CLI evidence covers live request construction, authorization propagation, selected database IDs, and production confirmation guardrails. Approved disposable live read-back/cleanup verification remains open. Delete Document firestore delete --document users/alice --confirm firestore delete --document firestruct_verification/run1/users/alice --access-token "$TOKEN" --confirm Required options: - --document - --confirm - --access-token or --authorization is required for live projects. - --production-confirm "DELETE <project-id>" is required for production projects. Deletes fail without --confirm and fail for read-only projects. CLI evidence covers live request construction, authorization propagation, selected database IDs, and production confirmation guardrails. Approved disposable live read-back/cleanup verification remains open. Run Through Selected Module module select firestore run query --collection users --limit 50 run dispatches Firestore actions only when the selected CLI module is firestore. Not Yet Covered by CLI The GUI Firestore module has broader coverage than the current CLI. These flows are not first-class CLI commands yet: - bulk field operations - live write-through JavaScript mutations - recursive copy/move/rename - Firebase-proven vector nearest-neighbor ranking behavior CLI parity for these workflows is tracked in tasks/prd-phase-3-cli-parity.md. Completion requires CLI integration tests against Firebase emulators or approved live Firebase evidence for behavior the emulator cannot represent. Source Anchors - Sources/FirestructCLIKit/FirestoreCommand.swift - Sources/FirestructCore/FirestoreSimpleQueryService.swift - Sources/FirestructCore/FirestoreDocumentWriteService.swift - Tests/FirestructCLIIntegrationTests/FirestructCLIIntegrationTests.swift

Last updated on Jul 12, 2026

Auth CLI

Purpose The Auth CLI exposes Firebase Authentication user administration through the same AuthListService used by the macOS app. It supports emulator projects by default and supports live Firebase projects when a bearer token is supplied. All successful commands print JSON. Failures return exit code 1 with a readable error on stderr. Project Setup project connect --name Local --project-id demo-firestruct --environment emulator --host localhost --port 8080 --auth-port 9099 project select Local Options shared by Auth commands: - --project <name|firebaseProjectID|uuid> overrides the selected project. - --tenant <tenant-id> overrides the selected Auth tenant for one command. - --project-auth explicitly uses project-level Auth for one command, bypassing a selected tenant. - --authorization "Bearer <token>" supplies a live-project authorization header. - --access-token <token> is shorthand for --authorization "Bearer <token>". For emulator projects, Firestruct sends the emulator admin authorization header automatically. Discover And Select Auth Tenants auth tenants list auth tenants list --page-size 100 auth tenants select clinic-a auth tenants current auth tenants select project-auth auth tenants list discovers Firebase Auth tenants through Identity Toolkit and identifies the selected scope. Live projects require --access-token or --authorization. auth tenants select <tenant-id> stores a selection independently for each linked Firebase project; subsequent list, search, create, update, enable/disable, delete, import/export, transfer-source, and script commands use it automatically. Use auth tenants select project-auth to clear the saved tenant. In automation, prefer explicit --tenant or --project-auth so a previous interactive selection cannot change the target scope. List Users auth list --limit 100 auth list --limit 100 --page-token <nextPageToken> auth list --filter alice --sort-by email auth list --sort-by createdAt --descending Options: - --limit defaults to 1000 and must be between 1 and 1000. - --page-token requests a specific Firebase Auth page. - --filter applies a client-side substring filter across UID, email, phone, and display name. - --sort-by accepts uid, email, phoneNumber, createdAt, or lastLoginAt. - --descending reverses the sort order. Output contains project, users, nextPageToken, and logs. Each user includes profile fields, disabled and email verification state, custom claims JSON, metadata timestamps, password hash/salt when returned by Firebase, linked provider IDs, and provider details. Search And Get auth search --uid auth_alice auth search --email alice@example.test auth search --phone +15555550123 auth get --uid auth_alice auth search and auth get use the Identity Toolkit lookup endpoint. Provide one of --uid, --email, --phone, or --search. Create User auth create --uid auth_alice --email alice@example.test --password secret auth create --email alice@example.test --display-name "Alice" --email-verified true auth create --uid auth_alice --custom-claims '{"role":"admin"}' Supported fields: - --uid - --email - --password - --phone - --display-name - --photo-url - --disabled true|false - --email-verified true|false - --custom-claims '<json object>' Update User auth update --uid auth_alice --display-name "Alice Updated" auth update --uid auth_alice --disabled true auth update --uid auth_alice --email-verified false auth update --uid auth_alice --custom-claims '{"tier":"pro"}' auth update --uid auth_alice --delete-password --uid is required. The other fields match auth create. Custom claims are validated by the core Auth service before the request is sent. Bulk Enable, Disable, And Delete auth disable --uid auth_alice --confirm auth enable --uids auth_alice,auth_bob --confirm auth delete --uid auth_alice --confirm auth delete --uids auth_alice,auth_bob --confirm Bulk mutation commands require --confirm. --uid targets one user, and --uids accepts a comma-separated list. Output includes a task object with queued/running/success lifecycle fields, processed and total operation counters, attempt count, duration, and any retained error description. Export Users auth export --format json --output build/auth-users.json auth export --format csv --output build/auth-users.csv auth export --search alice@example.test --output build/alice.json auth export --uids auth_alice,auth_bob --fields uid,email,customClaims --output build/auth-users.json Options: - --format json|csv defaults to json. - --output <path> is required. - --search <text> exports lookup results instead of all users. - --uid or --uids narrows the exported all-user result. - --page-size controls all-user pagination and defaults to 1000. - --fields <comma-separated AuthExportField names> selects export fields. - --no-metadata omits metadata fields. - --no-custom-claims omits custom claims. - --include-hashes includes password hash and salt when Firebase returns them. - --delimiter <char> sets CSV delimiter. - --json-structure array|keyedByUID|envelope controls JSON shape. - --timestamps iso8601|unixMilliseconds|unixSeconds controls timestamp encoding. Output includes export counts, destination metadata, logs, and the completed task snapshot. Import Users auth import --file auth-users.json --format json --confirm auth import --file auth-users.csv --format csv --uid-column uid --confirm auth import --file auth-users.json --update-existing --confirm Options: - --file <path> is required. - --format json|csv defaults to json. - --delimiter <char> sets CSV delimiter. - --no-header treats CSV as headerless. - --uid-column <name> defaults to uid. - --update-existing updates users when create returns an already-exists error. - --confirm is required. JSON imports accept either an array of user objects or an object keyed by UID. CSV imports require a UID column unless --no-header is used. Output includes imported count, logs, and the completed task snapshot. Transfer Users auth transfer --target Staging --confirm auth transfer --target Production --uids auth_alice,auth_bob --confirm auth transfer --target Staging --delete-source --confirm auth transfer --target Production --tenant source-tenant --target-tenant target-tenant --confirm The selected or --project project is the source. --target accepts the target project name, Firebase project ID, or UUID. Transfer exports users from the source, creates or updates them in the target, and optionally deletes source users with --delete-source. By default, --tenant is used for both source and target tenant scopes. Pass --target-tenant when the target Auth tenant differs. When --tenant is omitted, the source uses that project's selected Auth tenant. The target defaults to the same scope unless --target-tenant is supplied. For live-to-live or emulator-to-live transfer, use target-specific credentials when needed: auth transfer --target Production --access-token <source-token> --target-access-token <target-token> --confirm Output includes transferred count, optional source deletion count, logs, and the completed task snapshot. JavaScript Auth Scripts auth run --file scripts/auth-report.js auth run --script 'async function run(ctx, admin) { const r = await admin.auth().listUsers(100); return r.users.map(u => ({ uid: u.uid, email: u.email })); }' auth run loads all Auth users first, injects them into the local JavaScript runtime as admin.auth() data, and returns structured documents, raw runtime JSON, and logs. The Auth shim supports common Admin Auth methods such as listUsers, getUser, getUserByEmail, getUserByPhoneNumber, getUsers, createUser, updateUser, deleteUser, deleteUsers, setCustomUserClaims, token helpers, and email link helpers. Options: - --file <path> reads a script from disk. - --script <text> runs an inline script. - --timeout <seconds> defaults to 15. Script mutations run against the local runtime snapshot, not Firebase. Use auth create, auth update, auth delete, auth import, or auth transfer for Firebase mutations. Auth-To-Firestore Routes Routes connect one exact Auth scope—project-level Auth or one tenant—to a Firestore project, database, collection, and UID mapping strategy. They are persisted in the same local project registry used by the macOS app. Create a document-ID route: auth tenants select clinic-a auth routes set --firestore-project CustomerData --database customer-data --collection tenantUsers Create a field-value route for a shared collection: auth routes set \ --firestore-project CustomerData \ --database customer-data \ --collection users \ --key-strategy field-value \ --uid-field auth.uid \ --tenant-field tenantID \ --tenant-value clinic-a Route management commands: auth routes list auth routes list --all auth routes disable --id <route-uuid> auth routes enable --id <route-uuid> auth routes delete --id <route-uuid> --confirm set creates a route unless --id <route-uuid> identifies an existing route to update. Collection paths must have an odd number of segments. The database must be configured on the target project. Field-value routes require --uid-field; --tenant-field and --tenant-value must be supplied together. Only one route may exist for each Auth project/tenant scope. Resolve from Auth to Firestore: auth routes resolve-auth --uid auth_alice auth routes resolve-auth --uid auth_alice --plan-only Resolve from a Firestore document back to Auth: project select CustomerData auth routes resolve-firestore --document users/profile-1 --auth-project AuthProject auth routes resolve-firestore --document users/profile-1 --auth-project AuthProject --tenant clinic-a Resolution restores the route's Firestore database and Auth tenant instead of relying on the currently selected database. Shared-collection routes apply their tenant discriminator. Ambiguous reverse matches fail until --auth-project, --tenant, or --project-auth identifies an exact Auth scope. --plan-only prints route/query resolution without Firebase calls when the mapping permits it; field-value reverse resolution must read the document to obtain the UID. Firestore requests accept --firestore-access-token or --firestore-authorization; reverse Auth lookup accepts --auth-access-token or --auth-authorization. The unprefixed credential flags remain the fallback for both. Run Through Selected Module module select auth run list --limit 100 run export --output build/auth-users.json run dispatches Auth actions when the selected CLI module is auth. Current CLI Gaps The GUI Auth module still has a few workflows that are not first-class CLI commands: - Direct Storage file-picker profile-photo upload proof; the covered GUI path is the selected Storage download URL handoff to photoURL. - Saved Auth query/script presets. - Durable retry/cancel across separate CLI invocations; completed Auth task snapshots are persisted through the shared Tasks CLI history. Source Anchors - Sources/FirestructCLIKit/AuthCommand.swift - Sources/FirestructCLIKit/AuthTenantsCommand.swift - Sources/FirestructCLIKit/AuthRoutesCommand.swift - Sources/FirestructCLIKit/FirestructCLI.swift - Sources/FirestructCore/AuthFirestoreLinkRouteService.swift - Sources/FirestructCore/AuthListService.swift - Sources/FirestructCore/AuthListService+Operations.swift - Tests/FirestructCLIIntegrationTests/FirestructCLIIntegrationTests.swift

Last updated on Jul 12, 2026

Storage CLI

Current Status Storage has a first-class CLI command group in Sources/FirestructCLIKit/StorageCommand.swift. It reuses StorageService, so emulator behavior and guarded production URL/request shapes match the macOS Storage module. Approved live bucket verification is still required before live Storage hardening is claimed. Project Selection Commands use the selected project from project select unless --project <name|firebaseProjectID|uuid> is passed. If --bucket is omitted, the CLI defaults to: <firebaseProjectID>.appspot.com Live Storage requests can pass either: --authorization "Bearer <token>" --access-token <token> Commands Bucket discovery: storage buckets [--bucket fallback-bucket] Object browsing: storage list --bucket demo.appspot.com [--prefix avatars/] [--recursive] [--browser] storage list --bucket demo.appspot.com --browser --sort-by updated --descending storage inspect --bucket demo.appspot.com --path avatars/alice.png --browser adds GUI-like folder/file entries built with StorageService.browserEntries. inspect returns object metadata, preview kind, metadata rows, and the object download URL. Uploads: storage upload --bucket demo.appspot.com --file ./avatar.png --path avatars/alice.png --confirm storage upload --bucket demo.appspot.com --file ./data.json --path imports/data.json --content-type application/json --metadata '{"owner":"alice"}' --confirm storage upload-folder --bucket demo.appspot.com --folder ./avatars --target avatars --confirm Downloads: storage download --bucket demo.appspot.com --path avatars/alice.png --output ./avatar.png storage download-batch --bucket demo.appspot.com --paths avatars/a.png,avatars/b.png --output-dir ./downloads [--concurrency 4] storage zip --bucket demo.appspot.com --paths avatars/a.png,avatars/b.png --output ./selection.zip storage zip-folder --bucket demo.appspot.com --path avatars --output ./avatars.zip Mutations: storage delete --bucket demo.appspot.com --path avatars/alice.png --confirm storage delete --bucket demo.appspot.com --paths avatars/a.png,avatars/b.png --confirm storage delete-folder --bucket demo.appspot.com --path avatars --confirm storage copy --bucket demo.appspot.com --path avatars/a.png --target avatars/b.png --confirm storage move --bucket demo.appspot.com --path avatars/a.png --target archive/a.png --confirm storage copy-folder --bucket demo.appspot.com --path avatars --target avatars-copy --confirm storage move-folder --bucket demo.appspot.com --path avatars --target archive/avatars --confirm storage rename-folder --bucket demo.appspot.com --path avatars --name archived-avatars --confirm storage duplicate-folder --bucket demo.appspot.com --path avatars --confirm URL helpers: storage url --bucket demo.appspot.com --path avatars/alice.png storage signed-url --bucket demo.appspot.com --path avatars/alice.png --expires 3600 storage signed-url --bucket demo.appspot.com --path avatars/alice.png --expires 3600 --service-account-file ./service-account.json For emulator projects, signed-url returns a deterministic emulator download URL with the requested expiration. For production projects, V4 signing requires --service-account-file. Safety - Upload, delete, copy, move, folder upload, folder delete, folder copy, folder move, folder rename, and folder duplicate require --confirm. - Read-only project links reject Storage mutations. - Folder copy/move checks for nested targets and duplicate destination objects before mutating. - Object copy/move validates that source and target paths differ. - Long multi-object operations run through TaskOrchestrator and return task status, counters, duration, and errors in JSON output. Output All commands emit JSON. Long-running commands include a task object: { "status": "success", "processedOperations": 2, "totalOperations": 2, "attemptCount": 1 } Current Verification FirestructCLIIntegrationTests/testCLICommandsRoundTripAgainstFirebaseEmulators uploads two real Storage emulator objects, lists them through selected-module browser output, inspects and downloads one object, builds both selected-object and folder ZIP archives, validates archive payload bytes with /usr/bin/unzip, copies the folder, moves the copied folder, lists emulator source/target paths afterward, deletes an object, and verifies Storage folder/delete task titles are retained by tasks list. FirestructCLIIntegrationTests/testStorageMoveSignedURLAndReadOnlyGuard verifies read-only project links reject Storage mutations and emulator signed URLs are deterministic. Approved live bucket verification is still required before live Storage hardening is claimed. Source Anchors - Sources/FirestructCLIKit/StorageCommand.swift - Sources/FirestructCLIKit/FirestructCLI.swift - Sources/FirestructCLIKit/JSONOutput.swift - Sources/FirestructCore/StorageService.swift - Tests/FirestructCLIIntegrationTests/FirestructCLIIntegrationTests.swift

Last updated on Jul 12, 2026

Push CLI

Current Status Push has a first-class CLI command group for local payload validation, Firestore-backed token resolution, and guarded send attempts. Use the CLI for repeatable QA checks that do not deliver notifications, plus explicitly labeled simulated sends. Non-dry-run sends require credentials and produce per-target HTTP results. Real FCM delivery is still not claimed until an approved live project/device fixture proves it. Commands push validate --payload payload.json push validate --payload payload.json --project demo-firestruct push resolve-tokens --source token-source.json push resolve-tokens --collection users --field "push.tokens.*" --path-pattern "users/*" push send --payload payload.json --confirm --dry-run push send --payload payload.json --confirm --access-token "$GOOGLE_ACCESS_TOKEN" The push module also supports selected-module routing: module select push run validate --payload payload.json run resolve-tokens --source token-source.json Payload File push validate --payload reads a JSON object. Common fields: { "targetMode": "token", "tokens": ["abcDEF1234567890"], "title": "Hello", "body": "World", "data": { "kind": "smoke" }, "dryRun": true } Validation returns JSON with: - valid - validation errors and warnings - messagePreview - deliveryMode: "validation-only" - sendImplemented: false Validation covers local request shape and payload safety only. It reports APNS badge, priority, push type, expiration, and background-update issues; Android priority, TTL, notification priority, visibility, and color issues; Webpush TTL, urgency, and link issues; invalid notification image/icon/badge URLs; reserved FCM data keys; oversized data fields; and the FCM HTTP v1 4096-byte message limit. No FCM send is attempted by push validate. Send Boundary push send requires a selected project and --confirm. Non-dry-run delivery is rejected for read-only projects, and production non-dry-run delivery requires --production-confirm SEND. Without --authorization or --access-token, push send does not contact FCM. It returns deliveryMode: "simulated-send", per-token status: "simulated", fcmAPIAttempted: false, liveDeliveryAttempted: false, and task output. With credentials, push send uses the FCM HTTP v1 API. --dry-run sends validate_only: true and reports deliveryMode: "fcm-http-v1-dry-run". Non-dry-run credentialed sends report deliveryMode: "fcm-http-v1-send" and must not be claimed as release evidence until an approved live FCM project and device/token fixture are recorded. Token Source File push resolve-tokens --source reads a JSON object: { "collection": "users", "pathPattern": "users/*", "tokenFieldPath": "push.tokens.*", "limit": 500 } Resolution queries the selected Firebase project with Firestruct's Firestore query service, then passes the real returned documents into PushTokenSourceResolverService. Output includes resolved tokens, matched document paths, invalid token candidates, and logs. Still Live-Only Actual FCM delivery proof remains live-only. Release runbooks may not claim real delivery support until an approved FCM project/device fixture captures the API response and cleanup or token invalidation notes. Verification Covered by: swift test --filter FirestructCLIIntegrationTests/testPushValidateUsesPayloadJSONAndSelectedModuleRouting swift test --filter FirestructCLIIntegrationTests/testCLICommandsRoundTripAgainstFirebaseEmulators The focused validation test reads real valid and invalid payload files, validates locally, checks warnings, platform/data/URL errors, message preview JSON, and verifies selected-module run validate. It also verifies push send rejects missing --confirm, returns labeled simulated per-token results with task counters for a confirmed no-credential dry-run, rejects read-only non-dry-run delivery, and requires --production-confirm SEND for production non-dry-run sends. The emulator round-trip writes token documents into a real Firestore emulator, resolves tokens via a JSON token-source file, reports invalid candidates, and verifies selected-module run resolve-tokens. Source Anchors - Sources/FirestructCLIKit/PushCommand.swift - Sources/FirestructCore/PushTestingService.swift - Sources/FirestructCore/PushTokenSourceResolverService.swift

Last updated on Jul 12, 2026

PITR Recovery CLI

Current Status PITR has a first-class CLI command group for task-backed load, diff, and guarded restore command shapes. The commands use the shared FirestorePITRService, return JSON output, and preserve the same read-only and production confirmation guardrails as the macOS module. Current automated evidence proves command shape, request construction, task output, selected-module routing, and local guardrails with URLProtocol-backed service tests. It does not prove real Firestore PITR historical reads or live restore effects. Approved PITR-enabled Firebase evidence is still required before live PITR behavior should be claimed externally verified. Commands pitr load --document users/alice --read-time 2026-05-03T12:00:00Z pitr diff --document users/alice --read-time 2026-05-03T12:00:00Z pitr restore --document users/alice --read-time 2026-05-03T12:00:00Z --confirm pitr restore --document users/alice --read-time 2026-05-03T12:00:00Z --confirm --production-confirm "RECOVER my-project" pitr-recovery is accepted as a top-level alias. The commands also work through selected-module routing: module select pitr run diff --document users/alice --read-time 2026-05-03T12:00:00Z Output Contract Successful commands return machine-readable JSON with: - selected project metadata - pitr.action, documentPath, readTime, databaseID, and requiresApprovedLivePITRVerification - snapshot.current and snapshot.recovered document versions with decoded fields and raw JSON - diffRows with field path, current value, recovered value, and status - logs from the PITR service - task snapshot with status, counters, duration, attempts, and error details - restore raw JSON for pitr restore Safety Boundary Restore requires --confirm. Read-only projects reject restore before network requests. Production restore requires --production-confirm "RECOVER <project-id>" before any load or PATCH request is attempted. For live projects, pass --authorization "Bearer <token>" or --access-token <token>. The command output still marks PITR behavior as requiring approved live verification until a PITR-enabled Firebase project run with before/after evidence and cleanup is recorded. Verification Covered by: swift test --filter FirestructCLIIntegrationTests/testPITRCLIQueuesLoadDiffAndRestoreWithTaskOutput swift test --filter FirestructCLIIntegrationTests/testPITRCLIRestoreRejectsReadOnlyAndProductionBeforeNetwork The first test uses the real PITR service through the CLI with a URLProtocol session, verifies pitr load, selected-module run diff, and pitr restore task output, current/recovered/diff/log JSON, and recovered-field PATCH request body. The second test proves read-only and production confirmation failures happen before any network request. Source Anchors - Sources/FirestructCLIKit/PITRCommand.swift - Sources/FirestructCore/FirestorePITRService.swift

Last updated on Jul 12, 2026

Index Advisor CLI

Current Status Index Advisor has a deterministic local-file CLI command group for CI/support automation. It does not call Firebase, sync remote indexes, create indexes, or deploy index files. Those write-like or live remote workflows remain GUI/live verification work and must require explicit project approval if added later. All successful commands emit JSON. Commands index-advisor analyze Analyze a query shape against local Firestore index JSON: index-advisor analyze \ --collection users \ --where-fields status,region \ --order-by "createdAt desc" \ --indexes firestore.indexes.json You can also pass a query-shape file: index-advisor analyze \ --query-shape query-shape.json \ --indexes firestore.indexes.json \ --error-file firestore-error.log Supported query-shape JSON fields: - collectionPath - whereFields - orderByClauses with fieldPath and optional direction - orderByFields as a shorthand array when direction does not matter The JSON response includes: - queryShape.collectionGroup - loaded indexes - report.requiredFields - report.hasMatchingIndex - report.matchingIndexes - report.missingFields - report.warnings.proactive - report.warnings.cost - report.suggestedIndexJSON - report.suggestedIndexSpec - optional report.indexCreationURL - deterministic logs and explanations Matching is order-sensitive. The analyzer treats a candidate index as covered only when the required query fields match the composite index prefix and any orderBy directions match. A candidate with the right fields in the wrong order returns hasMatchingIndex: false, emits an order/direction mismatch log, and keeps the deterministic suggested index output. index-advisor parse-error Extract a Firebase Console index creation URL from captured Firestore error text: index-advisor parse-error --file firestore-error.log index-advisor parse-error --text "FAILED_PRECONDITION: ..." The response includes found, indexCreationURL, and logs. index-advisor load-indexes Parse local Firestore index JSON and return the normalized index definitions: index-advisor load-indexes --file firestore.indexes.json This is useful in CI to validate that the index file is parseable before using it in index-advisor analyze. Selected Module Dispatch index-advisor can be selected as the active module: module select index-advisor run parse-error --file firestore-error.log Not Yet Covered by CLI - Remote index sync from a live Firebase project. - Index creation or deploy. - Opening Firebase Console from the terminal. - AI explanations beyond deterministic service output. Any future live sync or write-like behavior must label the target project and environment, refuse read-only projects where applicable, require explicit confirmation for production changes, and include approved live verification evidence. Source Anchors - Sources/FirestructCore/IndexAdvisorService.swift - Sources/FirestructCore/FirestoreIndexCreationLinkSummary.swift - Sources/FirestructCLIKit/IndexAdvisorCommand.swift - Tests/FirestructCLIIntegrationTests/FirestructCLIIntegrationTests.swift

Last updated on Jul 12, 2026

Seed Studio CLI

Purpose The Seed Studio CLI automates deterministic Firestore seed snapshots for emulator setup. It uses the same SeedStudioService as the macOS module for schema parsing, generation, apply, and drift analysis. All successful commands print JSON. Failures return exit code 1 with a readable error on stderr. Generate Snapshot seed import-template --template seed.json --output normalized-seed.json seed generate --template seed.json --output snapshot.json --seed 42 seed export-template --snapshot snapshot.json --output exported-seed.json Options: - --template <path> is required and must contain a Seed Studio schema JSON document. - --output <path> is required. - --seed <uint> defaults to 1. The generated file is a CLI snapshot envelope containing both the parsed schema and generated snapshot. Keeping both pieces together lets later seed apply and seed diff coerce values and compare fields without relying on an external template file. Output includes the template path, destination path, random seed, collection path, document count, and snapshot digest. seed import-template parses and validates a schema JSON file, then writes the normalized SeedSchema form to disk. seed export-template reads a generated snapshot envelope and writes its embedded schema to disk. Together they provide a real file round-trip for template import/export workflows without touching Firebase data. Apply Snapshot seed apply --project Local --snapshot snapshot.json --confirm seed apply --project Local --snapshot snapshot.json --allow-overwrite --confirm seed apply --project Local --snapshot snapshot.json --document-ids seed-1,seed-3 --confirm seed apply --project Local --snapshot snapshot.json --reset-existing --allow-overwrite --confirm Options: - --snapshot <path> is required and must be produced by seed generate. - --project <name|firebaseProjectID|uuid> overrides the selected project. - --confirm is required. - --allow-overwrite permits replacing existing documents. - --reset-existing deletes each generated document path before reapplying it. - --document-ids <ids> applies only the comma- or newline-separated generated document IDs. Without --allow-overwrite, existing selected documents are skipped and reported in skippedDocumentIDs; missing selected documents are recreated. With --allow-overwrite, selected existing documents are replaced. Apply currently uses emulator-safe writes. Non-emulator writes are blocked by the core service because live seed rollout requires a separate approved verification path. Output includes selected project JSON, source/applied document counts, partial document IDs, applied/skipped counts, applied document paths, logs, and a completed task snapshot. Diff Snapshot seed diff --project Local --snapshot snapshot.json seed diff --project Local --snapshot snapshot.json --limit 1000 Options: - --snapshot <path> is required. - --project <name|firebaseProjectID|uuid> overrides the selected project. - --limit <count> controls the current Firestore query limit and defaults to 0, which fetches all documents in Firestruct's Firestore query service. Diff reads current Firestore emulator data from the snapshot collection path and reports changed, unchanged, missing, and new documents. Current Verification FirestructCLIIntegrationTests/testCLICommandsRoundTripAgainstFirebaseEmulators imports a template to a normalized file, generates a deterministic Seed Studio snapshot from that imported template, exports the template back out of the snapshot, decodes both template artifacts, verifies apply rejects missing --confirm, applies the snapshot to a real Firestore emulator, queries the seeded collection, mutates/deletes/adds emulator documents, runs partial seed apply --document-ids without overwrite to prove existing selected docs are skipped while missing selected docs are recreated, runs partial apply with --allow-overwrite to prove selected changed docs are restored, and runs seed diff to assert the final unchanged/new counts. Source Anchors - Sources/FirestructCLIKit/SeedCommand.swift - Sources/FirestructCore/SeedStudioService.swift - Sources/FirestructCore/SeedStudioService+GenerationUtilities.swift

Last updated on Jul 12, 2026

Tasks CLI

Current Status Firestruct exposes a first-class Tasks CLI command group for current-process tasks and durable completed-task history: tasks list tasks show <task-id> tasks retry <task-id> tasks cancel <task-id> Successful command output is JSON. Task rows include id, title, status, processedOperations, totalOperations, timestamps, durationSeconds, attemptCount, lastErrorDescription, recordedAt, source, and bounded per-task lifecycle logs. Persistence Boundary CLI task inspection includes two layers: - current-process tasks from the live TaskOrchestrator - durable completed-task snapshots from task-history.json tasks list and tasks show can read persisted terminal task snapshots and their lifecycle logs in a fresh CLI context. tasks retry and tasks cancel still require the original same-process runner because Firestruct does not serialize operation closures. Every Tasks CLI response includes: { "persistence": { "mode": "persistent-history", "crossProcessPersistent": true, "retryCancelScope": "same-process" } } This is intentionally a history model, not a durable background job runner. Commands List tasks list Returns current-process tasks plus persisted terminal history, with summary counts for queued, running, success, failed, total, and history tasks. Show tasks show <task-id> tasks show --id <task-id> Returns a single task snapshot or a non-zero error when the task ID is unknown or malformed. Retry tasks retry <task-id> tasks retry --id <task-id> Retries failed tasks through the real TaskOrchestrator runner. Retrying a queued, running, or successful task returns a non-zero actionable error. Cancel tasks cancel <task-id> tasks cancel --id <task-id> Cancels queued or running tasks where the underlying operation can observe cancellation. Cancelling an already completed or failed task returns a non-zero actionable error. Verification - FirestructCLIIntegrationTests/testTasksCLIListsShowsRetriesAndRejectsInvalidStatesInSameProcess runs a Firestore schema command through a real shared TaskOrchestrator, lists and shows the resulting success task, enqueues a real failing task, verifies failed task visibility, retries it through the Tasks CLI, and checks invalid retry/cancel states return non-zero errors. It then creates a fresh CLI context pointing at the same history file, verifies the completed and failed/retried tasks are still visible with source: history, verifies lifecycle logs include enqueue/start/progress/success/failure/retry events, and verifies retry fails with a persisted-history-only message. - FirestructCLIIntegrationTests/testCLICommandsRoundTripAgainstFirebaseEmulators runs Firestore, Seed, Auth, Storage, and Migrations commands against Firebase emulators, then verifies tasks list retains Seed apply, Auth disable/delete, Storage delete, and Migrations record-applied tasks in the same process. Remaining Gaps - Durable retry/cancel across new CLI processes is not implemented. - Future long-running CLI commands such as approved-live Workspace deploy, approved-live Push real FCM delivery, and production/live migration apply workflows must route through the shared CLI context task orchestrator when they are implemented. PITR load/diff/restore command shapes already route through the task orchestrator, but approved live PITR evidence is still required before historical read or restore behavior is claimed. - Persisted lifecycle logs are bounded per task. They preserve task-state events, progress counters, attempt counts, and failure/cancellation messages; they do not serialize operation-specific stdout/stderr streams unless the command includes that output in its own task/result payload. Source Anchors - Sources/FirestructCore/TaskOrchestrator.swift - Sources/FirestructCLIKit/TasksCommand.swift - Sources/FirestructCLIKit/CLIContext.swift - Sources/FirestructCLIKit/TaskHistoryStore.swift

Last updated on Jul 12, 2026

Migrations CLI

Purpose The Migrations CLI inspects local Fireway migration files and compares them with Firestore migration records. It uses the same MigrationExplorerService as the macOS module. All successful commands print JSON. Failures return exit code 1 with a readable error on stderr. Status And List migrations status --project Local --directory ./migrations --collection fireway migrations list --project Local --directory ./migrations --collection fireway status and list are aliases. They load local migration files, query the configured Firestore migration collection, and classify each migration as: - applied: local file and remote record exist, and checksum matches or the remote record has no checksum. - drifted: local file and remote record exist, but checksum differs. - pending: local file exists without a remote record. - missing: remote record exists without a local file. Options: - --directory <path> is required unless the selected project has a local workspace path; when a workspace path exists, the default is <workspace>/migrations. - --collection <path> defaults to fireway. - --project <name|firebaseProjectID|uuid> overrides the selected project. - --limit <count> controls the remote Firestore query limit and defaults to 1000. Output includes selected project JSON, local/remote counts, status counts, status rows, local files, remote records, logs, and executionMode: inspection-only. Show Migration migrations show 001_add_users --project Local --directory ./migrations --collection fireway migrations show --id 001_add_users --project Local --directory ./migrations --collection fireway show returns the status row, local file metadata, remote record metadata, and full local source content for one migration ID. Record Applied migrations record-applied 001_add_users --project Local --directory ./migrations --collection fireway --confirm migrations record-applied --all-pending --project Local --directory ./migrations --collection fireway --confirm record-applied is explicitly record-only. It does not execute Fireway source code. It writes migration records for pending local files to the configured Firestore emulator collection, including checksum, source path, applied timestamp, status, and rollback note metadata. The command requires --confirm, rejects read-only projects, and currently supports emulator projects only. Output includes selected project JSON, executionMode: record-only, requested and recorded IDs, skipped IDs, refreshed status counts, rollback notes, logs, and a task snapshot. Apply Migration migrations apply 005_apply_writes --project Local --directory ./migrations --collection fireway --confirm migrations apply --all-pending --project Local --directory ./migrations --collection fireway --confirm apply executes pending migration JavaScript against a Firestore emulator target. It requires --confirm, rejects read-only projects, and currently rejects non-emulator projects until approved live verification exists. The emulator execution adapter supports migration source files that expose an up function through module.exports = async (...) => {}, module.exports.up, exports.up, or a top-level/exported up. The migration function receives a helper object with db, firestore, admin, collection, doc, batch, projectID, databaseID, environment, migrationID, migrationFileName, migrationSourcePath, and migrationCollectionPath. Firestore writes emitted by the script are applied to the emulator through the shared Firestore write service. After successful script execution, Firestruct records the migration in the configured migration collection with checksum, source path, status, timestamp, and rollback-note metadata. Output includes selected project JSON, executionMode: emulator-fireway-js, requested and executed IDs, script results, applied Firestore mutation count, refreshed status counts, rollback notes, logs, and a task snapshot. Execution Boundary The Migrations CLI distinguishes three workflows: - status / list / show: inspection only. - record-applied: record-only state write for externally executed migrations. - apply: emulator-only JavaScript execution with Firestore emulator mutation proof and migration-state recording. Production/live apply is not available until approved live verification proves the same workflow safely. Current Verification FirestructCLIIntegrationTests/testCLICommandsRoundTripAgainstFirebaseEmulators writes local migration files, creates Firestore emulator migration records, runs migrations status, asserts applied/drifted/missing/pending counts, runs migrations show and asserts the drifted status plus source content, verifies record-applied rejects missing --confirm, records a pending local migration, then queries the Firestore emulator to assert the migration record exists with status: applied and checksum metadata. The same emulator test verifies migrations apply rejects missing --confirm, executes 005_apply_writes through executionMode: emulator-fireway-js, asserts one Firestore mutation was applied, queries the target emulator collection to prove the script wrote the expected document, and queries the migration collection to prove the migration record exists with status: applied. Source Anchors - Sources/FirestructCLIKit/MigrationsCommand.swift - Sources/FirestructCore/ProjectRegistry+Migrations.swift - Sources/FirestructCore/FirewayIntegrationService.swift

Last updated on Jul 12, 2026

Workspace Link CLI

Current Status Workspace Link has a first-class read-only/safe CLI command group for local workspace linking, local file inspection, and deterministic rules/index diffing. It also exposes task-backed guarded deploy command shapes for Firebase CLI dry-run/real deploy routing. Use the CLI for automation-friendly status, diff, and dry-run task evidence. Failed Firebase CLI dry-run output preserves the exact command plus stdout and stderr so project/auth/API failures are reviewable. Real successful Firebase CLI dry-run output and approved live deploy proof are still open before deploy behavior should be claimed as externally verified. Commands workspace link --path ./firebase-project workspace link --path ./firebase-project --firebase-json ./firebase.custom.json --firebaserc ./firebaserc.custom workspace status workspace diff --rules --remote-rules-file deployed.rules workspace diff --indexes --remote-indexes-file deployed.indexes.json workspace diff --rules --indexes --access-token "$GOOGLE_ACCESS_TOKEN" workspace deploy --rules --dry-run --confirm workspace deploy --indexes --dry-run --confirm workspace deploy --rules --confirm --production-confirm DEPLOY workspace-link is accepted as an alias for workspace. The commands also work through selected-module routing: module select workspace-link run status run diff --rules --remote-rules-file deployed.rules run deploy --indexes --dry-run --confirm Implemented Coverage - local Firebase workspace linking - firebase.json and .firebaserc inspection - rules/index viewing - local rules/index diffing against explicit comparison files - diff reason classification for contentChanged, localMissing, remoteMissing, bothMissing, and malformed firestore.indexes parse errors with diagnostics - live REST rules/index diffing when an access token is supplied - actionable live REST credential/API failure logs for Firebase Rules and Firestore Indexes requests - task-backed deploy command construction for rules and indexes - deploy output containing selected project metadata, config path, command, logs, and task status - read-only real deploy rejection before command execution - production real deploy typed-confirmation guard before command execution Output Contract Successful commands return machine-readable JSON with: - selected project metadata, including linked workspace/config paths - workspaceLink.workspacePath, firebaseJSONPath, firebasercPath - linked files with label, path, existence, and content preview - diff entries with hasDifferences, reason, diagnostics, summary, and diff preview - deploy output with target, dryRun, configPath, command, output, liveDeployAttempted, and requiresApprovedLiveDeployVerification - task output with status, counters, duration, attempts, and error details for deploy commands - executionMode such as local-workspace-inspection, local-file-diff, live-rest-diff, firebase-cli-dry-run, or firebase-cli-deploy When live REST comparison fails, logs include the Firebase API service name, HTTP status, backend message when present, and a credential/IAM remediation hint. This is deterministic error-surfacing coverage; it does not by itself prove live deploy support. When a Firebase CLI deploy/dry-run command fails, errors and logs include the exact /usr/bin/env firebase deploy ... command, stdout JSON when present, and stderr text. This preserves real Firebase CLI failure output for review but does not convert a failed dry-run into external deploy proof. Deploy Boundary workspace deploy requires --confirm and exactly one target flag: --rules or --indexes. Real, non-dry-run deploys reject read-only projects and production real deploys require --production-confirm DEPLOY. Current automated evidence uses a deterministic command runner to prove command shape, guardrails, task output, selected-module routing, and failed command output preservation. A local 2026-06-26 real Firebase CLI dry-run attempt against demo-firestruct reached Firebase and returned project-not-found JSON, which is failure-output evidence only. Before claiming externally verified deploy support, run a successful real Firebase CLI dry-run against a valid local workspace/project or use an approved disposable live project deploy and record the output/cleanup evidence. Verification Covered by: swift build swift test --filter FirestructCLIIntegrationTests/testWorkspaceLinkCLIInspectsAndDiffsLocalFirebaseWorkspace swift test --filter FirestructCLIIntegrationTests/testWorkspaceDeployCLIQueuesDryRunTaskAndGuardsRealDeploy swift test --filter WorkspaceLinkRemoteServiceTests/testFetchDeployedConfigSurfacesActionableCredentialAndAPIErrors swift test --filter WorkspaceLinkRemoteServiceTests/testWorkspaceDeployServiceThrowsOnCommandFailureWithCommandAndOutput swift test --filter WorkspaceDeployTaskTests/testWorkspaceDryRunDeployFailureCapturesCommandAndFirebaseOutput The focused test writes a real temporary Firebase workspace with firebase.json, .firebaserc, rules, and indexes files; links it through the CLI; verifies status output; diffs rules/indexes against explicit remote fixture files; verifies content-changed, remote-missing, parse-error, and local-missing reason output; then verifies selected-module run diff routing. The deploy test uses the same style of temporary Firebase workspace fixture, then verifies workspace deploy --rules --dry-run --confirm and selected-module run deploy --indexes --dry-run --confirm enqueue successful tasks, emit target project/environment/config-path JSON, and call the Firebase deploy command shape with --dry-run and --config. It also proves read-only real deploy and production missing-confirmation guards reject before command execution. The focused failure-output tests prove failed Firebase CLI deploy/dry-run commands keep the command line, stdout JSON, stderr text, task failure status, and Workspace Link logs. Source Anchors - Sources/FirestructCLIKit/WorkspaceCommand.swift - Sources/FirestructCore/WorkspaceLinkRemoteService.swift - Sources/FirestructCore/ProjectRegistry+WorkspaceServices.swift

Last updated on Jul 12, 2026

Support CLI

Current Status There is no Support CLI command group. Support is currently an in-app and help-center workflow, not a terminal interface. The macOS app embeds the configured Chatwoot support surface and the public help center carries module articles for users who need setup or workflow guidance. CLI users should open those resources rather than expecting commands to create tickets or chat sessions. GUI-Only Coverage Today Use the macOS Support module for Chatwoot support access. When reporting an issue, include the Firestruct version, macOS version, target Firebase project type, emulator or production environment, module name, command or UI action, relevant logs, and whether the project is read-only. For data operations, avoid sending secrets, service-account JSON, private Firebase data, or access tokens unless a secure support channel explicitly requests them. The absence of a Support CLI command keeps diagnostics gathering manual for now. That is deliberate while the product is early: users can review the contents of any logs or screenshots before sharing them with support. Future CLI Shape Support CLI coverage is optional. If added, it should focus on diagnostics bundles rather than interactive chat: support diagnostics --output firestruct-diagnostics.zip support open-ticket --subject "Issue summary" If diagnostics support is added later, it should generate a local archive first and ask the user to review it before upload. Interactive chat and account identity should remain tied to the configured support provider. Source Anchors - Sources/FirestructApp/Features/Support/

Last updated on May 07, 2026

Purchases and Pro Access CLI

Current Status There is no Purchases CLI command group and no CLI entitlement workflow. Purchases are intentionally GUI-owned today because StoreKit purchase, restore, and entitlement presentation belong in the native macOS app. The CLI can run project, Firestore, Auth, and Storage workflows, but it should not present itself as a purchase surface or a way to avoid paid feature gates. Current CLI Implication The CLI currently exposes project/module selection plus broad Firestore, Auth, Storage, Tasks, Index Advisor, Seed Studio, Workspace Link, Push validation/token resolution, and Migrations inspection/record-only workflows. It does not expose StoreKit purchase or restore, and it does not yet provide a CLI entitlement status surface. Before promoting CLI automation as a public paid feature surface, CLI Pro enforcement should be designed explicitly so command-line automation cannot bypass GUI access rules. For internal testing, treat CLI mutation access as an implementation detail rather than a product entitlement promise. Any public automation path that creates, updates, deletes, imports, exports, transfers, uploads, deploys, runs scripts, sends push notifications, applies seeds, or applies migrations should respect the same commercial and safety boundaries shown in the app. Support conversations should direct users to the Purchases and Pro Access GUI article for plan details, restore behavior, and paywall expectations. CLI scripts can still be documented for read-only inspection and emulator-safe workflows, but the purchase decision and restore state should remain clear to the user before paid actions begin. Future CLI Shape Expected future commands: pro status pro restore StoreKit purchase itself is likely to remain GUI-native. Source Anchors - Sources/FirestructApp/Features/Purchases/Model/ProAccessState.swift - Sources/FirestructApp/Features/Purchases/Services/AppModel+Purchases.swift

Last updated on Jul 12, 2026