* Generic function to load markdown files from specified directories * @param dir Directory (eg. "~/.claude/commands") * @returns Array of parsed markdown files with metadata
(dir: string)
| 611 | * @returns Array of parsed markdown files with metadata |
| 612 | */ |
| 613 | async function loadMarkdownFiles(dir: string): Promise< |
| 614 | { |
| 615 | filePath: string |
| 616 | frontmatter: FrontmatterData |
| 617 | content: string |
| 618 | }[] |
| 619 | > { |
| 620 | // File search strategy: |
| 621 | // - Default: ripgrep (faster, battle-tested) |
| 622 | // - Fallback: native Node.js (when CLAUDE_CODE_USE_NATIVE_FILE_SEARCH is set) |
| 623 | // |
| 624 | // Why both? Ripgrep has poor startup performance in native builds. |
| 625 | const useNative = isEnvTruthy(process.env.CLAUDE_CODE_USE_NATIVE_FILE_SEARCH) |
| 626 | const signal = AbortSignal.timeout(3000) |
| 627 | let files: string[] |
| 628 | try { |
| 629 | files = useNative |
| 630 | ? await findMarkdownFilesNative(dir, signal) |
| 631 | : await ripGrep( |
| 632 | ['--files', '--hidden', '--follow', '--no-ignore', '--glob', '*.md'], |
| 633 | dir, |
| 634 | signal, |
| 635 | ) |
| 636 | } catch (e: unknown) { |
| 637 | // Handle missing/inaccessible dir directly instead of pre-checking |
| 638 | // existence (TOCTOU). findMarkdownFilesNative already catches internally; |
| 639 | // ripGrep rejects on inaccessible target paths. |
| 640 | if (isFsInaccessible(e)) return [] |
| 641 | throw e |
| 642 | } |
| 643 | |
| 644 | const results = await Promise.all( |
| 645 | files.map(async filePath => { |
| 646 | try { |
| 647 | const rawContent = await readFile(filePath, { encoding: 'utf-8' }) |
| 648 | const { frontmatter, content } = parseFrontmatter(rawContent, filePath) |
| 649 | |
| 650 | return { |
| 651 | filePath, |
| 652 | frontmatter, |
| 653 | content, |
| 654 | } |
| 655 | } catch (error) { |
| 656 | const errorMessage = |
| 657 | error instanceof Error ? error.message : String(error) |
| 658 | logForDebugging( |
| 659 | `Failed to read/parse markdown file: ${filePath}: ${errorMessage}`, |
| 660 | ) |
| 661 | return null |
| 662 | } |
| 663 | }), |
| 664 | ) |
| 665 | |
| 666 | return results.filter(_ => _ !== null) |
| 667 | } |
no test coverage detected