HotCodePush

Files

What config.json, the keyring entry, hotcodepush.json, the resource file and the private key file hold, where each lives per OS and who writes it.

The CLI keeps five things on disk, listed below with where each one lives. Nothing else: no .hotcodepush directory in the project and no private key the CLI keeps for itself.

FileHoldsWhere
config.jsonHolds the API URL, the session id, the update-check fields, a pending login, the telemetry-notice timestamp, and the token only where no keyring works.the user's config directory
the keyring entryHolds the session token login stored.the OS secure storage
hotcodepush.jsonHolds the app id, the channel by name, the public keys, the SDK options and extraFingerprintPaths.the project root, committed
the resource fileHolds hotcodepush.json minus the CLI's keys, plus the build-time facts.the built app, written by every build, never committed
the private key fileHolds the RSA private key of a signing key pair, PEM, PKCS #8.where signing-key create wrote it, out of version control

config.json

The user's config directory is ~/.config/hotcodepush on macOS and Linux, $XDG_CONFIG_HOME/hotcodepush when that variable is set, and %APPDATA%\hotcodepush on Windows. The file is written with mode 0600 on macOS and Linux, since it can hold the token. One that does not parse is invalid_json.

KeyWritten byHolds
apiUrllogin --api-urlNames the API every command talks to. Defaults to production.
lastUpdateCheckAt, latestKnownVersionthe daily update checkHold when the npm registry was last asked and what it answered.
pending*a login that could not waitHold the device authorization the next login redeems or shows again.
sessionExpiresAtlogin, renewed when a command finds it passed and the API still knows the sessionHolds when the session ends, the hint that makes a command ask to log in again.
sessionIdloginHolds the session's non-secret id, which logout deletes.
telemetryNoticeShownAtthe first command on the machineRecords that the telemetry notice was printed.
tokenlogin, only where no keyring backend worksHolds the session token, the fallback for headless machines.

The keyring entry

The session token lives in the OS secure storage: the macOS Keychain, the Windows Credential Manager or the Secret Service on Linux. The entry is under the service hotcodepush-cli and the account token.

Where no keyring backend works, headless CI the usual case, the token goes into config.json instead. The HOTCODEPUSH_TOKEN variable wins over both, and logout deletes the entry and the fallback while leaving the variable alone.

hotcodepush.json

hotcodepush.json is the project's configuration, next to package.json, written by init and read by every command. --config <path> names it when it lies elsewhere. Running init writes appId and channel. Every command finds the file walking up from the working directory, so the CLI runs from any folder of the repository. Every other key is an SDK option, listed on the configuration pages for React Native, Expo, Capacitor and Cordova.

hotcodepush.json
{
  "appId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "channel": "production"
}
KeyWritten byRead by
appIdinitEvery command reads it, as the default for --app.
channelinit, the app's default channel by namerelease create, the build steps and every verb that takes --channel read it, as the default. Defaults to production when absent.
extraFingerprintPathsyouThe fingerprint reads it and hashes the files under these paths beside the native packages. It is the one key that never reaches a device.
publicKeyssigning-key create and signing-key add append, signing-key delete removesAn upload reads it and signs when the list is not empty, and the build steps write the keys into the resource file.

The CLI keeps the file's indentation when it edits it, and doctor reports a file that does not parse as a failed configuration check.

The resource file

The resource file is what the SDK reads at runtime: hotcodepush.json without channel and extraFingerprintPaths, plus what only a build can know. The SDK package's Xcode phase and Gradle task write it into every native build: binary create in a store build, resource-file write in every other build. It describes one build, so it is never committed.

KeyHolds
appId, publicKeys, the SDK optionsCome from hotcodepush.json, the public keys re-encoded as { "der", "keyId" } in the form the platform's own API imports, PKCS #1 on iOS and SPKI on Android.
builtAtHolds the build's time. No release older than it is applied.
channelIdHolds the channel resolved to its id through the API, or null when the build ran offline or without a token and the project names the channel by name.
embeddedBundleIdHolds the bundle's id once a store build created its binary, or null from resource-file write.
embeddedBundleManifestHolds the embedded bundle's files with path, hash and size, or null for a React Native or Expo debug build that bundled nothing.
filesBaseUrl, updatesBaseUrlHold the hosts the device reads from, written only when they differ from production's. HOTCODEPUSH_FILES_BASE_URL and HOTCODEPUSH_UPDATES_BASE_URL set them.
fingerprintHolds the native fingerprint the build was made on.

How an update reaches a device explains what the SDK does with the file.

The private key file

signing-key create writes the private key of a new pair to hotcodepush-private-key.pem in the working directory, or to --private-key-path, with mode 0600 on macOS and Linux. The CLI never prints the key, never keeps a copy and never looks for the file.

An upload gets the key through --private-key-path, or from HOTCODEPUSH_SIGNING_KEY in CI. Keep the file out of version control. Sign your bundles covers the rotation.

Temporary files

An upload writes its gzip copies and the full pack under a hotcodepush- directory in the system's temporary folder, removed when the command ends. The file hotcodepush fingerprint --json > <file> writes is one you keep, the input of fingerprint diff.

Last updated on

On this page