luff
A production-grade CLI tool for printing file contents with multiple output formats, written in Rust.
Features
- Multiple Output Formats: Markdown code blocks, tree view
- Smart File Discovery: Directory walking with gitignore support
- Clipboard Integration: Copy output directly to system clipboard
- Security Hardened: Protection against path traversal, symlink attacks, resource exhaustion
- High Performance: Upfront collection with minimal allocations, efficient I/O
- Well Tested: Unit tests, property-based tests, integration tests, E2E tests
- Modular Architecture: Clean separation of concerns, easy to extend
Installation
From Source
Development Build
Usage
Process Specific Files
Print specific files with Markdown formatting:
Walk Current Directory
Print all files in the current directory:
Walk from Git Root
Start from the git repository root:
Respect .gitignore (default)
Honor gitignore patterns when walking (on by default):
Include Ignored Files
Include files that .gitignore would normally skip:
Include Hidden Files
Include dot-directories and files:
Tree Output Format
Display as a tree structure:
Limit Directory Depth
Only traverse up to N levels deep:
Copy to Clipboard
Copy output to system clipboard (also prints to stdout):
Clipboard Only (No Stdout)
Copy to clipboard without printing to terminal:
Enable Debug Logging
Show detailed information about file processing:
Combined Options
# Walk git repo, include ignored files, include dotfiles, debug output
# Process specific files with tree format
# Walk with depth limit and copy to clipboard
# Clipboard-only mode with tree format
Options
| Flag | Long | Description |
|---|---|---|
-f |
--files <FILES>... |
Process specific files (disables directory walk) |
-g |
--git |
Start from git repository root |
-d |
--dotfiles |
Include hidden files/directories |
-I |
--ignored |
Include files ignored by .gitignore |
-c |
--clip |
Copy output to clipboard (also prints to stdout unless -S used) |
-S |
--suppress-stdout |
Suppress stdout output (useful with -c for clipboard-only) |
-v |
--verbose |
Enable debug logging |
--format <FORMAT> |
Output format: markdown, tree (default: markdown) | |
--max-depth <N> |
Maximum directory depth (0 = unlimited, default: 0) | |
-h |
--help |
Print help information |
-V |
--version |
Print version information |
Output Modes
| Flags | Behavior |
|---|---|
| (none) | Stream to stdout (default, low memory) |
-c |
Buffer entire output, write to stdout AND clipboard |
-c -S |
Buffer entire output, copy to clipboard only (no stdout) |
-S |
No output (edge case, allowed but not useful) |
Note: Clipboard mode requires buffering the entire output in memory before writing. For large codebases, this may use significant memory.
Architecture
Key Design Decisions
- Upfront Collection: Directory walker collects file paths at construction to prevent output file inclusion
- Shell Redirection Protection: Skips empty files created within 2 seconds to avoid including
luff > output.txtoutput - Zero-cost Abstractions: Walker enum provides unified interface without runtime overhead
- Security First: All file operations validated against path traversal, size limits, symlink attacks
- Explicit Error Handling: No panics in library code, Result types throughout
Development
Prerequisites
- Rust 1.85 or later
- Git (for git-related functionality)
- Clipboard support (X11/Wayland on Linux, native on macOS/Windows)
Building
# Debug build
# Release build (optimized)
# Run with arguments
Testing
# Run all tests
# Run with output
# Run specific test
# Run integration tests only
# Run E2E tests
# Run with property-based tests
Benchmarking
# Run all benchmarks
# Run specific benchmark
# Generate HTML reports
Code Quality
# Check for issues
# Format code
# Check for unsafe code
Security
This project follows security best practices:
- Path Validation: All paths validated against traversal attacks
- Size Limits: Files limited to 100MB to prevent memory exhaustion
- TOCTOU Protection: File metadata re-checked after open
- Symlink Safety: Canonicalization with validation
- Input Sanitization: All user input validated
- No Unsafe Code: Pure safe Rust (verify with cargo geiger)
- Root Containment: File list mode prevents access outside project root
- Timeout Protection: File operations have 5-second timeout to prevent FIFO blocking
Platform Support
- Linux: Full support (X11 or Wayland required for clipboard)
- macOS: Full support (native clipboard)
- Windows: Full support (native clipboard)
- Headless: Works without clipboard (graceful degradation)