6 releases
Uses new Rust 2024
| 0.2.5 | Feb 13, 2026 |
|---|---|
| 0.2.3 | Feb 13, 2026 |
| 0.1.1 | Feb 13, 2026 |
#704 in Filesystem
41KB
658 lines
Snapcat
Snapcat is a fast, flexible Rust library for walking directories, generating a visual tree, and collecting file contents with intelligent filtering. It’s perfect for code summarizers, backup tools, static analyzers, or any project that needs a structured snapshot of a filesystem.
Features
- Efficient directory walking – powered by the
ignorecrate, with.gitignoresupport, hidden file control, symlink following, and depth limits. - Glob-based ignore patterns – exclude files/folders using familiar patterns like
*.logortarget/. - Binary detection – automatically skip binary files with simple null‑byte check or accurate content inspection.
- File size limits – omit content for files larger than a threshold.
- ASCII directory tree – get a human‑readable tree like the
treecommand. - Parallel processing (optional) – use Rayon to read files concurrently.
- Streaming mode (optional) – process files one‑by‑one without loading everything into memory.
- Structured output –
SnapcatResultandFileEntryimplementserde::Serialize/Deserializefor easy JSON, YAML, etc. - Flexible formatting – built‑in
outputmodule provides Markdown, plain text, and JSON formatters. - Optional logging – integrate with
tracingfor debug output.
Installation
Or use cargo add:
cargo add snapcat
Enable optional features
cargo add snapcat --features parallel,streaming,logging
| Feature | Description |
|---|---|
parallel |
Parallel file reading with Rayon. |
streaming |
Iterator‑based processing (low memory footprint). |
logging |
tracing debug logs (useful for debugging). |
Quick Start
use snapcat::{SnapcatBuilder, snapcat};
fn main() -> Result<(), snapcat::SnapcatError> {
let options = SnapcatBuilder::new(".")
.respect_gitignore(true)
.include_hidden(false)
.ignore_patterns(vec!["*.tmp".to_string()])
.build();
let result = snapcat(options)?;
// Print the directory tree
println!("{}", result.tree);
// Print each file's path and content
for file in result.files {
println!("File: {}", file.path.display());
if !file.is_binary {
println!("{}", file.content);
}
}
Ok(())
}
️ Configuration
All options are configured via SnapcatBuilder (or directly via SnapcatOptions). The builder provides a fluent interface:
use snapcat::{SnapcatBuilder, BinaryDetection};
let options = SnapcatBuilder::new("./src")
.respect_gitignore(false)
.max_depth(5)
.include_hidden(true)
.follow_links(true)
.ignore_patterns(vec!["node_modules".into(), "*.log".into()])
.file_size_limit(Some(1024 * 1024)) // 1 MB
.binary_detection(BinaryDetection::Accurate)
.include_file_size(true)
.build();
BinaryDetection
| Variant | Description |
|---|---|
Simple |
Checks for null bytes in the first 4 KiB (fast, usually sufficient). |
Accurate |
Uses content_inspector (slower but more accurate). |
None |
Treats all files as text. |
SnapcatOptions
| Field | Type | Description |
|---|---|---|
root |
PathBuf |
Starting directory. |
respect_gitignore |
bool |
Honor .gitignore files. |
max_depth |
Option<usize> |
Maximum recursion depth (None = unlimited). |
include_hidden |
bool |
Include hidden files/dirs (starting with .). |
follow_links |
bool |
Follow symbolic links. |
ignore_patterns |
Vec<String> |
Glob patterns to exclude (e.g., "*.log"). |
file_size_limit |
Option<u64> |
Skip content for files larger than this (bytes). |
binary_detection |
BinaryDetection |
Method to detect binary files. |
include_file_size |
bool |
Include file size in FileEntry. |
Output
SnapcatResult
Returned by snapcat():
tree: String– ASCII directory tree.files: Vec<FileEntry>– List of processed files.
FileEntry
| Field | Type | Description |
|---|---|---|
path |
PathBuf |
Path to the file. |
content |
String |
File contents or placeholder message. |
is_binary |
bool |
Whether the file was detected as binary. |
size |
Option<u64> |
File size in bytes (if include_file_size is true). |
When a file is skipped because it’s too large, content becomes "[File too large, content omitted]" and is_binary is false.
For binary files, content becomes "[Binary file, content omitted]" and is_binary is true.
Advanced Features
Streaming Mode
Process files one by one without holding all results in memory – ideal for huge directories.
use snapcat::{SnapcatBuilder, SnapcatStream};
let options = SnapcatBuilder::new("/var/log").build();
let mut stream = SnapcatStream::new(options)?;
for item in stream {
match item {
Ok(entry) => println!("{} ({} bytes)", entry.path.display(), entry.size.unwrap_or(0)),
Err(e) => eprintln!("Error: {}", e),
}
}
Parallel Processing
Enable the parallel feature and snapcat() will automatically use Rayon’s thread pool to read files concurrently – no code changes required.
Logging
With the logging feature, snapcat emits tracing debug events. Install a subscriber to see them:
use tracing_subscriber;
tracing_subscriber::fmt::init();
// Now snapcat will log debug info
let result = snapcat(options)?;
Output Formatting
The output module provides helpers to format results as Markdown, plain text, or JSON, and write them to files.
use snapcat::{SnapcatBuilder, snapcat, output::{OutputFormat, write_result_to_file}};
let result = snapcat(SnapcatBuilder::new(".").build())?;
write_result_to_file(&result, OutputFormat::Markdown, "snapshot.md", true)?;
️ Error Handling
All fallible operations return SnapcatError, which implements std::error::Error.
pub enum SnapcatError {
Io { path: PathBuf, source: std::io::Error },
Walk(String),
InvalidPath(String),
BinaryDetection,
}
Io– I/O error on a specific file (includes the path).Walk– Error while walking the directory (e.g., permission denied).InvalidPath– The root path is invalid.BinaryDetection– (Rare) binary detection failure.
Examples
Dump all Rust files
let options = SnapcatBuilder::new(".").build();
let result = snapcat(options)?;
for file in result.files {
if file.path.extension().map_or(false, |ext| ext == "rs") {
println!("// {}", file.path.display());
println!("{}", file.content);
}
}
Generate a JSON snapshot
let options = SnapcatBuilder::new(".").include_file_size(true).build();
let result = snapcat(options)?;
let json = serde_json::to_string_pretty(&result)?;
std::fs::write("snapshot.json", json)?;
License
This project is licensed under the GNU Affero General Public License v3.0 – see the LICENSE file for details.
Contributing
Contributions are welcome! Feel free to open an issue or pull request on GitHub.
Dependencies
~4–10MB
~168K SLoC