@@ -35,6 +35,9 @@ internal static string ResolveClaude()
3535 Path . Combine ( home , ".local" , "bin" , "claude" ) ,
3636 } ;
3737 foreach ( string c in candidates ) { if ( File . Exists ( c ) ) return c ; }
38+ // Try NVM-installed claude under ~/.nvm/versions/node/*/bin/claude
39+ string nvmClaude = ResolveClaudeFromNvm ( home ) ;
40+ if ( ! string . IsNullOrEmpty ( nvmClaude ) ) return nvmClaude ;
3841#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
3942 return Which ( "claude" , "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin" ) ;
4043#else
@@ -70,6 +73,9 @@ internal static string ResolveClaude()
7073 Path . Combine ( home , ".local" , "bin" , "claude" ) ,
7174 } ;
7275 foreach ( string c in candidates ) { if ( File . Exists ( c ) ) return c ; }
76+ // Try NVM-installed claude under ~/.nvm/versions/node/*/bin/claude
77+ string nvmClaude = ResolveClaudeFromNvm ( home ) ;
78+ if ( ! string . IsNullOrEmpty ( nvmClaude ) ) return nvmClaude ;
7379#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
7480 return Which ( "claude" , "/usr/local/bin:/usr/bin:/bin" ) ;
7581#else
@@ -78,6 +84,75 @@ internal static string ResolveClaude()
7884 }
7985 }
8086
87+ // Attempt to resolve claude from NVM-managed Node installations, choosing the newest version
88+ private static string ResolveClaudeFromNvm ( string home )
89+ {
90+ try
91+ {
92+ if ( string . IsNullOrEmpty ( home ) ) return null ;
93+ string nvmNodeDir = Path . Combine ( home , ".nvm" , "versions" , "node" ) ;
94+ if ( ! Directory . Exists ( nvmNodeDir ) ) return null ;
95+
96+ string bestPath = null ;
97+ Version bestVersion = null ;
98+ foreach ( string versionDir in Directory . EnumerateDirectories ( nvmNodeDir ) )
99+ {
100+ string name = Path . GetFileName ( versionDir ) ;
101+ if ( string . IsNullOrEmpty ( name ) ) continue ;
102+ if ( name . StartsWith ( "v" , StringComparison . OrdinalIgnoreCase ) )
103+ {
104+ // Extract numeric portion: e.g., v18.19.0-nightly -> 18.19.0
105+ string versionStr = name . Substring ( 1 ) ;
106+ int dashIndex = versionStr . IndexOf ( '-' ) ;
107+ if ( dashIndex > 0 )
108+ {
109+ versionStr = versionStr . Substring ( 0 , dashIndex ) ;
110+ }
111+ if ( Version . TryParse ( versionStr , out Version parsed ) )
112+ {
113+ string candidate = Path . Combine ( versionDir , "bin" , "claude" ) ;
114+ if ( File . Exists ( candidate ) )
115+ {
116+ if ( bestVersion == null || parsed > bestVersion )
117+ {
118+ bestVersion = parsed ;
119+ bestPath = candidate ;
120+ }
121+ }
122+ }
123+ }
124+ }
125+ return bestPath ;
126+ }
127+ catch { return null ; }
128+ }
129+
130+ // Explicitly set the Claude CLI absolute path override in EditorPrefs
131+ internal static void SetClaudeCliPath ( string absolutePath )
132+ {
133+ try
134+ {
135+ if ( ! string . IsNullOrEmpty ( absolutePath ) && File . Exists ( absolutePath ) )
136+ {
137+ EditorPrefs . SetString ( PrefClaude , absolutePath ) ;
138+ }
139+ }
140+ catch { }
141+ }
142+
143+ // Clear any previously set Claude CLI override path
144+ internal static void ClearClaudeCliPath ( )
145+ {
146+ try
147+ {
148+ if ( EditorPrefs . HasKey ( PrefClaude ) )
149+ {
150+ EditorPrefs . DeleteKey ( PrefClaude ) ;
151+ }
152+ }
153+ catch { }
154+ }
155+
81156 // Use existing UV resolver; returns absolute path or null.
82157 internal static string ResolveUv ( )
83158 {
0 commit comments