Created
February 20, 2026 18:15
-
-
Save stackdumper/19f916260f9f8f59928f079e427f45c3 to your computer and use it in GitHub Desktop.
A script that produces a more compact project file tree for CLAUDE.m.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { readdirSync, statSync } from 'fs' | |
| import { join, basename } from 'path' | |
| // Patterns to ignore (can be extended via args if needed) | |
| const IGNORE_PATTERNS = ['.git', '.claude', 'node_modules', 'dist', '.DS_Store', 'pnpm-lock.yaml'] | |
| // File extensions to ignore | |
| const IGNORE_EXTENSIONS = ['.png', '.csv'] | |
| type TreeNode = { | |
| name: string | |
| children: TreeNode[] | null // null = file, array = directory | |
| } | |
| function shouldIgnore(name: string, isFile: boolean): boolean { | |
| if (IGNORE_PATTERNS.includes(name)) return true | |
| if (isFile && IGNORE_EXTENSIONS.some((ext) => name.endsWith(ext))) return true | |
| return false | |
| } | |
| function buildTree(dirPath: string): TreeNode { | |
| const name = basename(dirPath) || '.' | |
| const entries = readdirSync(dirPath).sort() | |
| const children: TreeNode[] = [] | |
| for (const entry of entries) { | |
| const fullPath = join(dirPath, entry) | |
| const stat = statSync(fullPath) | |
| const isFile = stat.isFile() | |
| if (shouldIgnore(entry, isFile)) continue | |
| if (stat.isDirectory()) { | |
| children.push(buildTree(fullPath)) | |
| } else { | |
| children.push({ name: entry, children: null }) | |
| } | |
| } | |
| return { name, children } | |
| } | |
| function formatCompact(node: TreeNode, isRoot: boolean = false): string { | |
| if (node.children === null) { | |
| return node.name | |
| } | |
| if (node.children.length === 0) { | |
| return `${node.name} {}` | |
| } | |
| const files = node.children.filter((c) => c.children === null) | |
| const dirs = node.children.filter((c) => c.children !== null) | |
| const parts: string[] = [] | |
| // Files as space-separated list | |
| if (files.length > 0) { | |
| parts.push(files.map((f) => f.name).join(' ')) | |
| } | |
| // Directories recursively | |
| for (const dir of dirs) { | |
| parts.push(formatCompact(dir, false)) | |
| } | |
| // Root level: newlines between top-level items | |
| if (isRoot) { | |
| return `${node.name} {\n${parts.join('\n')}\n}` | |
| } | |
| return `${node.name} { ${parts.join(' ')} }` | |
| } | |
| // Main | |
| const root = process.argv[2] || '.' | |
| const tree = buildTree(root) | |
| console.log(formatCompact(tree, true)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment