MCPcopy Create free account
hub / github.com/claude-code-best/claude-code / checkInstall

Function checkInstall

src/utils/nativeInstaller/installer.ts:797–937  ·  view source on GitHub ↗
(
  force: boolean = false,
)

Source from the content-addressed store, hash-verified

795}
796
797export async function checkInstall(
798 force: boolean = false,
799): Promise<SetupMessage[]> {
800 // Skip all installation checks if disabled via environment variable
801 if (isEnvTruthy(process.env.DISABLE_INSTALLATION_CHECKS)) {
802 return []
803 }
804
805 // Get the actual installation type and config
806 const installationType = await getCurrentInstallationType()
807
808 // Skip checks for development builds - config.installMethod from a previous
809 // native installation shouldn't trigger warnings when running dev builds
810 if (installationType === 'development') {
811 return []
812 }
813
814 const config = getGlobalConfig()
815
816 // Only show warnings if:
817 // 1. User is actually running from native installation, OR
818 // 2. User has explicitly set installMethod to 'native' in config (they're trying to use native)
819 // 3. force is true (used during installation process)
820 const shouldCheckNative =
821 force || installationType === 'native' || config.installMethod === 'native'
822
823 if (!shouldCheckNative) {
824 return []
825 }
826
827 const dirs = getBaseDirectories()
828 const messages: SetupMessage[] = []
829 const localBinDir = dirname(dirs.executable)
830 const resolvedLocalBinPath = resolve(localBinDir)
831 const platform = getPlatform()
832 const isWindows = platform.startsWith('win32')
833
834 // Check if bin directory exists
835 try {
836 await access(localBinDir)
837 } catch {
838 messages.push({
839 message: `installMethod is native, but directory ${localBinDir} does not exist`,
840 userActionRequired: true,
841 type: 'error',
842 })
843 }
844
845 // Check if claude executable exists and is valid.
846 // On non-Windows, call readlink directly and route errno — ENOENT means
847 // the executable is missing, EINVAL means it exists but isn't a symlink.
848 // This avoids an access()→readlink() TOCTOU where deletion between the
849 // two calls produces a misleading "Not a symlink" diagnostic.
850 // isPossibleClaudeBinary stats the path internally, so we don't pre-check
851 // with access() — that would be a TOCTOU between access and the stat.
852 if (isWindows) {
853 // On Windows it's a copied executable, not a symlink
854 if (!(await isPossibleClaudeBinary(dirs.executable))) {

Callers 3

runFunction · 0.85
useInstallMessagesFunction · 0.85

Calls 11

getGlobalConfigFunction · 0.85
getBaseDirectoriesFunction · 0.85
getPlatformFunction · 0.85
isPossibleClaudeBinaryFunction · 0.85
isENOENTFunction · 0.85
getShellTypeFunction · 0.85
getShellConfigPathsFunction · 0.85
isEnvTruthyFunction · 0.50
resolveFunction · 0.50
pushMethod · 0.45

Tested by

no test coverage detected