# dirmd Generate markdown documentation from directory structure. Optimized for LLM ingestion. ## Features - Recursive directory traversal - ASCII tree visualization (LLM-friendly, minimal token overhead) - Full file contents with explicit delimiters and metadata - Filters dotfiles, binaries, and blacklisted extensions - Vertical slices mode: root file + one markdown per top-level directory - Append mode for single files or directories - Force overwrite of existing output files - Configurable depth, file size limits, ignore patterns - Optional upload to Proton Drive after generating output - Skip frontend files (`.html`, `.css`, `.js`, etc.) - Frontend only mode (include only frontend files and `README.md`) - Omit test files and inline test blocks (Go, Java, Rust) ## Build go build -o dirmd . ## Usage # Create new documentation dirmd -o output.md ~/repos/myproject # Overwrite existing output file dirmd -o output.md ~/repos/myproject -f # Append a single file dirmd -a -i README.md -o existing.md # Append another directory dirmd -a ~/repos/anotherproject -o existing.md # Generate with vertical slices dirmd -o output.md ~/repos/myproject --vertical-slices # Skip frontend files (.html, .css, .js, etc.) dirmd -o output.md ~/repos/myproject --skip-frontend # Frontend only (include only frontend files and README.md) dirmd -o output.md ~/repos/myproject --frontend-only # Omit test files and inline test blocks # Go: excludes *_test.go # Java: excludes *Test.java, *Tests.java, src/test/java/* # Rust: strips #[cfg(test)] mod tests { ... } blocks dirmd -o output.md ~/repos/myproject --omit-test # Combine filters dirmd -o output.md ~/repos/myproject --frontend-only --omit-test # Generate and upload to Proton Drive (default: /my-files/md/) dirmd -o output.md ~/repos/myproject --proton-drive # Generate and upload to a specific remote path dirmd -o output.md ~/repos/myproject --proton-drive --drive-path /my-files/docs/api.md ## Test File Omission The `--omit-test` flag removes test files and inline test blocks to reduce token overhead in LLM context windows. Behavior varies by language: | Language | Exclusion Strategy | What Gets Removed | |----------|-------------------|-------------------| | **Go** | File exclusion | All `*_test.go` files | | **Java** | File exclusion | `*Test.java`, `*Tests.java`, files under `src/test/java/` | | **Rust** | Content stripping | Entire `#[cfg(test)] mod tests { ... }` blocks removed from `.rs` files | The Rust stripping works by detecting the `#[cfg(test)]` attribute, then tracking brace depth until the module closes. Nested braces in string literals may occasionally throw off the count, but this is acceptable for RAG use cases. ## Frontend Filtering Two complementary flags control frontend file inclusion: | Flag | Effect | |------|--------| | `--skip-frontend` | Exclude frontend files, keep everything else | | `--frontend-only` | Include only frontend files and `README.md`, exclude everything else | Frontend extensions covered: | Type | Extensions | |------|------------| | Templates | `.html`, `.htm`, `.gohtml`, `.tmpl` | | Stylesheets | `.css`, `.scss`, `.sass`, `.less` | | JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` | | TypeScript | `.ts`, `.tsx` | | Frameworks | `.vue`, `.svelte` | `--skip-frontend` and `--frontend-only` are mutually exclusive. Both can be combined with `--omit-test`. ## Vertical Slices Mode When `--vertical-slices` is passed, dirmd splits output into multiple files instead of one monolithic document: - **Root file** (`-o output.md`): Full directory tree with cross-references to slice files, a vertical slices index table (file counts, total bytes per directory), and full contents of all root-level files. - **Slice files** (`cmd.md`, `internal.md`, etc.): One per top-level directory, placed alongside the root file. Each contains its own tree, a back-reference to the root document, and full recursive file contents for that directory. This mode cannot be combined with `--append` or `--input-file`. Example output with `dirmd -o docs.md ~/repos/myproject --vertical-slices`: docs/ ├── docs.md ← root: tree + slices index + root file contents ├── cmd.md ← slice: tree + contents of cmd/ └── internal.md ← slice: tree + contents of internal/ ## LLM-Optimized Output Output is designed for RAG ingestion and LLM context windows, not human presentation: - **ASCII tree format** (`+-` instead of Unicode box-drawing) to reduce token overhead - **Explicit file delimiters**: `--- FILE: ./path (bytes, lines) ---` and `--- END FILE ---` - **Document type markers**: `[ROOT]` and `[SLICE]` in H1 headers - **Cross-references**: Directory entries in root tree show `-> see cmd.md`; slice files reference their root document - **Slices index table**: File counts and total bytes per slice for informed retrieval decisions - **Tilde fences** (`~~~`) to avoid conflicts with backticks in source files ## Flags | Flag | Description | Default | |------|-------------|---------| | `-o`, `--output` | Output markdown file path (required) | | | `-a`, `--append` | Append to existing output file | false | | `-f`, `--force` | Overwrite existing output file (non-append mode) | false | | `-i`, `--input-file` | Single file input (append mode only) | | | `--vertical-slices` | Split output into root file + one markdown per top-level directory | false | | `--max-size` | Max file size in bytes | 524288 | | `--max-depth` | Max directory recursion depth | 20 | | `--ignore` | Additional ignore patterns (glob) | | | `--extensions` | Additional file extensions to skip | | | `--proton-drive` | Upload output to Proton Drive after writing locally | false | | `--drive-path` | Full remote path on Proton Drive (e.g. /my-files/md/report.md) | /my-files/md/ | | `--skip-frontend` | Omit frontend file types (.html, .css, .js, .ts, .vue, .svelte, etc.) | false | | `--frontend-only` | Include only frontend file types and README.md | false | | `--omit-test` | Exclude test files (Go *_test.go, Java *Test.java) and strip #[cfg(test)] blocks from Rust | false | ## Proton Drive Integration dirmd can optionally upload the generated markdown file(s) to Proton Drive using the [Proton Drive CLI](https://proton.me/support/drive-cli). The upload is performed only when `--proton-drive` is passed. Without it, dirmd behaves exactly as before — no Proton Drive dependency is required. In vertical slices mode, all generated files (root + slices) are uploaded to `/my-files/md/`. The `--drive-path` flag is ignored in slices mode ; each file is uploaded by its basename. ### Prerequisites 1. Install the Proton Drive CLI — see the [official guide](https://proton.me/support/drive-cli) for download and installation instructions. 2. Authenticate by running `proton-drive auth login`. 3. Ensure `proton-drive` is in your PATH. If the CLI is not installed or you are not logged in, dirmd will report the error to stderr and exit with a non-zero code. Local files are always written successfully before the upload is attempted. For full documentation on the Proton Drive CLI, including installation, authentication, and troubleshooting, refer to the [official Proton Drive CLI support page](https://proton.me/support/drive-cli). ## Examples # Custom depth and size limit dirmd -o output.md ~/repos/project --max-depth 5 --max-size 262144 # Ignore specific directories dirmd -o output.md ~/repos/project --ignore __pycache__ --ignore .venv # Skip additional file extensions dirmd -o output.md ~/repos/project --extensions .log --extensions .tmp # Vertical slices with overwrite dirmd -o docs.md ~/repos/project -f --vertical-slices # Skip frontend and omit tests dirmd -o docs.md ~/repos/project -f --skip-frontend --omit-test # Frontend only with test omission dirmd -o docs.md ~/repos/project -f --frontend-only --omit-test # Generate, then upload to default remote location dirmd -o docs.md ~/repos/project --proton-drive # Generate, then upload to a custom remote location dirmd -o docs.md ~/repos/project --proton-drive --drive-path /my-files/projects/docs.md # Overwrite existing local file and upload to Drive dirmd -o docs.md ~/repos/project -f --proton-drive ## Output Format Produces markdown with: 1. Absolute path as H1 header with `[ROOT]` or `[SLICE]` marker 2. ASCII directory tree (indented with `+-` and `|` characters) 3. Vertical slices index table (sliced mode only) 4. All text files with content in fenced code blocks 5. Explicit `--- FILE: ---` and `--- END FILE ---` delimiters with byte and line counts 6. Language detection from file extensions Example output structure (non-sliced mode): # /home/user/repos/myproject [ROOT] ## Directory Tree ~~~ myproject/ +- cmd/ | +- main.go +- internal/ | +- config.go ~~~ ## Contents --- FILE: ./cmd/main.go (45 bytes, 3 lines) --- ~~~go package main func main() {} ~~~ --- END FILE --- Note: Uses tilde fences (~~~) internally to avoid conflicts with nested backticks in source files.