twocents/open source

Configuration reference

Required fields, overrides, validation, and path resolution.

Start with the complete example in getting started, then use the tables below to adjust it. The validator in src/main.ts defines which values are accepted.

Root fields

FieldRequired / defaultMeaning
nameRequiredLowercase kebab-case app label.
appDirectoryRequiredExpo app directory, resolved from the project root.
bundleIdentifierRequiredBundle identifier installed in the simulator.
schemeRequiredURL scheme without ://; must match screenshot deep links.
xcodeSchemeRequiredXcode scheme and basename of its .xcworkspace.
iosProductRequiredBuilt app filename, such as ExampleApp.app.
apiEnvironmentRequiredApp-defined nonempty environment name.
appearancelightlight, dark, system, or both.
backupCodeEnvOmittedName of an environment variable containing an optional setup credential.
backupCodeEmpty stringLiteral setup value supported by the runtime; use backupCodeEnv instead for secrets.
simulatorRequiredNonempty name, deviceType, and runtime.
metroRequiredport, an integer from 1024 through 65535. Must be available.
defaultsRequiredAll four stability settings below; there are no implicit timing defaults.
screenshotsRequiredNonempty array of screenshot definitions.

Names match ^[a-z0-9][a-z0-9-]*$. Schemes must be valid URL schemes and are compared case-insensitively. All filesystem paths are relative to the project root, not the JSON file's directory. Root backupCodeEnv rejects an unset or whitespace-only variable and cannot be combined with a nonempty literal backupCode. Unknown object keys are stripped by the current Zod object schemas; double-check spellings rather than expecting unknown-key errors.

Stability settings

FieldValidationMeaning
minimumWaitMsInteger, at least 0Wait before sampling; included in the timeout budget.
sampleIntervalMsInteger, at least 50Delay between samples.
stableSamplesInteger, at least 2Consecutive sufficiently similar frames required.
timeoutMsInteger, at least 1000Sampling time budget; must exceed minimumWaitMs.

Values are numbers in milliseconds where named Ms. The quickstart's 750 / 250 / 3 / 15000 settings are examples, not built-in defaults. A blocked simulator screenshot operation can outlast the sampling budget; this is not a hard wall-clock deadline for the whole capture.

Screenshot fields and overrides

Every screenshot requires name and deeplink. The name follows the app-name pattern and must be unique. The deep link must be a URL using the configured scheme. Generated PNG filenames must also be unique after appearance expansion.

Optional fields:

  • state: one key or key:value, or a nonempty array; see app states.
  • optional: boolean, defaults to false; metadata, not a failure-policy switch.
  • apiEnvironment, appearance, and backupCode: override root values.
  • minimumWaitMs, sampleIntervalMs, stableSamples, and timeoutMs: override individual root defaults fields. The merged settings must still validate.

backupCodeEnv is a root field, not a per-screenshot override. Avoid storing secrets in per-screenshot literal values. Use separate configurations and an environment variable when captures require different secret credentials.

both expands into light then dark, producing <name>-light.png and <name>-dark.png. A single appearance produces <name>.png. With system, Snapbot does not force a device appearance; it preserves the simulator's current setting and passes system to your app callback.

Choose a dedicated simulator

Snapbot resolves the configured simulator by name. It creates a missing one using the specified device type and installed runtime. Multiple simulators with the same name are an error; the diagnostic lists their UDIDs. Inspect them before manually deleting unwanted duplicates with xcrun simctl delete <udid>. Use a dedicated simulator because Snapbot boots it, installs the app, adjusts appearance and permissions, and shuts it down after the run.

On this page