33
44using System . Text . Json ;
55using System . Text . Json . Nodes ;
6- using Aspire . Cli . Git ;
76using Aspire . Cli . Resources ;
87using Microsoft . Extensions . Logging ;
98
@@ -18,22 +17,18 @@ internal sealed class ClaudeCodeAgentEnvironmentScanner : IAgentEnvironmentScann
1817 private const string McpConfigFileName = ".mcp.json" ;
1918 private const string AspireServerName = "aspire" ;
2019
21- private readonly IGitRepository _gitRepository ;
2220 private readonly IClaudeCodeCliRunner _claudeCodeCliRunner ;
2321 private readonly ILogger < ClaudeCodeAgentEnvironmentScanner > _logger ;
2422
2523 /// <summary>
2624 /// Initializes a new instance of <see cref="ClaudeCodeAgentEnvironmentScanner"/>.
2725 /// </summary>
28- /// <param name="gitRepository">The Git repository service for finding repository boundaries.</param>
2926 /// <param name="claudeCodeCliRunner">The Claude Code CLI runner for checking if Claude Code is installed.</param>
3027 /// <param name="logger">The logger for diagnostic output.</param>
31- public ClaudeCodeAgentEnvironmentScanner ( IGitRepository gitRepository , IClaudeCodeCliRunner claudeCodeCliRunner , ILogger < ClaudeCodeAgentEnvironmentScanner > logger )
28+ public ClaudeCodeAgentEnvironmentScanner ( IClaudeCodeCliRunner claudeCodeCliRunner , ILogger < ClaudeCodeAgentEnvironmentScanner > logger )
3229 {
33- ArgumentNullException . ThrowIfNull ( gitRepository ) ;
3430 ArgumentNullException . ThrowIfNull ( claudeCodeCliRunner ) ;
3531 ArgumentNullException . ThrowIfNull ( logger ) ;
36- _gitRepository = gitRepository ;
3732 _claudeCodeCliRunner = claudeCodeCliRunner ;
3833 _logger = logger ;
3934 }
@@ -42,64 +37,52 @@ public ClaudeCodeAgentEnvironmentScanner(IGitRepository gitRepository, IClaudeCo
4237 public async Task ScanAsync ( AgentEnvironmentScanContext context , CancellationToken cancellationToken )
4338 {
4439 _logger . LogDebug ( "Starting Claude Code environment scan in directory: {WorkingDirectory}" , context . WorkingDirectory . FullName ) ;
45-
46- // Get the git root to use as a boundary for searching
47- _logger . LogDebug ( "Finding git repository root..." ) ;
48- var gitRoot = await _gitRepository . GetRootAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
49- _logger . LogDebug ( "Git root: {GitRoot}" , gitRoot ? . FullName ?? "(none)" ) ;
40+ _logger . LogDebug ( "Workspace root: {RepositoryRoot}" , context . RepositoryRoot . FullName ) ;
5041
5142 // Find the .claude folder to determine if Claude Code is being used in this project
5243 _logger . LogDebug ( "Searching for .claude folder..." ) ;
53- var claudeCodeFolder = FindClaudeCodeFolder ( context . WorkingDirectory , gitRoot ) ;
44+ var claudeCodeFolder = FindClaudeCodeFolder ( context . WorkingDirectory , context . RepositoryRoot ) ;
5445
55- // Determine the repo root - use git root, or infer from .claude folder location, or fall back to working directory
56- DirectoryInfo ? repoRoot = gitRoot ;
57- if ( repoRoot is null && claudeCodeFolder is not null )
46+ if ( claudeCodeFolder is not null )
5847 {
59- // .claude folder's parent is the repo root
60- repoRoot = claudeCodeFolder . Parent ;
61- _logger . LogDebug ( "Inferred repo root from .claude folder parent: {RepoRoot}" , repoRoot ? . FullName ?? "(none)" ) ;
62- }
63-
64- if ( claudeCodeFolder is not null || repoRoot is not null )
65- {
66- var targetRepoRoot = repoRoot ?? context . WorkingDirectory ;
67- _logger . LogDebug ( "Found .claude folder or repo root at: {RepoRoot}" , targetRepoRoot . FullName ) ;
48+ // If .claude folder is found, override the workspace root with its parent directory
49+ var workspaceRoot = claudeCodeFolder . Parent ?? context . RepositoryRoot ;
50+ _logger . LogDebug ( "Inferred workspace root from .claude folder parent: {WorkspaceRoot}" , workspaceRoot . FullName ) ;
6851
6952 // Check if the aspire server is already configured in .mcp.json
7053 _logger . LogDebug ( "Checking if Aspire MCP server is already configured in .mcp.json..." ) ;
71- if ( HasAspireServerConfigured ( targetRepoRoot ) )
54+ if ( HasAspireServerConfigured ( workspaceRoot ) )
7255 {
7356 _logger . LogDebug ( "Aspire MCP server is already configured - skipping" ) ;
7457 // Already configured, no need to offer an applicator
7558 return ;
7659 }
7760
78- // Found a .claude folder or git repo - add an applicator to configure MCP
79- _logger . LogDebug ( "Adding Claude Code applicator for .mcp.json at: {RepoRoot }" , targetRepoRoot . FullName ) ;
80- context . AddApplicator ( CreateApplicator ( targetRepoRoot ) ) ;
61+ // Found a .claude folder - add an applicator to configure MCP
62+ _logger . LogDebug ( "Adding Claude Code applicator for .mcp.json at: {WorkspaceRoot }" , workspaceRoot . FullName ) ;
63+ context . AddApplicator ( CreateApplicator ( workspaceRoot ) ) ;
8164 }
8265 else
8366 {
84- // No .claude folder or git repo found - check if Claude Code CLI is installed
85- _logger . LogDebug ( "No .claude folder or git repo found, checking for Claude Code CLI installation..." ) ;
67+ // No .claude folder found - check if Claude Code CLI is installed
68+ _logger . LogDebug ( "No .claude folder found, checking for Claude Code CLI installation..." ) ;
8669 var claudeCodeVersion = await _claudeCodeCliRunner . GetVersionAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
8770
8871 if ( claudeCodeVersion is not null )
8972 {
9073 _logger . LogDebug ( "Found Claude Code CLI version: {Version}" , claudeCodeVersion ) ;
9174
9275 // Check if the aspire server is already configured in .mcp.json
93- if ( HasAspireServerConfigured ( context . WorkingDirectory ) )
76+ if ( HasAspireServerConfigured ( context . RepositoryRoot ) )
9477 {
9578 _logger . LogDebug ( "Aspire MCP server is already configured - skipping" ) ;
9679 // Already configured, no need to offer an applicator
9780 return ;
9881 }
9982
100- // Claude Code is installed - offer to create config at working directory
101- _logger . LogDebug ( "Adding Claude Code applicator for .mcp.json at working directory : {WorkingDirectory }" , context . WorkingDirectory . FullName ) ;
102- context . AddApplicator ( CreateApplicator ( context . WorkingDirectory ) ) ;
83+ // Claude Code is installed - offer to create config at workspace root
84+ _logger . LogDebug ( "Adding Claude Code applicator for .mcp.json at workspace root : {WorkspaceRoot }" , context . RepositoryRoot . FullName ) ;
85+ context . AddApplicator ( CreateApplicator ( context . RepositoryRoot ) ) ;
10386 }
10487 else
10588 {
@@ -110,12 +93,12 @@ public async Task ScanAsync(AgentEnvironmentScanContext context, CancellationTok
11093
11194 /// <summary>
11295 /// Walks up the directory tree to find a .claude folder.
113- /// Stops if we go above the git root (if provided) .
96+ /// Stops if we go above the workspace root.
11497 /// Ignores the .claude folder in the user's home directory.
11598 /// </summary>
11699 /// <param name="startDirectory">The directory to start searching from.</param>
117- /// <param name="gitRoot ">The git repository root, or null if not in a git repository .</param>
118- private static DirectoryInfo ? FindClaudeCodeFolder ( DirectoryInfo startDirectory , DirectoryInfo ? gitRoot )
100+ /// <param name="repositoryRoot ">The workspace root to use as the boundary for searches .</param>
101+ private static DirectoryInfo ? FindClaudeCodeFolder ( DirectoryInfo startDirectory , DirectoryInfo repositoryRoot )
119102 {
120103 var currentDirectory = startDirectory ;
121104 var homeDirectory = Environment . GetFolderPath ( Environment . SpecialFolder . UserProfile ) ;
@@ -130,9 +113,9 @@ public async Task ScanAsync(AgentEnvironmentScanContext context, CancellationTok
130113 return new DirectoryInfo ( claudeCodePath ) ;
131114 }
132115
133- // Stop if we've reached the git root without finding .claude
134- // (don't search above the repository boundary)
135- if ( gitRoot is not null && string . Equals ( currentDirectory . FullName , gitRoot . FullName , StringComparison . OrdinalIgnoreCase ) )
116+ // Stop if we've reached the workspace root without finding .claude
117+ // (don't search above the workspace boundary)
118+ if ( string . Equals ( currentDirectory . FullName , repositoryRoot . FullName , StringComparison . OrdinalIgnoreCase ) )
136119 {
137120 return null ;
138121 }
0 commit comments