10 KiB
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)
Installation
Only for linux.
Download binary from release page or install with go
go install git.flo.fo/FLO/dirmd@latest
Use with Git Post Hook
combine with git post hook to sync with proton drive on each commit
add something like this in ./.git/hooks/post-commit
#!/bin/bash
set -euo pipefail
if ! command -v dirmd &>/dev/null; then
exit 0
fi
REPO_ROOT=$(git rev-parse --show-toplevel)
REPO_NAME=$(basename "$REPO_ROOT")
dirmd -o "/tmp/${REPO_NAME}" "$REPO_ROOT" -f --vertical-slices --proton-drive
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/<filename>)
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:
- ISO 8601 Timestamp: Added as a metadata line (
> Generated: ...) immediately after the H1 header for every new file created. - Git Commit Info: If the source directory is a Git repository, a second metadata line (
> Commit: <sha> (<message>)) is added below the timestamp. - 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. 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
- Install the Proton Drive CLI — see the official guide for download and installation instructions.
- Authenticate by running
proton-drive auth login. - Ensure
proton-driveis 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.
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:
- Absolute path as H1 header with
[ROOT]or[SLICE]marker - Timestamp metadata line (ISO 8601) immediately after the H1 header (only for new files)
- ASCII directory tree (indented with
+-and|characters) - Vertical slices index table (sliced mode only)
- All text files with content in fenced code blocks
- Explicit
--- FILE: ---and--- END FILE ---delimiters with byte and line counts - Language detection from file extensions
Example output structure (non-sliced mode):
# /home/user/repos/myproject [ROOT]
> Generated: 2026-09-02T14:30:00Z
> Commit: a1b2c3d (Fix login bug)
## 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.