Skip to content

Project CLAUDE.md files not discovered when ccexp is run from subdirectories #69

@nyatinte

Description

@nyatinte

Problem Description

When running ccexp from a subdirectory within a project, the project's CLAUDE.md and CLAUDE.local.md files are not discovered and displayed in the UI.

Steps to Reproduce

  1. Navigate to a project directory that contains CLAUDE.md and/or CLAUDE.local.md files
  2. Create a subdirectory: mkdir test-dir && cd test-dir
  3. Run ccexp: ../dist/index.js or ccexp (if installed globally)
  4. Observe that the project's CLAUDE.md files are not shown in the file list

Expected Behavior

Project-level CLAUDE.md and CLAUDE.local.md files should be discovered and displayed regardless of which subdirectory ccexp is executed from within the project.

Actual Behavior

Only user-level files from ~/.claude/ are displayed. The project's memory files are missing.

Root Cause Analysis

Current Implementation (AS-IS)

  1. Working Directory Dependency (src/index.tsx:24)

    .option('-p, --path <path>', 'specify directory to scan', process.cwd())
  2. Limited Scan Scope (src/claude-md-scanner.ts)

    • Scans from process.cwd() downward
    • Scans ~/.claude/
    • Scans first-level subdirectories in home
    • Does NOT scan parent directories
  3. Environment-Specific Hardcoding

    const projectDirectories = new Set([
      'my_programs',  // Specific to certain environments
      'projects',
      'dev',
      // ...
    ]);

Proposed Solution (TO-BE)

Scan from HOME directory with intelligent filtering

export const scanClaudeFiles = async (options: ScanOptions = {}): Promise<ClaudeFileInfo[]> => {
  const { homedir } = await import('node:os');
  const homeDir = homedir();
  const files: string[] = [];

  // 1. Scan ~/.claude directory
  const globalClaudeDir = join(homeDir, '.claude');
  if (existsSync(globalClaudeDir)) {
    const globalFiles = await findClaudeFiles({
      path: globalClaudeDir,
      recursive: true,
    });
    files.push(...globalFiles);
  }

  // 2. Scan all directories under HOME with smart filtering
  const homeContents = await readdir(homeDir, { withFileTypes: true });
  
  for (const entry of homeContents) {
    if (!entry.isDirectory() || shouldExcludeDirectory(entry.name)) continue;
    
    const dirPath = join(homeDir, entry.name);
    
    // Prioritize likely project directories
    if (await isLikelyProjectDirectory(dirPath, entry.name)) {
      const projectFiles = await findClaudeFiles({
        path: dirPath,
        recursive: true,
      });
      files.push(...projectFiles);
    }
  }

  // Remove duplicates and process
  const uniqueFiles = uniq(files);
  // ... process files
};

Improved Directory Detection

// Remove environment-specific hardcoding
async function isLikelyProjectDirectory(dirPath: string, dirName: string): boolean {
  // 1. Pattern-based detection
  const namePatterns = [
    /^(dev|develop|development)$/i,
    /^(proj|project|projects)$/i,
    /^(work|workspace|code|src|source)$/i,
    /^(repo|repos|repositories)$/i,
    /^(git|github|gitlab)$/i,
  ];
  
  if (namePatterns.some(pattern => pattern.test(dirName))) {
    return true;
  }
  
  // 2. Marker file detection
  const markers = [
    '.git', 'package.json', 'Cargo.toml', 'go.mod', 
    'requirements.txt', '.claude', 'CLAUDE.md'
  ];
  
  for (const marker of markers) {
    if (existsSync(join(dirPath, marker))) {
      return true;
    }
  }
  
  return false;
}

// Comprehensive exclusion patterns
function shouldExcludeDirectory(name: string): boolean {
  const excludePatterns = [
    // System/Cache
    /^\.cache$/, /^\.npm$/, /^\.yarn$/, /^node_modules$/,
    
    // OS-specific
    /^Library$/, /^Applications$/, /^\.Trash$/, // macOS
    /^AppData$/, /^LocalAppData$/, // Windows
    
    // Large media directories
    /^Downloads$/, /^Pictures$/, /^Movies$/, /^Music$/,
    
    // Hidden config
    /^\.local$/, /^\.config$/, /^\.vscode$/, /^\.idea$/,
  ];
  
  return excludePatterns.some(pattern => pattern.test(name));
}

Benefits

  1. Reliability: Scanning from HOME ensures all CLAUDE.md files are found regardless of execution location
  2. Performance: Smart filtering and pattern matching reduce unnecessary scans
  3. Security: Clear exclusion patterns avoid system directories
  4. Portability: No environment-specific hardcoding

Implementation Notes

  • Maintain backward compatibility with existing API
  • Add depth limits to prevent excessive scanning
  • Consider adding a progress indicator for large file systems
  • Cache results for improved performance on repeated runs

This change will significantly improve the user experience by ensuring ccexp behaves consistently regardless of where it's executed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions