Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
264 changes: 209 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,101 +1,255 @@
# gitclean
<div align="center">

A fast Rust CLI to scan and clean files and directories ignored by .gitignore across your project. It detects ignored items, shows sizes, and lets you interactively delete them.
# 🧹 gitclean

## Features
### _Clean your Git projects like a pro_

- Recursively collects .gitignore rules (supports nested .gitignore)
- Extra ignore patterns via CLI (`-i ".env*,.config*"`)
- Preserves common secret/config files by default (negated patterns)
- Parallel size computation (WalkDir + Rayon)
- TUI multiselect (inquire) with sizes, sorted descending
- Informative spinners and logs (indicatif + console)
**A blazingly fast Rust CLI that scans and removes files ignored by `.gitignore` — interactively and safely.**

## Install
[![Crates.io](https://img.shields.io/crates/v/gitclean.svg)](https://crates.io/crates/gitclean)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Rust](https://img.shields.io/badge/rust-%23000000.svg?style=flat&logo=rust&logoColor=white)](https://www.rust-lang.org/)

Build from source:
[Installation](#-installation) •
[Features](#-features) •
[Usage](#-usage) •
[Examples](#-examples) •
[Library](#-library-usage)

</div>

---

## 🎯 Why gitclean?

Ever wondered how much disk space those `node_modules`, `target`, or `.next` folders are eating up across your projects? **gitclean** gives you **instant visibility** and **safe cleanup** of all ignored files and directories.

### ✨ What makes it special?

- **⚡ Blazingly Fast** – Written in Rust with parallel processing
- **🎯 Smart Detection** – Recursively respects all nested `.gitignore` files
- **🔒 Safe by Default** – Preserves secrets like `.env` files automatically
- **📊 Visual Insights** – See sizes before you delete
- **🎨 Beautiful TUI** – Interactive multiselect with sorted results
- **🛡️ Zero Risk** – Review and confirm before any deletion

---

## 🚀 Installation

Install directly from crates.io:

```bash
cargo install --path .
cargo install gitclean
```

Or build a release binary:
That's it! Now you can use `gitclean` anywhere.

---

## ✨ Features

| Feature | Description |
|---------|-------------|
| 🔄 **Recursive Scanning** | Collects rules from all `.gitignore` files in your project tree |
| 🎯 **Custom Patterns** | Add extra ignore patterns via CLI (`-i ".env*,.config*"`) |
| 🔐 **Smart Preservation** | Automatically protects common secret/config files |
| ⚡ **Parallel Processing** | Lightning-fast size computation with WalkDir + Rayon |
| 🎨 **Interactive TUI** | Beautiful multiselect interface with sizes, sorted descending |
| 📊 **Detailed Logging** | Informative spinners and progress indicators |

---

## 📖 Usage

```bash
cargo build --release
./target/release/gitclean .
gitclean <PATH> [OPTIONS]
```

## Usage
### Options

```bash
gitclean <PATH> [--ignores|-i "pattern1,pattern2,..."]
```
<PATH> Project root directory to scan
-i, --ignores <PATTERNS> Extra ignore patterns (comma-separated)
-h, --help Print help information
-V, --version Print version information
```

---

## 💡 Examples

Examples:
### Clean current directory

```bash
# Current directory
gitclean .
```

**Output:**
```
🧹 gitclean v1.0.0
📂 Root: /home/user/projects/my-app
📋 Default patterns: 15
🎯 Extra patterns: 0

⠋ Loading .gitignore files...
✓ Found 3 .gitignore files

⠋ Scanning ignored items...
✓ Found 127 ignored items (45 dirs, 82 files)

⠋ Computing sizes...
✓ Sizes computed

┌──────────────────────────────────────────┐
│ Select items to delete (Space to toggle) │
└──────────────────────────────────────────┘

[ ] node_modules/ 1.2 GB
[ ] target/ 856 MB
[ ] .next/ 234 MB
[ ] dist/ 89 MB
[ ] coverage/ 12 MB
```

### Scan specific project

```bash
gitclean ~/projects/my-app
```

# Custom root path
gitclean /path/to/project
### Add custom ignore patterns

# Add extra ignore patterns (comma-separated)
```bash
gitclean . -i ".env*,.config*,*.log"
```

## Logs & UX
This will additionally ignore:
- All files starting with `.env`
- All files starting with `.config`
- All `.log` files

---

- Startup header: shows version, root, default and extra pattern counts
- Spinners for: loading .gitignore, scanning ignored items, computing sizes
- Summary after scanning: total ignored (dirs/files)
- Deletion logs include size per item
## 🎨 Interactive Experience

## Library usage
gitclean provides a delightful CLI experience:

Core logic is exposed as a library for reuse:
1. **🔄 Spinner animations** while scanning
2. **📊 Progress indicators** for long operations
3. **📋 Organized results** sorted by size (largest first)
4. **✅ Multi-select interface** to choose what to delete
5. **✓ Confirmation logs** showing freed space

---

## 📚 Library Usage

Use `gitclean` as a library in your own Rust projects:

```rust
use gitclean::{gather_gitignores, scan_ignored_files, calculate_sizes, format_size};
use gitclean::{
gather_gitignores,
scan_ignored_files,
calculate_sizes,
format_size
};
use indicatif::ProgressBar;
use std::path::Path;

let root = Path::new(".").canonicalize().unwrap();
let spinner = ProgressBar::hidden();
let extra: Vec<String> = vec![];
let map = gather_gitignores(&root, &spinner, &extra)?;
let ignored = scan_ignored_files(&root, &map, &spinner)?;
let items = calculate_sizes(ignored, &spinner, &root)?;
println!("{} items", items.len());
fn main() -> anyhow::Result<()> {
let root = Path::new(".").canonicalize()?;
let spinner = ProgressBar::hidden();
let extra: Vec<String> = vec![];

// Gather all .gitignore rules
let map = gather_gitignores(&root, &spinner, &extra)?;

// Scan for ignored files
let ignored = scan_ignored_files(&root, &map, &spinner)?;

// Calculate sizes
let items = calculate_sizes(ignored, &spinner, &root)?;

println!("Found {} ignored items", items.len());
for item in items {
println!("{}: {}", item.path.display(), format_size(item.size));
}

Ok(())
}
```

---

## 🏗️ Architecture

gitclean is built with a clean modular structure:

```
src/
├── lib.rs → Public API exports
├── patterns.rs → Default ignore patterns
├── types.rs → Core types (ItemWithSize)
├── ignore.rs → .gitignore parsing
├── scan.rs → Scanning logic
├── size.rs → Size computation
├── fsops.rs → File operations
├── util.rs → Utilities (format_size)
└── main.rs → CLI interface
```

Each module is designed to be **reusable** and **testable**.

## Module layout
---

- `src/lib.rs`: public re-exports
- `src/patterns.rs`: default ignore patterns
- `src/types.rs`: shared types (`ItemWithSize`)
- `src/ignore.rs`: .gitignore loading (`gather_gitignores`)
- `src/scan.rs`: scan logic (`scan_ignored_files`, `is_path_ignored`)
- `src/size.rs`: size computation (`calculate_sizes`)
- `src/fsops.rs`: file ops (`remove_item`)
- `src/util.rs`: helpers (`format_size`)
- `src/main.rs`: thin CLI using the library
## 🛠️ Development

## Development
### Run tests

```bash
# Run tests
cargo test
```

### Build release

# Build release
```bash
cargo build --release
./target/release/gitclean .
```

### Run locally

```bash
cargo run -- .
```

## Contributing
---

## 🤝 Contributing

Contributions are welcome! Here's how you can help:

1. 🍴 Fork the repository
2. 🌿 Create a feature branch (`git checkout -b feature/amazing-feature`)
3. 💾 Commit your changes (`git commit -m 'Add amazing feature'`)
4. 📤 Push to the branch (`git push origin feature/amazing-feature`)
5. 🎉 Open a Pull Request

Please read [`CONTRIBUTING.md`](CONTRIBUTING.md) and follow the [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md).

---

## 📝 License

MIT © 2025 [Jordy Fontoura](https://github.com/jordyfontoura)

---

<div align="center">

Contributions are welcome! Please read `CONTRIBUTING.md` and follow the `CODE_OF_CONDUCT.md`.
**Made with ❤️ and 🦀 Rust**

## License
[⬆ Back to top](#-gitclean)

MIT © 2025 Jordy Fontoura
</div>
Loading