diff --git a/__e2e__/__snapshots__/config.test.ts.snap b/__e2e__/__snapshots__/config.test.ts.snap
index 0249bc706..ddb819206 100644
--- a/__e2e__/__snapshots__/config.test.ts.snap
+++ b/__e2e__/__snapshots__/config.test.ts.snap
@@ -26,7 +26,7 @@ exports[`shows up current config without unnecessary output 1`] = `
     },
     {
       "name": "build-ios",
-      "description": "builds your app for iOS platform",
+      "description": "builds your app on iOS simulator",
       "examples": [
         "<<REPLACED>>"
       ],
@@ -65,9 +65,7 @@ exports[`shows up current config without unnecessary output 1`] = `
     "android": {
       "sourceDir": "<<REPLACED_ROOT>>/TestProject/android",
       "appName": "app",
-      "packageName": "com.testproject",
-      "applicationId": "com.testproject",
-      "mainActivity": ".MainActivity"
+      "packageName": "com.testproject"
     }
   }
 }
diff --git a/packages/cli-config/src/__tests__/__snapshots__/index-test.ts.snap b/packages/cli-config/src/__tests__/__snapshots__/index-test.ts.snap
index 453523b62..505caac8e 100644
--- a/packages/cli-config/src/__tests__/__snapshots__/index-test.ts.snap
+++ b/packages/cli-config/src/__tests__/__snapshots__/index-test.ts.snap
@@ -11,7 +11,7 @@ Object {
       ],
       "podspecPath": "<<REPLACED>>/node_modules/react-native-test/ReactNativeTest.podspec",
       "scriptPhases": Array [],
-      "version": "unresolved",
+      "version": "0.0.1",
     },
   },
   "root": "<<REPLACED>>/node_modules/react-native-test",
@@ -58,7 +58,7 @@ Object {
           "path": "./phase.sh",
         },
       ],
-      "version": "unresolved",
+      "version": "0.0.1",
     },
   },
   "root": "<<REPLACED>>/node_modules/react-native-test",
@@ -109,7 +109,7 @@ Object {
           "show_env_vars_in_log": false,
         },
       ],
-      "version": "unresolved",
+      "version": "0.0.1",
     },
   },
   "root": "<<REPLACED>>/node_modules/react-native-test",
@@ -134,7 +134,7 @@ Object {
         "configurations": Array [],
         "podspecPath": "<<REPLACED>>/node_modules/react-native-test/ReactNativeTest.podspec",
         "scriptPhases": Array [],
-        "version": "unresolved",
+        "version": "0.0.1",
       },
     },
     "root": "<<REPLACED>>/node_modules/react-native-test",
@@ -153,7 +153,7 @@ Object {
       ],
       "podspecPath": "<<REPLACED>>/node_modules/react-native-test/ReactNativeTest.podspec",
       "scriptPhases": Array [],
-      "version": "unresolved",
+      "version": "0.0.1",
     },
   },
   "root": "<<REPLACED>>/node_modules/react-native-test",
diff --git a/packages/cli-config/src/__tests__/findDependencies-test.ts b/packages/cli-config/src/__tests__/findDependencies-test.ts
index 90a366faf..cb2af37bf 100644
--- a/packages/cli-config/src/__tests__/findDependencies-test.ts
+++ b/packages/cli-config/src/__tests__/findDependencies-test.ts
@@ -14,10 +14,24 @@ test('returns plugins from both dependencies and dev dependencies', () => {
   writeFiles(DIR, {
     'package.json': `
       {
+        "name": "plugin",
+        "version": "1.0.0",
         "dependencies": {"rnpm-plugin-test": "*"},
         "devDependencies": {"rnpm-plugin-test-2": "*"}
       }
     `,
+    'node_modules/rnpm-plugin-test/package.json': `
+    {
+      "name": "rnpm-plugin-test",
+      "version": "1.0.0"
+
+    }`,
+    'node_modules/rnpm-plugin-test-2/package.json': `
+    {
+      "name": "rnpm-plugin-test-2",
+      "version": "1.0.0"
+    }`,
   });
-  expect(findDependencies(DIR)).toHaveLength(2);
+
+  expect(findDependencies(DIR).size).toBe(3);
 });
diff --git a/packages/cli-config/src/__tests__/index-test.ts b/packages/cli-config/src/__tests__/index-test.ts
index 104ed7de0..b7157e310 100644
--- a/packages/cli-config/src/__tests__/index-test.ts
+++ b/packages/cli-config/src/__tests__/index-test.ts
@@ -17,7 +17,12 @@ const androidPath = slash(
 );
 
 const REACT_NATIVE_MOCK = {
-  'node_modules/react-native/package.json': '{}',
+  'node_modules/react-native/package.json': `
+  {
+    "name": "react-native",
+    "version": "0.0.1"
+  }
+  `,
   'node_modules/react-native/react-native.config.js': `
     const ios = require("${iosPath}");
     const android = require("${androidPath}");
@@ -59,22 +64,27 @@ beforeEach(async () => {
 
 afterEach(async () => await cleanup(DIR));
 
-test('should have a valid structure by default', () => {
+test('should have a valid structure by default', async () => {
   DIR = getTempDirectory('config_test_structure');
   writeFiles(DIR, {
     'react-native.config.js': `module.exports = {
       reactNativePath: "."
     }`,
   });
-  const config = loadConfig(DIR);
+  const config = await loadConfig(DIR);
   expect(removeString(config, DIR)).toMatchSnapshot();
 });
 
-test('should return dependencies from package.json', () => {
+test('should return dependencies from package.json', async () => {
   DIR = getTempDirectory('config_test_deps');
   writeFiles(DIR, {
     ...REACT_NATIVE_MOCK,
-    'node_modules/react-native-test/package.json': '{}',
+    'node_modules/react-native-test/package.json': `
+    {
+      "name": "react-native-test",
+      "version": "0.0.1"
+    }
+    `,
     'node_modules/react-native-test/ReactNativeTest.podspec': '',
     'package.json': `{
       "dependencies": {
@@ -83,15 +93,20 @@ test('should return dependencies from package.json', () => {
       }
     }`,
   });
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
   expect(removeString(dependencies, DIR)).toMatchSnapshot();
 });
 
-test('should read a config of a dependency and use it to load other settings', () => {
+test('should read a config of a dependency and use it to load other settings', async () => {
   DIR = getTempDirectory('config_test_settings');
   writeFiles(DIR, {
     ...REACT_NATIVE_MOCK,
-    'node_modules/react-native-test/package.json': '{}',
+    'node_modules/react-native-test/package.json': `
+    {
+      "name": "react-native-test",
+      "version": "0.0.1"
+    }
+    `,
     'node_modules/react-native-test/ReactNativeTest.podspec': '',
     'node_modules/react-native-test/react-native.config.js': `module.exports = {
       dependency: {
@@ -122,17 +137,22 @@ test('should read a config of a dependency and use it to load other settings', (
       }
     }`,
   });
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
   expect(
     removeString(dependencies['react-native-test'], DIR),
   ).toMatchSnapshot();
 });
 
-test('should merge project configuration with default values', () => {
+test('should merge project configuration with default values', async () => {
   DIR = getTempDirectory('config_test_merge');
   writeFiles(DIR, {
     ...REACT_NATIVE_MOCK,
-    'node_modules/react-native-test/package.json': '{}',
+    'node_modules/react-native-test/package.json': `
+    {
+      "name": "react-native-test",
+      "version": "0.0.1"
+    }
+    `,
     'node_modules/react-native-test/ReactNativeTest.podspec': '',
     'package.json': `{
       "dependencies": {
@@ -153,17 +173,22 @@ test('should merge project configuration with default values', () => {
       }
     }`,
   });
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
   expect(removeString(dependencies['react-native-test'], DIR)).toMatchSnapshot(
     'snapshoting `react-native-test` config',
   );
 });
 
-test('should load commands from "react-native-foo" and "react-native-bar" packages', () => {
+test('should load commands from "react-native-foo" and "react-native-bar" packages', async () => {
   DIR = getTempDirectory('config_test_packages');
   writeFiles(DIR, {
     'react-native.config.js': 'module.exports = { reactNativePath: "." }',
-    'node_modules/react-native-foo/package.json': '{}',
+    'node_modules/react-native-foo/package.json': `
+    {
+      "name": "react-native-foo",
+      "version": "0.0.1"
+    }
+    `,
     'node_modules/react-native-foo/react-native.config.js': `module.exports = {
       commands: [
         {
@@ -172,7 +197,12 @@ test('should load commands from "react-native-foo" and "react-native-bar" packag
         }
       ]
     }`,
-    'node_modules/react-native-bar/package.json': '{}',
+    'node_modules/react-native-bar/package.json': `
+    {
+      "name": "react-native-bar",
+      "version": "0.0.1"
+    }
+    `,
     'node_modules/react-native-bar/react-native.config.js': `module.exports = {
       commands: [
         {
@@ -188,15 +218,20 @@ test('should load commands from "react-native-foo" and "react-native-bar" packag
       }
     }`,
   });
-  const {commands} = loadConfig(DIR);
+  const {commands} = await loadConfig(DIR);
   expect(commands).toMatchSnapshot();
 });
 
-test('should not skip packages that have invalid configuration (to avoid breaking users)', () => {
+test('should not skip packages that have invalid configuration (to avoid breaking users)', async () => {
   process.env.FORCE_COLOR = '0'; // To disable chalk
   DIR = getTempDirectory('config_test_skip');
   writeFiles(DIR, {
-    'node_modules/react-native/package.json': '{}',
+    'node_modules/react-native/package.json': `
+    {
+      "name": "react-native",
+      "version": "0.0.1"
+    }
+    `,
     'node_modules/react-native/react-native.config.js': `module.exports = {
       dependency: {
         invalidProperty: 5
@@ -208,18 +243,20 @@ test('should not skip packages that have invalid configuration (to avoid breakin
       }
     }`,
   });
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
   expect(removeString(dependencies, DIR)).toMatchSnapshot(
     'dependencies config',
   );
   expect(spy.mock.calls[0][0]).toMatchSnapshot('logged warning');
 });
 
-test('does not use restricted "react-native" key to resolve config from package.json', () => {
+test('does not use restricted "react-native" key to resolve config from package.json', async () => {
   DIR = getTempDirectory('config_test_restricted');
   writeFiles(DIR, {
     'node_modules/react-native-netinfo/package.json': `{
-      "react-native": "src/index.js"
+      "react-native": "src/index.js",
+      "name": "react-native-netinfo",
+      "version": "0.0.1"
     }`,
     'react-native.config.js': 'module.exports = { reactNativePath: "." }',
     'package.json': `{
@@ -228,12 +265,13 @@ test('does not use restricted "react-native" key to resolve config from package.
       }
     }`,
   });
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
+
   expect(dependencies).toHaveProperty('react-native-netinfo');
   expect(spy).not.toHaveBeenCalled();
 });
 
-test('supports dependencies from user configuration with custom root and properties', () => {
+test('supports dependencies from user configuration with custom root and properties', async () => {
   DIR = getTempDirectory('config_test_custom_root');
   const escapePathSeparator = (value: string) =>
     path.sep === '\\' ? value.replace(/(\/|\\)/g, '\\\\') : value;
@@ -274,7 +312,7 @@ module.exports = {
     }`,
   });
 
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
   expect(removeString(dependencies['local-lib'], DIR)).toMatchInlineSnapshot(`
     Object {
       "name": "local-lib",
@@ -292,11 +330,14 @@ module.exports = {
   `);
 });
 
-test('should apply build types from dependency config', () => {
+test('should apply build types from dependency config', async () => {
   DIR = getTempDirectory('config_test_apply_dependency_config');
   writeFiles(DIR, {
     ...REACT_NATIVE_MOCK,
-    'node_modules/react-native-test/package.json': '{}',
+    'node_modules/react-native-test/package.json': `{
+      "name": "react-native-test",
+      "version": "0.0.1"
+    }`,
     'node_modules/react-native-test/ReactNativeTest.podspec': '',
     'node_modules/react-native-test/react-native.config.js': `module.exports = {
       dependency: {
@@ -314,13 +355,13 @@ test('should apply build types from dependency config', () => {
       }
     }`,
   });
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
   expect(
     removeString(dependencies['react-native-test'], DIR),
   ).toMatchSnapshot();
 });
 
-test('supports dependencies from user configuration with custom build type', () => {
+test('supports dependencies from user configuration with custom build type', async () => {
   DIR = getTempDirectory('config_test_apply_custom_build_config');
   writeFiles(DIR, {
     ...REACT_NATIVE_MOCK,
@@ -335,7 +376,12 @@ test('supports dependencies from user configuration with custom build type', ()
     },
   }
 }`,
-    'node_modules/react-native-test/package.json': '{}',
+    'node_modules/react-native-test/package.json': `
+    {
+      "name": "react-native-test",
+      "version": "0.0.1"
+    }
+    `,
     'node_modules/react-native-test/ReactNativeTest.podspec': '',
     'node_modules/react-native-test/react-native.config.js':
       'module.exports = {}',
@@ -347,17 +393,20 @@ test('supports dependencies from user configuration with custom build type', ()
     }`,
   });
 
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
   expect(
     removeString(dependencies['react-native-test'], DIR),
   ).toMatchSnapshot();
 });
 
-test('supports disabling dependency for ios platform', () => {
+test('supports disabling dependency for ios platform', async () => {
   DIR = getTempDirectory('config_test_disable_dependency_platform');
   writeFiles(DIR, {
     ...REACT_NATIVE_MOCK,
-    'node_modules/react-native-test/package.json': '{}',
+    'node_modules/react-native-test/package.json': `{
+      "name": "react-native-test",
+      "version": "0.0.1"
+    }`,
     'node_modules/react-native-test/ReactNativeTest.podspec': '',
     'node_modules/react-native-test/react-native.config.js': `
       module.exports = {
@@ -376,13 +425,13 @@ test('supports disabling dependency for ios platform', () => {
     }`,
   });
 
-  const {dependencies} = loadConfig(DIR);
+  const {dependencies} = await loadConfig(DIR);
   expect(
     removeString(dependencies['react-native-test'], DIR),
   ).toMatchSnapshot();
 });
 
-test('should convert project sourceDir relative path to absolute', () => {
+test('should convert project sourceDir relative path to absolute', async () => {
   DIR = getTempDirectory('config_test_absolute_project_source_dir');
   const iosProjectDir = './ios2';
   const androidProjectDir = './android2';
@@ -441,7 +490,7 @@ test('should convert project sourceDir relative path to absolute', () => {
     `,
   });
 
-  const config = loadConfig(DIR);
+  const config = await loadConfig(DIR);
 
   expect(config.project.ios?.sourceDir).toBe(path.join(DIR, iosProjectDir));
   expect(config.project.android?.sourceDir).toBe(
diff --git a/packages/cli-config/src/findDependencies.ts b/packages/cli-config/src/findDependencies.ts
index cb0f5ecd0..e05114355 100644
--- a/packages/cli-config/src/findDependencies.ts
+++ b/packages/cli-config/src/findDependencies.ts
@@ -1,24 +1,49 @@
+import {DependencyMap} from '@react-native-community/cli-types';
+import {findDependencyPath} from '@react-native-community/cli-tools';
 import path from 'path';
 import fs from 'fs';
 
 /**
  * Returns an array of dependencies from project's package.json
  */
-export default function findDependencies(root: string): Array<string> {
-  let pjson;
+export default function findDependencies(root: string): DependencyMap {
+  const dependencies: DependencyMap = new Map();
+
+  const checkDependency = (dependencyPath: string) => {
+    let pjson: {[key: string]: any};
+
+    const packageJsonPath = path.join(dependencyPath, 'package.json');
+
+    if (!fs.existsSync(packageJsonPath)) {
+      return;
+    }
 
-  try {
     pjson = JSON.parse(
-      fs.readFileSync(path.join(root, 'package.json'), 'utf8'),
+      fs.readFileSync(path.join(dependencyPath, 'package.json'), 'utf8'),
     );
-  } catch (e) {
-    return [];
-  }
 
-  const deps = [
-    ...Object.keys(pjson.dependencies || {}),
-    ...Object.keys(pjson.devDependencies || {}),
-  ];
+    if (dependencies.has(pjson.name)) {
+      return;
+    }
+
+    dependencies.set(pjson.name, {
+      version: pjson.version,
+      peerDependencies: pjson.peerDependencies || {},
+      path: dependencyPath,
+    });
+
+    for (const dependency in {
+      ...pjson.dependencies,
+      ...pjson.devDependencies,
+    }) {
+      const depPath = findDependencyPath(dependency, root, dependencyPath);
+      if (depPath) {
+        checkDependency(depPath);
+      }
+    }
+  };
+
+  checkDependency(root);
 
-  return deps;
+  return dependencies;
 }
diff --git a/packages/cli-config/src/loadConfig.ts b/packages/cli-config/src/loadConfig.ts
index ffd3533de..66af3d4bf 100644
--- a/packages/cli-config/src/loadConfig.ts
+++ b/packages/cli-config/src/loadConfig.ts
@@ -11,6 +11,7 @@ import {
   version,
   resolveNodeModuleDir,
   UnknownProjectError,
+  resolveTransitiveDeps,
 } from '@react-native-community/cli-tools';
 import findDependencies from './findDependencies';
 import resolveReactNativePath from './resolveReactNativePath';
@@ -75,7 +76,9 @@ function getReactNativeVersion(reactNativePath: string) {
 /**
  * Loads CLI configuration
  */
-function loadConfig(projectRoot: string = findProjectRoot()): Config {
+async function loadConfig(
+  projectRoot: string = findProjectRoot(),
+): Promise<Config> {
   let lazyProject: ProjectConfig;
   const userConfig = readConfigFromDisk(projectRoot);
 
@@ -113,11 +116,22 @@ function loadConfig(projectRoot: string = findProjectRoot()): Config {
     },
   };
 
+  const dependencyMap = findDependencies(projectRoot);
+  let dependencies = Array.from(dependencyMap.keys());
+
+  if (
+    userConfig.unstable_autolinkPeerDependencies &&
+    !process.argv.includes('config')
+  ) {
+    const installedDependencies = await resolveTransitiveDeps(
+      projectRoot,
+      dependencyMap,
+    );
+    dependencies = [...dependencies, ...installedDependencies];
+  }
+
   const finalConfig = Array.from(
-    new Set([
-      ...Object.keys(userConfig.dependencies),
-      ...findDependencies(projectRoot),
-    ]),
+    new Set([...Object.keys(userConfig.dependencies), ...dependencies]),
   ).reduce((acc: Config, dependencyName) => {
     const localDependencyRoot =
       userConfig.dependencies[dependencyName] &&
diff --git a/packages/cli-config/src/schema.ts b/packages/cli-config/src/schema.ts
index ee4ed7074..91c759633 100644
--- a/packages/cli-config/src/schema.ts
+++ b/packages/cli-config/src/schema.ts
@@ -186,6 +186,7 @@ export const projectConfig = t
         linkConfig: t.func(),
       }),
     ).default({}),
+    unstable_autolinkPeerDependencies: t.bool(),
   })
   .unknown(true)
   .default();
diff --git a/packages/cli-doctor/src/commands/doctor.ts b/packages/cli-doctor/src/commands/doctor.ts
index 7271aa1f6..667999456 100644
--- a/packages/cli-doctor/src/commands/doctor.ts
+++ b/packages/cli-doctor/src/commands/doctor.ts
@@ -175,7 +175,7 @@ const doctorCommand = (async (_, options, config) => {
     Promise.all(categories.map(iterateOverHealthChecks));
 
   const healthchecksPerCategory = await iterateOverCategories(
-    Object.values(getHealthchecks(options)).filter(
+    Object.values(await getHealthchecks(options)).filter(
       (category) => category !== undefined,
     ) as HealthCheckCategory[],
   );
diff --git a/packages/cli-doctor/src/tools/healthchecks/index.ts b/packages/cli-doctor/src/tools/healthchecks/index.ts
index cd8b8fb37..8bca0c348 100644
--- a/packages/cli-doctor/src/tools/healthchecks/index.ts
+++ b/packages/cli-doctor/src/tools/healthchecks/index.ts
@@ -1,3 +1,5 @@
+import loadConfig from '@react-native-community/cli-config';
+import {logger} from '@react-native-community/cli-tools';
 import nodeJS from './nodeJS';
 import {yarn, npm} from './packageManagers';
 import adb from './adb';
@@ -12,11 +14,9 @@ import xcode from './xcode';
 import cocoaPods from './cocoaPods';
 import iosDeploy from './iosDeploy';
 import {Healthchecks, HealthCheckCategory} from '../../types';
-import loadConfig from '@react-native-community/cli-config';
 import xcodeEnv from './xcodeEnv';
 import packager from './packager';
 import deepmerge from 'deepmerge';
-import {logger} from '@react-native-community/cli-tools';
 
 export const HEALTHCHECK_TYPES = {
   ERROR: 'ERROR',
@@ -28,14 +28,16 @@ type Options = {
   contributor: boolean | void;
 };
 
-export const getHealthchecks = ({contributor}: Options): Healthchecks => {
+export const getHealthchecks = async ({
+  contributor,
+}: Options): Promise<Healthchecks> => {
   let additionalChecks: HealthCheckCategory[] = [];
   let projectSpecificHealthchecks = {};
   let config;
 
   // Doctor can run in a detached mode, where there isn't a config so this can fail
   try {
-    config = loadConfig();
+    config = await loadConfig();
     additionalChecks = config.healthChecks;
 
     if (config.reactNativePath) {
diff --git a/packages/cli/src/tools/__tests__/packageManager-test.ts b/packages/cli-tools/src/__tests__/packageManager-test.ts
similarity index 99%
rename from packages/cli/src/tools/__tests__/packageManager-test.ts
rename to packages/cli-tools/src/__tests__/packageManager-test.ts
index 78c31a652..03a3d2b27 100644
--- a/packages/cli/src/tools/__tests__/packageManager-test.ts
+++ b/packages/cli-tools/src/__tests__/packageManager-test.ts
@@ -2,7 +2,7 @@ jest.mock('execa', () => jest.fn());
 import execa from 'execa';
 import * as yarn from '../yarn';
 import * as bun from '../bun';
-import {logger} from '@react-native-community/cli-tools';
+import logger from '../logger';
 import * as PackageManager from '../packageManager';
 
 const PACKAGES = ['react', 'react-native'];
diff --git a/packages/cli-tools/src/__tests__/resolveTransitiveDeps.test.ts b/packages/cli-tools/src/__tests__/resolveTransitiveDeps.test.ts
new file mode 100644
index 000000000..7696efda1
--- /dev/null
+++ b/packages/cli-tools/src/__tests__/resolveTransitiveDeps.test.ts
@@ -0,0 +1,241 @@
+import path from 'path';
+import prompts from 'prompts';
+import {cleanup, getTempDirectory, writeFiles} from '../../../../jest/helpers';
+import {
+  calculateWorkingVersion,
+  filterInstalledPeers,
+  filterNativeDependencies,
+  findDependencyPath,
+  getMissingPeerDeps,
+  resolveTransitiveDeps,
+} from '../resolveTransitiveDeps';
+import logger from '../logger';
+import findDependencies from '../../../cli-config/src/findDependencies';
+
+jest.mock('execa', () => jest.fn());
+jest.mock('prompts', () => ({prompt: jest.fn()}));
+
+jest.mock('../logger', () => ({
+  isVerbose: jest.fn(),
+  warn: jest.fn(),
+  log: jest.fn(),
+}));
+
+const mockFetchJson = jest.fn();
+
+jest.mock('npm-registry-fetch', () => ({
+  json: mockFetchJson,
+}));
+
+const rootPackageJson = {
+  name: 'App',
+  version: '1.0.0',
+  dependencies: {
+    'react-native': '0.72.4',
+    '@react-navigation/stack': '^6.3.17',
+  },
+};
+
+const stackPackageJson = {
+  name: '@react-navigation/stack',
+  version: '6.3.17',
+  dependencies: {
+    '@react-navigation/elements': '^1.3.18',
+    'react-native-gesture-handler': '^1.10.3',
+  },
+  peerDependencies: {
+    react: '*',
+    'react-native': '*',
+    'react-native-gesture-handler': '>= 1.0.0',
+  },
+};
+
+const elementsPackageJson = {
+  name: '@react-navigation/elements',
+  version: '1.3.18',
+  peerDependencies: {
+    react: '*',
+    'react-native': '*',
+    'react-native-safe-area-view': '*',
+  },
+};
+
+const gestureHandlerPackageJson = {
+  name: 'react-native-gesture-handler',
+  version: '2.1.0',
+};
+
+const DIR = getTempDirectory('root_test');
+
+const createTempFiles = (rest?: Record<string, string>) => {
+  writeFiles(DIR, {
+    'package.json': JSON.stringify(rootPackageJson),
+    'node_modules/@react-navigation/stack/package.json': JSON.stringify(
+      stackPackageJson,
+    ),
+    'node_modules/@react-navigation/elements/package.json': JSON.stringify(
+      elementsPackageJson,
+    ),
+    'node_modules/react-native-gesture-handler/package.json': JSON.stringify(
+      gestureHandlerPackageJson,
+    ),
+    'node_modules/react-native-gesture-handler/ios/Podfile': '',
+    ...rest,
+  });
+};
+
+beforeEach(async () => {
+  await cleanup(DIR);
+  jest.resetAllMocks();
+});
+
+describe('calculateWorkingVersion', () => {
+  it('should return the highest matching version for all ranges', () => {
+    const workingVersion = calculateWorkingVersion(
+      ['*', '>=2.2.0', '>=2.0.0'],
+      ['1.9.0', '2.0.0', '2.2.0', '3.0.0'],
+    );
+
+    expect(workingVersion).toBe('3.0.0');
+  });
+
+  it('should return null if no version matches all ranges', () => {
+    const workingVersion = calculateWorkingVersion(
+      ['*', '>=2.2.0', '^1.0.0-alpha'],
+      ['1.9.0', '2.0.0', '2.1.0'],
+    );
+
+    expect(workingVersion).toBe(null);
+  });
+});
+
+describe('findDependencyPath', () => {
+  it('should return the path to the dependency if it is in top-level node_modules', () => {
+    writeFiles(DIR, {
+      'package.json': JSON.stringify(rootPackageJson),
+      'node_modules/@react-navigation/stack/package.json': JSON.stringify(
+        stackPackageJson,
+      ),
+    });
+
+    const dependencyPath = findDependencyPath(
+      '@react-navigation/stack',
+      DIR,
+      path.join(DIR, 'node_modules', '@react-navigation/stack'),
+    );
+
+    expect(dependencyPath).toBe(
+      path.join(DIR, 'node_modules', '@react-navigation/stack'),
+    );
+  });
+
+  it('should return the path to the nested node_modules if package is installed here', () => {
+    writeFiles(DIR, {
+      'package.json': JSON.stringify(rootPackageJson),
+      'node_modules/@react-navigation/stack/node_modules/react-native-gesture-handler/package.json':
+        '{}',
+    });
+
+    const dependencyPath = findDependencyPath(
+      'react-native-gesture-handler',
+      DIR,
+      path.join(DIR, 'node_modules', '@react-navigation/stack'),
+    );
+
+    expect(dependencyPath).toBe(
+      path.join(
+        DIR,
+        'node_modules',
+        '@react-navigation/stack',
+        'node_modules',
+        'react-native-gesture-handler',
+      ),
+    );
+  });
+});
+
+describe('filterNativeDependencies', () => {
+  it('should return only dependencies with peer dependencies containing native code', () => {
+    createTempFiles({
+      'node_modules/react-native-safe-area-view/ios/Podfile': '{}',
+    });
+    const dependencies = findDependencies(DIR);
+    const filtered = filterNativeDependencies(DIR, dependencies);
+    expect(filtered.keys()).toContain('@react-navigation/elements');
+  });
+});
+
+describe('filterInstalledPeers', () => {
+  it('should return only dependencies with peer dependencies that are installed', () => {
+    createTempFiles();
+    const dependencies = findDependencies(DIR);
+    const libsWithNativeDeps = filterNativeDependencies(DIR, dependencies);
+    const nonInstalledPeers = filterInstalledPeers(DIR, libsWithNativeDeps);
+
+    expect(Object.keys(nonInstalledPeers)).toContain('@react-navigation/stack');
+    expect(Object.keys(nonInstalledPeers['@react-navigation/stack'])).toContain(
+      'react-native-gesture-handler',
+    );
+  });
+});
+
+describe('getMissingPeerDepsForYarn', () => {
+  it('should return an array of peer dependencies to install', () => {
+    createTempFiles();
+    const dependencies = findDependencies(DIR);
+    const missingDeps = getMissingPeerDeps(DIR, dependencies);
+    expect(missingDeps.values()).toContain('react');
+    expect(missingDeps.values()).toContain('react-native-gesture-handler');
+    expect(missingDeps.values()).toContain('react-native-safe-area-view');
+  });
+});
+
+describe('resolveTransitiveDeps', () => {
+  it('should display list of missing peer dependencies if there are any', async () => {
+    createTempFiles();
+    prompts.prompt.mockReturnValue({});
+    const dependencies = findDependencies(DIR);
+    await resolveTransitiveDeps(DIR, dependencies);
+    expect(logger.warn).toHaveBeenCalledWith(
+      'Looks like you are missing some of the peer dependencies of your libraries:\n',
+    );
+  });
+
+  it('should not display list if there are no missing peer dependencies', async () => {
+    writeFiles(DIR, {
+      'package.json': JSON.stringify(rootPackageJson),
+    });
+    const dependencies = findDependencies(DIR);
+    await resolveTransitiveDeps(DIR, dependencies);
+    expect(logger.warn).not.toHaveBeenCalled();
+  });
+
+  it('should prompt user to install missing peer dependencies', async () => {
+    createTempFiles();
+    prompts.prompt.mockReturnValue({});
+    const dependencies = findDependencies(DIR);
+    await resolveTransitiveDeps(DIR, dependencies);
+    expect(prompts.prompt).toHaveBeenCalledWith({
+      type: 'confirm',
+      name: 'installDependencies',
+      message:
+        'Do you want to install them now? The matching versions will be added as project dependencies and become visible for autolinking.',
+    });
+  });
+
+  it('should install missing peer dependencies if user confirms', async () => {
+    createTempFiles();
+    const dependencies = findDependencies(DIR);
+    prompts.prompt.mockReturnValue({installDependencies: true});
+    mockFetchJson.mockReturnValueOnce({
+      versions: {
+        '2.0.0': {},
+        '2.1.0': {},
+      },
+    });
+
+    const resolveDeps = await resolveTransitiveDeps(DIR, dependencies);
+
+    expect(resolveDeps).toEqual(['react-native-gesture-handler@^2.1.0']);
+  });
+});
diff --git a/packages/cli/src/tools/bun.ts b/packages/cli-tools/src/bun.ts
similarity index 91%
rename from packages/cli/src/tools/bun.ts
rename to packages/cli-tools/src/bun.ts
index 121be7515..081e6b6eb 100644
--- a/packages/cli/src/tools/bun.ts
+++ b/packages/cli-tools/src/bun.ts
@@ -1,7 +1,7 @@
-import {logger} from '@react-native-community/cli-tools';
 import {execSync} from 'child_process';
 import findUp from 'find-up';
 import semver from 'semver';
+import logger from './logger';
 
 export function getBunVersionIfAvailable() {
   let bunVersion;
diff --git a/packages/cli-tools/src/generateFileHash.ts b/packages/cli-tools/src/generateFileHash.ts
new file mode 100644
index 000000000..3cf26760c
--- /dev/null
+++ b/packages/cli-tools/src/generateFileHash.ts
@@ -0,0 +1,14 @@
+import fs from 'fs-extra';
+import {createHash} from 'crypto';
+import {CLIError} from './errors';
+
+export default function generateFileHash(filePath: string) {
+  try {
+    const file = fs.readFileSync(filePath, {encoding: 'utf8'});
+    const hash = createHash('md5').update(file).digest('hex');
+
+    return hash;
+  } catch {
+    throw new CLIError('Failed to generate file hash.');
+  }
+}
diff --git a/packages/cli-tools/src/index.ts b/packages/cli-tools/src/index.ts
index d0e1b92ba..b77a52b43 100644
--- a/packages/cli-tools/src/index.ts
+++ b/packages/cli-tools/src/index.ts
@@ -17,5 +17,10 @@ export {default as handlePortUnavailable} from './handlePortUnavailable';
 export * from './port';
 export {default as cacheManager} from './cacheManager';
 export {default as runSudo} from './runSudo';
+export * from './resolveTransitiveDeps';
+export * from './npm';
+export * from './bun';
+export * from './yarn';
+export * as PackageManager from './packageManager';
 
 export * from './errors';
diff --git a/packages/cli/src/tools/npm.ts b/packages/cli-tools/src/npm.ts
similarity index 100%
rename from packages/cli/src/tools/npm.ts
rename to packages/cli-tools/src/npm.ts
diff --git a/packages/cli/src/tools/packageManager.ts b/packages/cli-tools/src/packageManager.ts
similarity index 93%
rename from packages/cli/src/tools/packageManager.ts
rename to packages/cli-tools/src/packageManager.ts
index b465f1858..776f56f60 100644
--- a/packages/cli/src/tools/packageManager.ts
+++ b/packages/cli-tools/src/packageManager.ts
@@ -1,8 +1,8 @@
 import execa from 'execa';
-import {logger} from '@react-native-community/cli-tools';
 import {getYarnVersionIfAvailable, isProjectUsingYarn} from './yarn';
 import {getBunVersionIfAvailable, isProjectUsingBun} from './bun';
 import {getNpmVersionIfAvailable, isProjectUsingNpm} from './npm';
+import logger from './logger';
 
 export type PackageManager = keyof typeof packageManagers;
 
@@ -85,6 +85,17 @@ export function shouldUseNpm(options: Options) {
   return isProjectUsingNpm(options.root) && getNpmVersionIfAvailable();
 }
 
+export function getProjectPackageManager(root: string) {
+  if (isProjectUsingYarn(root)) {
+    return 'yarn';
+  }
+  if (isProjectUsingBun(root)) {
+    return 'bun';
+  }
+
+  return 'npm';
+}
+
 export function init(options: Options) {
   return configurePackageManager([], 'init', options);
 }
diff --git a/packages/cli-tools/src/resolveTransitiveDeps.ts b/packages/cli-tools/src/resolveTransitiveDeps.ts
new file mode 100644
index 000000000..d3b0ce829
--- /dev/null
+++ b/packages/cli-tools/src/resolveTransitiveDeps.ts
@@ -0,0 +1,310 @@
+import fs from 'fs-extra';
+import path from 'path';
+import * as npmRegistryFetch from 'npm-registry-fetch';
+import chalk from 'chalk';
+import {prompt} from 'prompts';
+import execa from 'execa';
+import semver from 'semver';
+import {DependencyMap} from '@react-native-community/cli-types';
+import {getLoader} from './loader';
+import logger from './logger';
+import {
+  PackageManager,
+  getProjectPackageManager,
+  install,
+} from './packageManager';
+
+export async function fetchAvailableVersions(
+  packageName: string,
+): Promise<string[]> {
+  const response = await npmRegistryFetch.json(`/${packageName}`);
+
+  return Object.keys(response.versions || {});
+}
+
+export function calculateWorkingVersion(
+  ranges: string[],
+  availableVersions: string[],
+): string | null {
+  const sortedVersions = availableVersions
+    .filter((version) =>
+      ranges.every((range) => semver.satisfies(version, range)),
+    )
+    .sort(semver.rcompare);
+
+  return sortedVersions.length > 0 ? sortedVersions[0] : null;
+}
+
+export function findDependencyPath(
+  dependencyName: string,
+  rootPath: string,
+  parentPath: string,
+) {
+  let dependencyPath;
+  const topLevelPath = path.join(rootPath, 'node_modules', dependencyName);
+  const nestedPath = path.join(parentPath, 'node_modules', dependencyName);
+
+  if (fs.existsSync(topLevelPath)) {
+    dependencyPath = topLevelPath;
+  } else if (fs.existsSync(nestedPath)) {
+    dependencyPath = nestedPath;
+  }
+
+  return dependencyPath;
+}
+
+export function filterNativeDependencies(
+  root: string,
+  dependencies: DependencyMap,
+) {
+  const depsWithNativePeers = new Map<string, Map<string, string>>();
+
+  dependencies.forEach((value, key) => {
+    if (value.peerDependencies) {
+      const nativeDependencies = new Map<string, string>();
+
+      Object.entries(value.peerDependencies).forEach(([name, versions]) => {
+        const dependencyPath = findDependencyPath(name, root, value.path);
+
+        if (dependencyPath) {
+          const iosPath = path.join(dependencyPath, 'ios');
+          const androidPath = path.join(dependencyPath, 'android');
+
+          if (fs.existsSync(iosPath) || fs.existsSync(androidPath)) {
+            nativeDependencies.set(name, versions);
+          }
+        }
+      });
+
+      if (nativeDependencies.size > 0) {
+        depsWithNativePeers.set(key, nativeDependencies);
+      }
+    }
+  });
+
+  return depsWithNativePeers;
+}
+
+export function filterInstalledPeers(
+  root: string,
+  peers: Map<string, Map<string, string>>,
+) {
+  const data: Record<string, Record<string, string>> = {};
+  const packageJsonPath = path.join(root, 'package.json');
+  const packageJson = require(packageJsonPath);
+  const dependencyList = {
+    ...packageJson.dependencies,
+    ...packageJson.devDependencies,
+  };
+  peers.forEach((peerDependencies, dependency) => {
+    peerDependencies.forEach((version, name) => {
+      if (!Object.keys(dependencyList).includes(name)) {
+        data[dependency] = {
+          ...data[dependency],
+          [name]: version,
+        };
+      }
+    });
+  });
+
+  return data;
+}
+
+export function findPeerDepsToInstall(
+  root: string,
+  dependencies: DependencyMap,
+) {
+  const rootPackageJson = require(path.join(root, 'package.json'));
+  const dependencyList = {
+    ...rootPackageJson.dependencies,
+    ...rootPackageJson.devDependencies,
+  };
+  const peerDependencies = new Set<string>();
+  Array.from(dependencies.entries()).forEach(([_, value]) => {
+    if (value.peerDependencies) {
+      Object.keys(value.peerDependencies).forEach((name) => {
+        if (!Object.keys(dependencyList).includes(name)) {
+          peerDependencies.add(name);
+        }
+      });
+    }
+  });
+
+  return peerDependencies;
+}
+
+export function getMissingPeerDeps(root: string, dependencies: DependencyMap) {
+  const depsToInstall = findPeerDepsToInstall(root, dependencies);
+  return depsToInstall;
+}
+
+// install peer deps with yarn/bun without making any changes to package.json and yarn.lock/bun.lockb
+export function silentInstallPeerDeps(
+  root: string,
+  missingPeerDependencies: DependencyMap,
+  pkgManager: PackageManager,
+) {
+  const dependenciesToInstall = getMissingPeerDeps(
+    root,
+    missingPeerDependencies,
+  );
+  const lockfile = pkgManager === 'yarn' ? 'yarn.lock' : 'bun.lockb';
+
+  const packageJsonPath = path.join(root, 'package.json');
+  const lockfilePath = path.join(root, lockfile);
+
+  if (dependenciesToInstall.size > 0) {
+    const binPackageJson = fs.readFileSync(packageJsonPath, {
+      encoding: 'utf8',
+    });
+    const binLockfile = fs.readFileSync(lockfilePath, {
+      encoding: 'utf8',
+    });
+
+    if (!binPackageJson) {
+      logger.error('package.json is missing');
+      return;
+    }
+
+    if (!binLockfile) {
+      logger.error(`${lockfile} is missing`);
+      return;
+    }
+    const loader = getLoader({text: 'Looking for peer dependencies...'});
+
+    loader.start();
+    try {
+      execa.sync(pkgManager, ['add', ...dependenciesToInstall]);
+      loader.succeed();
+    } catch {
+      loader.fail('Failed to verify peer dependencies');
+      return;
+    }
+
+    fs.writeFileSync(packageJsonPath, binPackageJson, {encoding: 'utf8'});
+    fs.writeFileSync(lockfilePath, binLockfile, {encoding: 'utf8'});
+  }
+}
+
+export async function promptForMissingPeerDependencies(
+  dependencies: Record<string, Record<string, string>>,
+): Promise<boolean> {
+  logger.warn(
+    'Looks like you are missing some of the peer dependencies of your libraries:\n',
+  );
+  logger.log(
+    Object.entries(dependencies)
+      .map(
+        ([dependencyName, peerDependencies]) =>
+          `\t${chalk.bold(dependencyName)}:\n ${Object.entries(
+            peerDependencies,
+          ).map(
+            ([peerDependency, peerDependencyVersion]) =>
+              `\t- ${peerDependency} ${peerDependencyVersion}\n`,
+          )}`,
+      )
+      .join('\n')
+      .replace(/,/g, ''),
+  );
+
+  const {installDependencies} = await prompt({
+    type: 'confirm',
+    name: 'installDependencies',
+    message:
+      'Do you want to install them now? The matching versions will be added as project dependencies and become visible for autolinking.',
+  });
+
+  return installDependencies;
+}
+
+export async function getPackagesVersion(
+  missingDependencies: Record<string, Record<string, string>>,
+) {
+  const packageToRanges: {[pkg: string]: string[]} = {};
+
+  for (const dependency in missingDependencies) {
+    const packages = missingDependencies[dependency];
+
+    for (const packageName in packages) {
+      if (!packageToRanges[packageName]) {
+        packageToRanges[packageName] = [];
+      }
+      packageToRanges[packageName].push(packages[packageName]);
+    }
+  }
+
+  const workingVersions: {[pkg: string]: string | null} = {};
+
+  for (const packageName in packageToRanges) {
+    const ranges = packageToRanges[packageName];
+    const availableVersions = await fetchAvailableVersions(packageName);
+    const workingVersion = calculateWorkingVersion(ranges, availableVersions);
+
+    if (workingVersion !== null) {
+      workingVersions[packageName] = workingVersion;
+    } else {
+      logger.warn(
+        `Could not find a version that matches all ranges for ${chalk.bold(
+          packageName,
+        )}. Please resolve this issue manually.`,
+      );
+    }
+  }
+
+  return workingVersions;
+}
+
+export async function installMissingPackages(
+  packages: Record<string, string | null>,
+  pkgManager: PackageManager,
+) {
+  const packageVersions = Object.entries(packages).map(
+    ([name, version]) => `${name}@^${version}`,
+  );
+  const flattenList = ([] as string[]).concat(...packageVersions);
+
+  const loader = getLoader({text: 'Installing peer dependencies...'});
+  loader.start();
+
+  try {
+    const deps = flattenList.map((dep) => dep);
+    install(deps, {
+      packageManager: pkgManager,
+      root: process.cwd(),
+      silent: true,
+    });
+    loader.succeed();
+
+    return deps;
+  } catch (error) {
+    loader.fail();
+
+    return [];
+  }
+}
+
+export async function resolveTransitiveDeps(
+  root: string,
+  dependencyMap: DependencyMap,
+) {
+  const packageManager = getProjectPackageManager(root);
+
+  if (packageManager !== 'npm') {
+    silentInstallPeerDeps(root, dependencyMap, packageManager);
+  }
+  const nonEmptyPeers = filterNativeDependencies(root, dependencyMap);
+  const nonInstalledPeers = filterInstalledPeers(root, nonEmptyPeers);
+  if (Object.keys(nonInstalledPeers).length > 0) {
+    const installDeps = await promptForMissingPeerDependencies(
+      nonInstalledPeers,
+    );
+
+    if (installDeps) {
+      const packagesVersions = await getPackagesVersion(nonInstalledPeers);
+
+      return installMissingPackages(packagesVersions, packageManager);
+    }
+  }
+
+  return [];
+}
diff --git a/packages/cli/src/tools/yarn.ts b/packages/cli-tools/src/yarn.ts
similarity index 95%
rename from packages/cli/src/tools/yarn.ts
rename to packages/cli-tools/src/yarn.ts
index 45a8f463a..178184d20 100644
--- a/packages/cli/src/tools/yarn.ts
+++ b/packages/cli-tools/src/yarn.ts
@@ -8,8 +8,8 @@
 
 import {execSync} from 'child_process';
 import semver from 'semver';
-import {logger} from '@react-native-community/cli-tools';
 import findUp from 'find-up';
+import logger from './logger';
 
 /**
  * Use Yarn if available, it's much faster than the npm client.
diff --git a/packages/cli-types/src/index.ts b/packages/cli-types/src/index.ts
index b20e4378a..f8cfc4a64 100644
--- a/packages/cli-types/src/index.ts
+++ b/packages/cli-types/src/index.ts
@@ -135,6 +135,7 @@ export type UserConfig = Omit<Config, 'root'> & {
     ios?: IOSProjectParams;
     [key: string]: any;
   };
+  unstable_autolinkPeerDependencies?: boolean;
 };
 
 export type UserDependencyConfig = {
@@ -148,6 +149,15 @@ export type UserDependencyConfig = {
   healthChecks: [];
 };
 
+export type DependencyMap = Map<
+  string,
+  {
+    version: string;
+    peerDependencies: Record<string, string>;
+    path: string;
+  }
+>;
+
 export {
   IOSProjectConfig,
   IOSProjectParams,
diff --git a/packages/cli/package.json b/packages/cli/package.json
index b3d934ff5..5e337a201 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -39,6 +39,7 @@
     "find-up": "^4.1.0",
     "fs-extra": "^8.1.0",
     "graceful-fs": "^4.1.3",
+    "npm-registry-fetch": "16.0.0",
     "prompts": "^2.4.2",
     "semver": "^7.5.2"
   },
@@ -46,6 +47,7 @@
     "@types/fs-extra": "^8.1.0",
     "@types/graceful-fs": "^4.1.3",
     "@types/hapi__joi": "^17.1.6",
+    "@types/npm-registry-fetch": "8.0.4",    
     "@types/prompts": "^2.4.4",
     "@types/semver": "^6.0.2",
     "deepmerge": "^4.3.0",
diff --git a/packages/cli/src/commands/init/__tests__/template.test.ts b/packages/cli/src/commands/init/__tests__/template.test.ts
index f30e51dc2..b2369bc5c 100644
--- a/packages/cli/src/commands/init/__tests__/template.test.ts
+++ b/packages/cli/src/commands/init/__tests__/template.test.ts
@@ -2,7 +2,7 @@ jest.mock('execa', () => jest.fn());
 import execa from 'execa';
 import path from 'path';
 import fs from 'fs';
-import * as PackageManger from '../../../tools/packageManager';
+import {PackageManager} from '@react-native-community/cli-tools';
 import {
   installTemplatePackage,
   getTemplateConfig,
@@ -20,11 +20,11 @@ afterEach(() => {
 });
 
 test('installTemplatePackage', async () => {
-  jest.spyOn(PackageManger, 'install').mockImplementationOnce(() => null);
+  jest.spyOn(PackageManager, 'install').mockImplementationOnce(jest.fn());
 
   await installTemplatePackage(TEMPLATE_NAME, TEMPLATE_SOURCE_DIR, 'npm');
 
-  expect(PackageManger.install).toHaveBeenCalledWith([TEMPLATE_NAME], {
+  expect(PackageManager.install).toHaveBeenCalledWith([TEMPLATE_NAME], {
     packageManager: 'npm',
     silent: true,
     root: TEMPLATE_SOURCE_DIR,
diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts
index b6351cb19..a09dd5be9 100644
--- a/packages/cli/src/commands/init/init.ts
+++ b/packages/cli/src/commands/init/init.ts
@@ -12,6 +12,10 @@ import {
   getLoader,
   Loader,
   cacheManager,
+  getBunVersionIfAvailable,
+  getNpmVersionIfAvailable,
+  getYarnVersionIfAvailable,
+  PackageManager,
 } from '@react-native-community/cli-tools';
 import {installPods} from '@react-native-community/cli-platform-ios';
 import {
@@ -21,12 +25,8 @@ import {
   executePostInitScript,
 } from './template';
 import {changePlaceholderInTemplate} from './editTemplate';
-import * as PackageManager from '../../tools/packageManager';
 import banner from './banner';
 import TemplateAndVersionError from './errors/TemplateAndVersionError';
-import {getBunVersionIfAvailable} from '../../tools/bun';
-import {getNpmVersionIfAvailable} from '../../tools/npm';
-import {getYarnVersionIfAvailable} from '../../tools/yarn';
 import {createHash} from 'crypto';
 
 const DEFAULT_VERSION = 'latest';
diff --git a/packages/cli/src/commands/init/template.ts b/packages/cli/src/commands/init/template.ts
index c5966fe82..b7333ed00 100644
--- a/packages/cli/src/commands/init/template.ts
+++ b/packages/cli/src/commands/init/template.ts
@@ -1,7 +1,10 @@
 import execa from 'execa';
 import path from 'path';
-import {logger, CLIError} from '@react-native-community/cli-tools';
-import * as PackageManager from '../../tools/packageManager';
+import {
+  logger,
+  CLIError,
+  PackageManager,
+} from '@react-native-community/cli-tools';
 import copyFiles from '../../tools/copyFiles';
 import replacePathSepForRegex from '../../tools/replacePathSepForRegex';
 import fs from 'fs';
@@ -21,7 +24,7 @@ export async function installTemplatePackage(
 ) {
   logger.debug(`Installing template from ${templateName}`);
 
-  await PackageManager.init({
+  PackageManager.init({
     packageManager,
     silent: true,
     root,
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index de74e82df..5d97a3856 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -174,7 +174,7 @@ async function setupAndRun() {
 
   let config: Config | undefined;
   try {
-    config = loadConfig();
+    config = await loadConfig();
 
     logger.enable();
 
diff --git a/yarn.lock b/yarn.lock
index c2e043e05..42cdd7ad0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1629,6 +1629,14 @@
     "@nodelib/fs.scandir" "2.1.5"
     fastq "^1.6.0"
 
+"@npmcli/agent@^2.0.0":
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.0.0.tgz#d8c4246c30c1ab55bb02970433acfeba85906ee7"
+  integrity sha512-RpRbD6PnaQIUl+p8MoH7sl2CHyMofCO0abOV+0VulqKW84+0nRWnj0bYFQELTN5HpNvzWAV8pRN6Fjx9ZLOS0g==
+  dependencies:
+    lru-cache "^10.0.1"
+    socks "^2.7.1"
+
 "@npmcli/fs@^3.1.0":
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e"
@@ -2230,6 +2238,14 @@
   resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6"
   integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=
 
+"@types/node-fetch@*":
+  version "2.6.4"
+  resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660"
+  integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==
+  dependencies:
+    "@types/node" "*"
+    form-data "^3.0.0"
+
 "@types/node-fetch@^2.3.7", "@types/node-fetch@^2.5.5":
   version "2.5.5"
   resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.5.tgz#cd264e20a81f4600a6c52864d38e7fef72485e92"
@@ -2248,6 +2264,27 @@
   resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
   integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
 
+"@types/npm-package-arg@*":
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/@types/npm-package-arg/-/npm-package-arg-6.1.1.tgz#9e2d8adc04d39824a3d9f36f738010a3f7da3c1a"
+  integrity sha512-452/1Kp9IdM/oR10AyqAgZOxUt7eLbm+EMJ194L6oarMYdZNiFIFAOJ7IIr0OrZXTySgfHjJezh2oiyk2kc3ag==
+
+"@types/npm-registry-fetch@8.0.4":
+  version "8.0.4"
+  resolved "https://registry.yarnpkg.com/@types/npm-registry-fetch/-/npm-registry-fetch-8.0.4.tgz#77b2737cde22314ccda1dfdb9568fd7769e95b90"
+  integrity sha512-R9yEj6+NDmXLpKNS19cIaMyaHfV0aHjy/1qbo8K9jiHyjyaYg0CEmuOV/L0Q91DZDi3SuxlYY+2XYwh9TbB+eQ==
+  dependencies:
+    "@types/node" "*"
+    "@types/node-fetch" "*"
+    "@types/npm-package-arg" "*"
+    "@types/npmlog" "*"
+    "@types/ssri" "*"
+
+"@types/npmlog@*":
+  version "4.1.4"
+  resolved "https://registry.yarnpkg.com/@types/npmlog/-/npmlog-4.1.4.tgz#30eb872153c7ead3e8688c476054ddca004115f6"
+  integrity sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==
+
 "@types/prettier@^1.19.0":
   version "1.19.1"
   resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f"
@@ -2315,6 +2352,13 @@
   resolved "https://registry.yarnpkg.com/@types/shell-quote/-/shell-quote-1.7.1.tgz#2d059091214a02c29f003f591032172b2aff77e8"
   integrity sha512-SWZ2Nom1pkyXCDohRSrkSKvDh8QOG9RfAsrt5/NsPQC4UQJ55eG0qClA40I+Gkez4KTQ0uDUT8ELRXThf3J5jw==
 
+"@types/ssri@*":
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/@types/ssri/-/ssri-7.1.1.tgz#2a2c94abf0d3a8c3b07bb4ff08142dd571407bb5"
+  integrity sha512-DPP/jkDaqGiyU75MyMURxLWyYLwKSjnAuGe9ZCsLp9QZOpXmDfuevk769F0BS86TmRuD5krnp06qw9nSoNO+0g==
+  dependencies:
+    "@types/node" "*"
+
 "@types/stack-utils@^1.0.1":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -3295,6 +3339,24 @@ cacache@^17.0.0:
     tar "^6.1.11"
     unique-filename "^3.0.0"
 
+cacache@^18.0.0:
+  version "18.0.0"
+  resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.0.tgz#17a9ecd6e1be2564ebe6cdca5f7cfed2bfeb6ddc"
+  integrity sha512-I7mVOPl3PUCeRub1U8YoGz2Lqv9WOBpobZ8RyWFXmReuILz+3OAyTa5oH3QPdtKZD7N0Yk00aLfzn0qvp8dZ1w==
+  dependencies:
+    "@npmcli/fs" "^3.1.0"
+    fs-minipass "^3.0.0"
+    glob "^10.2.2"
+    lru-cache "^10.0.1"
+    minipass "^7.0.3"
+    minipass-collect "^1.0.2"
+    minipass-flush "^1.0.5"
+    minipass-pipeline "^1.2.4"
+    p-map "^4.0.0"
+    ssri "^10.0.0"
+    tar "^6.1.11"
+    unique-filename "^3.0.0"
+
 cache-base@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
@@ -6018,6 +6080,13 @@ hosted-git-info@^6.0.0:
   dependencies:
     lru-cache "^7.5.1"
 
+hosted-git-info@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.0.tgz#276330b8ad9f4566e82c8ccb16050decc096076b"
+  integrity sha512-ICclEpTLhHj+zCuSb2/usoNXSVkxUSIopre+b1w8NDY9Dntp9LO4vLdHYI336TH8sAqwrRgnSfdkBG2/YpisHA==
+  dependencies:
+    lru-cache "^10.0.1"
+
 hsl-regex@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e"
@@ -7936,6 +8005,11 @@ loose-envify@^1.0.0, loose-envify@^1.4.0:
   dependencies:
     js-tokens "^3.0.0 || ^4.0.0"
 
+lru-cache@^10.0.1:
+  version "10.0.1"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a"
+  integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==
+
 lru-cache@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -8003,6 +8077,23 @@ make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1, make-fetch-happen@^11.0.3,
     socks-proxy-agent "^7.0.0"
     ssri "^10.0.0"
 
+make-fetch-happen@^13.0.0:
+  version "13.0.0"
+  resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz#705d6f6cbd7faecb8eac2432f551e49475bfedf0"
+  integrity sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==
+  dependencies:
+    "@npmcli/agent" "^2.0.0"
+    cacache "^18.0.0"
+    http-cache-semantics "^4.1.1"
+    is-lambda "^1.0.1"
+    minipass "^7.0.2"
+    minipass-fetch "^3.0.0"
+    minipass-flush "^1.0.5"
+    minipass-pipeline "^1.2.4"
+    negotiator "^0.6.3"
+    promise-retry "^2.0.1"
+    ssri "^10.0.0"
+
 makeerror@1.0.12, makeerror@1.0.x:
   version "1.0.12"
   resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
@@ -8310,6 +8401,11 @@ minipass@^5.0.0:
   resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.2.tgz#58a82b7d81c7010da5bd4b2c0c85ac4b4ec5131e"
   integrity sha512-eL79dXrE1q9dBbDCLg7xfn/vl7MS4F1gvJAgjJrQli/jbQWdUttuVawphqpffoIYfRdq78LHx6GP4bU/EQ2ATA==
 
+minipass@^7.0.2, minipass@^7.0.3:
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.3.tgz#05ea638da44e475037ed94d1c7efcc76a25e1974"
+  integrity sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==
+
 minizlib@^2.1.1, minizlib@^2.1.2:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
@@ -8657,6 +8753,16 @@ npm-package-arg@^10.0.0, npm-package-arg@^10.1.0:
     semver "^7.3.5"
     validate-npm-package-name "^5.0.0"
 
+npm-package-arg@^11.0.0:
+  version "11.0.0"
+  resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-11.0.0.tgz#0f09cba4a2c7e1bcba9c6520cd1775fa18eda82d"
+  integrity sha512-D8sItaQ8n6VlBUFed3DLz2sCpkabRAjaiLkTamDppvh8lmmAPirzNfBuhJd/2rlmoxZ2S9mOHmIEvzV2z2jOeA==
+  dependencies:
+    hosted-git-info "^7.0.0"
+    proc-log "^3.0.0"
+    semver "^7.3.5"
+    validate-npm-package-name "^5.0.0"
+
 npm-packlist@5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.1.tgz#79bcaf22a26b6c30aa4dd66b976d69cc286800e0"
@@ -8684,6 +8790,19 @@ npm-pick-manifest@^8.0.0:
     npm-package-arg "^10.0.0"
     semver "^7.3.5"
 
+npm-registry-fetch@16.0.0:
+  version "16.0.0"
+  resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-16.0.0.tgz#7529dd7c64c16a1bc8af72f99df73dfe98bb9549"
+  integrity sha512-JFCpAPUpvpwfSydv99u85yhP68rNIxSFmDpNbNnRWKSe3gpjHnWL8v320gATwRzjtgmZ9Jfe37+ZPOLZPwz6BQ==
+  dependencies:
+    make-fetch-happen "^13.0.0"
+    minipass "^7.0.2"
+    minipass-fetch "^3.0.0"
+    minipass-json-stream "^1.0.1"
+    minizlib "^2.1.2"
+    npm-package-arg "^11.0.0"
+    proc-log "^3.0.0"
+
 npm-registry-fetch@^14.0.0, npm-registry-fetch@^14.0.3, npm-registry-fetch@^14.0.5:
   version "14.0.5"
   resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz#fe7169957ba4986a4853a650278ee02e568d115d"
@@ -10925,7 +11044,7 @@ socks-proxy-agent@^7.0.0:
     debug "^4.3.3"
     socks "^2.6.2"
 
-socks@^2.6.2:
+socks@^2.6.2, socks@^2.7.1:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55"
   integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==