Mobile web browser providing access to websites that use the Ethereum blockchain
See the code
MetaMask is a mobile wallet that provides easy access to websites that use the Ethereum blockchain.
For up to the minute news, follow our Twitter or Medium pages.
To learn how to develop MetaMask-compatible applications, visit our Developer Docs.
To learn how to contribute to the MetaMask codebase, visit our Contributor Docs.
app/util/number/index.js burndown and ESLint allowlist)MetaMask Mobile requires an Infura project ID to connect to blockchain networks.
.js.env file from 1Password, ask around for the correct vault. This file contains the MM_INFURA_PROJECT_ID.MM_INFURA_PROJECT_ID in .js.env.example.js.env.example to .js.env[!CAUTION]
Without an Infura project ID, the app cannot connect to blockchain networks.
Expo is the fastest way to start developing. With the Expo framework, developers don't need to compile the native side of the application as before, hence no need for any native environment setup, developers only need to download a precompiled development build and run the javascript bundler. The development build will then connect with the bundler to load the javascript code.
Install node, yarn v4 and watchman.
git clone git@github.com:MetaMask/metamask-mobile.git && \
cd metamask-mobile
yarn setup:expo
yarn watch
Expo development builds are produced by the Expo Dev Build GitHub Actions workflow. It runs on every push to main, but only actually compiles iOS/Android when the @expo/fingerprint hash of native code changed since the last build (plus a weekly Monday refresh so artifacts never go stale) — most pushes just reuse the existing build. This means the resolved run may be older than main HEAD; that's expected. Artifacts are stored as GitHub Actions artifacts (not Runway buckets).
Prerequisites: GitHub CLI (gh) authenticated with access to this repository (gh auth login).
Recommended — install the latest build on a simulator/emulator:
# iOS simulator
yarn install:ios:dev
# Android emulator or device
yarn install:android:dev
Download only (no install):
yarn install:ios:dev --skipInstall
yarn install:android:dev --skipInstall
Re-runs skip the download when the GitHub Actions artifact digest matches a local cache under build/gh-expo-dev-build/. Force a fresh download with --force-download:
yarn install:ios:dev --force-download
yarn install:android:dev --force-download
Artifacts land under build/ (MetaMask.app on iOS, metamask-dev.apk on Android). The workflow run id is saved to build/expo-dev-build-run-id.txt.
Manual download from GitHub Actions:
Note: since most runs skip the actual build (fingerprint unchanged), the most recent successful run may not have build artifacts attached — open the run and check for a build-dev job (skipped runs only have resolve-dev-build).
# List recent successful Expo Dev Build runs on main
gh run list --repo MetaMask/metamask-mobile --workflow expo-dev-build.yml --branch main --status success --limit 5
mkdir -p build
# iOS simulator (.zip artifact → extract to MetaMask.app)
gh run download RUN_ID --repo MetaMask/metamask-mobile \
-n ios-app-main-dev-expo -D build
mkdir -p build/MetaMask.app
ditto -x -k build/metamask-simulator-*.zip build/MetaMask.app
# Android debug APK
gh run download RUN_ID --repo MetaMask/metamask-mobile \
-n android-apk-main-dev-expo -D build
cp build/metamask-dev-main-*.apk build/metamask-dev.apk
# iOS physical device (.ipa — requires registered test device)
gh run download RUN_ID --repo MetaMask/metamask-mobile \
-n ios-ipa-main-dev-expo -D build
Use a specific workflow run instead of the latest:
yarn install:ios:dev --run RUN_ID
yarn install:android:dev --run RUN_ID
(--run-id is also accepted.) Related: MCWP-683, supersedes PR #29891.
If on a simulator:
If on a physical device:
That's it! This will work for any javascript development, if you need to develop or modify native code please see the next section.
If developing or modifying native code or installing any library that introduces or uses native code, it is not possible to use an Expo precompiled development build as you need to compile the native side of the application again. To do so, please follow the steps stated in this section.
Before running the app for native development, make sure your development environment has all the required tools. Several of these tools (ie Node and Ruby) may require specific versions in order to successfully build the app.
Setup your development environment
Clone the project
git clone git@github.com:MetaMask/metamask-mobile.git && \
cd metamask-mobile
MetaMask uses Firebase Cloud Messaging (FCM) to enable app communications. To integrate FCM, you'll need configuration files for both iOS and Android platforms.
.js.env file from 1Password, ask around for the correct vault. This file contains the GOOGLE_SERVICES_B64_ANDROID and GOOGLE_SERVICES_B64_IOS secrets that will be used to generate the relevant configuration files for IOS/Android.As an external contributor, you need to provide your own Firebase project configuration files:
GoogleService-Info.plist (iOS)google-services.json (Android)io.metamask (IMPORTANT).google-services.json and GoogleService-Info.plist files in:android/app/google-services.json (for Android)ios/GoogleServices/GoogleService-Info.plist directory (for iOS)# Generate Android Base64 Version of Google Services
export GOOGLE_SERVICES_B64_ANDROID="$(base64 -w0 -i ./android/app/google-services.json)" && echo "export GOOGLE_SERVICES_B64_ANDROID=\"$GOOGLE_SERVICES_B64_ANDROID\"" | tee -a .js.env
# Generate IOS Base64 Version of Google Services
export GOOGLE_SERVICES_B64_IOS="$(base64 -w0 -i ./ios/GoogleServices/GoogleService-Info.plist)" && echo "export GOOGLE_SERVICES_B64_IOS=\"$GOOGLE_SERVICES_B64_IOS\"" | tee -a .js.env
[!CAUTION]
In case you don't provide your own Firebase project config file or run the steps above, you will face the error
No matching client found for package name 'io.metamask'.
In case of any doubt, please follow the instructions in the link below to get your Firebase project config file. Firebase Project Quickstart
yarn setup
Not the usual install command, this will run scripts and a lengthy postinstall flow
Run Metro bundler
yarn watch
Like a local server for the app
Run on a iOS device
yarn start:ios
Run on an Android device
yarn start:android
yarn skills)AI coding agents (Cursor, Claude Code, Codex) consume shared skills from the MetaMask/skills repo, with an optional private overlay from Consensys/skills. Per ADR #57 this content is not committed here — it is synced into local-only paths under .cursor/, .claude/, and .agents/. yarn install syncs the base set; yarn skills syncs every domain.
Zero-config setup:
yarn install # installs the base skill set (and refreshes the MetaMask/skills cache)
yarn skills # installs every domain, not just the base set
Optional local configuration:
cp .skills.local.example .skills.local
# edit .skills.local to set SKILLS_DOMAINS or override skills source paths
yarn skills --select # interactively pick domains
SKILLS_DOMAINS=perps,testing yarn skills # one-off domain override
Use .skills.local for persistent skills configuration. Shell environment variables with the same names are supported for one-off or CI overrides and take precedence.
Skipping yarn skills is fine — it only affects agent tooling, not the app build. The repo uses the shared @metamask/skills package so sync/cache behavior stays uniform across MetaMask packages. Set SKILLS_AUTO_UPDATE=0 in your shell or .skills.local to opt out.
Regeneration is best-effort, and quieter than it sounds. Yarn runs postinstall only when the dependency tree changes or the previous build failed, so a yarn install on an unchanged lockfile will not refresh skills — git pull on a branch that touched no dependencies usually leaves them as they were. Yarn also discards the output of a build it considers successful, and the hook deliberately exits 0 so a skills problem cannot fail yarn install, so nothing is printed either way. Run yarn skills when you want a refresh you can watch.
This project uses Husky to run pre-commit hooks that automatically format and lint your code before commits. The pre-commit hook runs lint-staged which executes:
*.{js,jsx,ts,tsx,json,feature} files*.{js,jsx,ts,tsx} filesGit hooks are opt-in. yarn setup does not install them.
yarn git:hooks:install # enable pre-commit lint/format
yarn git:hooks:uninstall # remove git hooks from this clone
git commit --no-verify -m "your commit message"
# Disable for current session
export HUSKY=0
git commit -m "your commit message"
# Or disable for a single command
HUSKY=0 git commit -m "your commit message"
Note: The CI/CD pipeline still runs linting checks. It's recommended to fix linting issues before pushing your changes to avoid build failures.
57 followers · starred Jan 2022
988 followers · starred Nov 2020
105 followers · starred Sep 2022
41 followers · starred Aug 2024
Mobile web browser providing access to websites that use the Ethereum blockchain
See the code
MetaMask is a mobile wallet that provides easy access to websites that use the Ethereum blockchain.
For up to the minute news, follow our Twitter or Medium pages.
To learn how to develop MetaMask-compatible applications, visit our Developer Docs.
To learn how to contribute to the MetaMask codebase, visit our Contributor Docs.
app/util/number/index.js burndown and ESLint allowlist)MetaMask Mobile requires an Infura project ID to connect to blockchain networks.
.js.env file from 1Password, ask around for the correct vault. This file contains the MM_INFURA_PROJECT_ID.MM_INFURA_PROJECT_ID in .js.env.example.js.env.example to .js.env[!CAUTION]
Without an Infura project ID, the app cannot connect to blockchain networks.
Expo is the fastest way to start developing. With the Expo framework, developers don't need to compile the native side of the application as before, hence no need for any native environment setup, developers only need to download a precompiled development build and run the javascript bundler. The development build will then connect with the bundler to load the javascript code.
Install node, yarn v4 and watchman.
git clone git@github.com:MetaMask/metamask-mobile.git && \
cd metamask-mobile
yarn setup:expo
yarn watch
Expo development builds are produced by the Expo Dev Build GitHub Actions workflow. It runs on every push to main, but only actually compiles iOS/Android when the @expo/fingerprint hash of native code changed since the last build (plus a weekly Monday refresh so artifacts never go stale) — most pushes just reuse the existing build. This means the resolved run may be older than main HEAD; that's expected. Artifacts are stored as GitHub Actions artifacts (not Runway buckets).
Prerequisites: GitHub CLI (gh) authenticated with access to this repository (gh auth login).
Recommended — install the latest build on a simulator/emulator:
# iOS simulator
yarn install:ios:dev
# Android emulator or device
yarn install:android:dev
Download only (no install):
yarn install:ios:dev --skipInstall
yarn install:android:dev --skipInstall
Re-runs skip the download when the GitHub Actions artifact digest matches a local cache under build/gh-expo-dev-build/. Force a fresh download with --force-download:
yarn install:ios:dev --force-download
yarn install:android:dev --force-download
Artifacts land under build/ (MetaMask.app on iOS, metamask-dev.apk on Android). The workflow run id is saved to build/expo-dev-build-run-id.txt.
Manual download from GitHub Actions:
Note: since most runs skip the actual build (fingerprint unchanged), the most recent successful run may not have build artifacts attached — open the run and check for a build-dev job (skipped runs only have resolve-dev-build).
# List recent successful Expo Dev Build runs on main
gh run list --repo MetaMask/metamask-mobile --workflow expo-dev-build.yml --branch main --status success --limit 5
mkdir -p build
# iOS simulator (.zip artifact → extract to MetaMask.app)
gh run download RUN_ID --repo MetaMask/metamask-mobile \
-n ios-app-main-dev-expo -D build
mkdir -p build/MetaMask.app
ditto -x -k build/metamask-simulator-*.zip build/MetaMask.app
# Android debug APK
gh run download RUN_ID --repo MetaMask/metamask-mobile \
-n android-apk-main-dev-expo -D build
cp build/metamask-dev-main-*.apk build/metamask-dev.apk
# iOS physical device (.ipa — requires registered test device)
gh run download RUN_ID --repo MetaMask/metamask-mobile \
-n ios-ipa-main-dev-expo -D build
Use a specific workflow run instead of the latest:
yarn install:ios:dev --run RUN_ID
yarn install:android:dev --run RUN_ID
(--run-id is also accepted.) Related: MCWP-683, supersedes PR #29891.
If on a simulator:
If on a physical device:
That's it! This will work for any javascript development, if you need to develop or modify native code please see the next section.
If developing or modifying native code or installing any library that introduces or uses native code, it is not possible to use an Expo precompiled development build as you need to compile the native side of the application again. To do so, please follow the steps stated in this section.
Before running the app for native development, make sure your development environment has all the required tools. Several of these tools (ie Node and Ruby) may require specific versions in order to successfully build the app.
Setup your development environment
Clone the project
git clone git@github.com:MetaMask/metamask-mobile.git && \
cd metamask-mobile
MetaMask uses Firebase Cloud Messaging (FCM) to enable app communications. To integrate FCM, you'll need configuration files for both iOS and Android platforms.
.js.env file from 1Password, ask around for the correct vault. This file contains the GOOGLE_SERVICES_B64_ANDROID and GOOGLE_SERVICES_B64_IOS secrets that will be used to generate the relevant configuration files for IOS/Android.As an external contributor, you need to provide your own Firebase project configuration files:
GoogleService-Info.plist (iOS)google-services.json (Android)io.metamask (IMPORTANT).google-services.json and GoogleService-Info.plist files in:android/app/google-services.json (for Android)ios/GoogleServices/GoogleService-Info.plist directory (for iOS)# Generate Android Base64 Version of Google Services
export GOOGLE_SERVICES_B64_ANDROID="$(base64 -w0 -i ./android/app/google-services.json)" && echo "export GOOGLE_SERVICES_B64_ANDROID=\"$GOOGLE_SERVICES_B64_ANDROID\"" | tee -a .js.env
# Generate IOS Base64 Version of Google Services
export GOOGLE_SERVICES_B64_IOS="$(base64 -w0 -i ./ios/GoogleServices/GoogleService-Info.plist)" && echo "export GOOGLE_SERVICES_B64_IOS=\"$GOOGLE_SERVICES_B64_IOS\"" | tee -a .js.env
[!CAUTION]
In case you don't provide your own Firebase project config file or run the steps above, you will face the error
No matching client found for package name 'io.metamask'.
In case of any doubt, please follow the instructions in the link below to get your Firebase project config file. Firebase Project Quickstart
yarn setup
Not the usual install command, this will run scripts and a lengthy postinstall flow
Run Metro bundler
yarn watch
Like a local server for the app
Run on a iOS device
yarn start:ios
Run on an Android device
yarn start:android
yarn skills)AI coding agents (Cursor, Claude Code, Codex) consume shared skills from the MetaMask/skills repo, with an optional private overlay from Consensys/skills. Per ADR #57 this content is not committed here — it is synced into local-only paths under .cursor/, .claude/, and .agents/. yarn install syncs the base set; yarn skills syncs every domain.
Zero-config setup:
yarn install # installs the base skill set (and refreshes the MetaMask/skills cache)
yarn skills # installs every domain, not just the base set
Optional local configuration:
cp .skills.local.example .skills.local
# edit .skills.local to set SKILLS_DOMAINS or override skills source paths
yarn skills --select # interactively pick domains
SKILLS_DOMAINS=perps,testing yarn skills # one-off domain override
Use .skills.local for persistent skills configuration. Shell environment variables with the same names are supported for one-off or CI overrides and take precedence.
Skipping yarn skills is fine — it only affects agent tooling, not the app build. The repo uses the shared @metamask/skills package so sync/cache behavior stays uniform across MetaMask packages. Set SKILLS_AUTO_UPDATE=0 in your shell or .skills.local to opt out.
Regeneration is best-effort, and quieter than it sounds. Yarn runs postinstall only when the dependency tree changes or the previous build failed, so a yarn install on an unchanged lockfile will not refresh skills — git pull on a branch that touched no dependencies usually leaves them as they were. Yarn also discards the output of a build it considers successful, and the hook deliberately exits 0 so a skills problem cannot fail yarn install, so nothing is printed either way. Run yarn skills when you want a refresh you can watch.
This project uses Husky to run pre-commit hooks that automatically format and lint your code before commits. The pre-commit hook runs lint-staged which executes:
*.{js,jsx,ts,tsx,json,feature} files*.{js,jsx,ts,tsx} filesGit hooks are opt-in. yarn setup does not install them.
yarn git:hooks:install # enable pre-commit lint/format
yarn git:hooks:uninstall # remove git hooks from this clone
git commit --no-verify -m "your commit message"
# Disable for current session
export HUSKY=0
git commit -m "your commit message"
# Or disable for a single command
HUSKY=0 git commit -m "your commit message"
Note: The CI/CD pipeline still runs linting checks. It's recommended to fix linting issues before pushing your changes to avoid build failures.
57 followers · starred Jan 2022
988 followers · starred Nov 2020
105 followers · starred Sep 2022
41 followers · starred Aug 2024