SkillAgentSearch skills...

Hazelnut

🌰 Terminal-based automated file organizer inspired by Hazel. Watch folders and organize files with rules.

Install / Use

/learn @ricardodantas/Hazelnut
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <img src="screenshots/01-dashboard.png" alt="Hazelnut Dashboard" width="700"> </p> <h1 align="center"> 🌰 Hazelnut </h1> <p align="center"> <strong>A terminal-based automated file organizer inspired by <a href="https://www.noodlesoft.com/">Hazel</a></strong> </p> <p align="center"> <i>Watch your folders and automatically organize files based on rules you define — all from your terminal.</i> </p> <p align="center"> <a href="https://github.com/ricardodantas/hazelnut/releases"> <img src="https://img.shields.io/github/v/release/ricardodantas/hazelnut?style=flat&labelColor=1e1e2e&color=cba6f7&logo=github&logoColor=white" alt="Release"> </a> <a href="https://crates.io/crates/hazelnut"> <img src="https://img.shields.io/crates/v/hazelnut?style=flat&labelColor=1e1e2e&color=fab387&logo=rust&logoColor=white" alt="Crates.io"> </a> <a href="https://github.com/ricardodantas/hazelnut/actions"> <img src="https://img.shields.io/github/actions/workflow/status/ricardodantas/hazelnut/ci.yml?style=flat&labelColor=1e1e2e&color=a6e3a1&logo=github-actions&logoColor=white&label=CI" alt="CI"> </a> <a href="https://github.com/ricardodantas/hazelnut/blob/main/LICENSE"> <img src="https://img.shields.io/badge/license-GPL--3.0-89b4fa?style=flat&labelColor=1e1e2e" alt="License"> </a> <a href="https://rust-lang.org"> <img src="https://img.shields.io/badge/rust-1.93+-f9e2af?style=flat&labelColor=1e1e2e&logo=rust&logoColor=white" alt="Rust Version"> </a> </p> <br>

📖 Table of Contents

<br>

✨ Features

<table> <tr> <td width="50%">

📁 Smart File Watching

Watch any folder for new and changed files with configurable debouncing and recursive monitoring. Paths support ~, $VAR, and ${VAR} expansion.

🎯 Flexible Rules Engine

Define powerful rules with conditions based on name, extension, size, age, and more. Multiple rules can match the same file — all matching rules execute in order.

⚡ Powerful Actions

Move, copy, rename, delete, archive files or directories, send to trash, or run custom scripts — all automated. Cross-filesystem moves are handled transparently.

</td> <td width="50%">

🖥️ Beautiful TUI

A gorgeous terminal interface for managing rules and monitoring activity in real-time.

🔧 Background Daemon

Set it and forget it — the daemon runs quietly and applies rules 24/7.

📝 Simple Configuration

Human-readable TOML config that's easy to write and maintain.

</td> </tr> </table> <br>

Feature Highlights

| Feature | Description | |---------|-------------| | 🔍 Pattern Matching | Glob patterns and regex for precise file matching | | 📊 Size Conditions | Filter files by size (greater than, less than) | | 📅 Age Conditions | Match files by modification date | | 🏷️ Multiple Extensions | Match any of multiple file types | | 📂 Recursive Watching | Monitor subdirectories automatically | | 🎨 15 Built-in Themes | From Dracula to Cyberpunk | | 🔔 Desktop Notifications | Get alerted on errors (cross-platform) | | 📋 Activity Log | Full history of all file operations |

<br>

🚀 Quick Start

Installation

macOS

# Homebrew (recommended - fast, pre-built binary)
brew install ricardodantas/tap/hazelnut

Linux

# Homebrew
brew install ricardodantas/tap/hazelnut

# Or via Cargo
cargo install hazelnut
Arch Linux (pacman)
pacman -S hazelnut

Windows

# Via Cargo (requires Rust toolchain)
cargo install hazelnut

# Or download pre-built binary from GitHub Releases:
# https://github.com/ricardodantas/hazelnut/releases

From Source

git clone https://github.com/ricardodantas/hazelnut
cd hazelnut
cargo install --path .

Note: The daemon (hazelnutd) is only available on macOS and Linux. On Windows, only the TUI (hazelnut) is available.

First Run

Hazelnut needs two things to work:

  1. Watch folders — which directories to monitor
  2. Rules — what to do with files in those folders

⚠️ Important: Rules alone won't do anything! You must also configure at least one watch folder.

  1. Create a config file at ~/.config/hazelnut/config.toml:
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# STEP 1: Define which folders to watch
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[[watch]]
path = "/home/youruser/Downloads"  # Full path, ~, $HOME all work
recursive = false                   # Set true to include subfolders

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# STEP 2: Define rules for what to do with files
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[[rule]]
name = "Organize PDFs"

[rule.condition]
extension = "pdf"

[rule.action]
type = "move"
destination = "/home/youruser/Documents/PDFs"
  1. Launch the TUI to manage and monitor:
hazelnut
  1. Or start the daemon to run in the background:
hazelnutd start
<p align="center"> <img src="screenshots/05-rules.png" alt="Rules View" width="600"> </p> <br>

⚙️ Configuration

Hazelnut uses TOML for configuration. The config file is always located at:

~/.config/hazelnut/config.toml

Full Configuration Example

# ─────────────────────────────────────────────────────────────
# General Settings
# ─────────────────────────────────────────────────────────────

[general]
# Logging level: trace, debug, info, warn, error
log_level = "info"

# Optional log file path
log_file = "~/.local/share/hazelnut/hazelnut.log"

# Wait time (seconds) before processing a file after change detected
debounce_seconds = 2

# How often to check for file changes (seconds)
polling_interval_secs = 5

# Desktop notifications on errors (cross-platform)
notifications_enabled = true

# Theme for the TUI
theme = "catppuccin-mocha"

# ─────────────────────────────────────────────────────────────
# Watch Folders
# ─────────────────────────────────────────────────────────────

[[watch]]
path = "~/Downloads"
recursive = false

[[watch]]
path = "~/Desktop"
recursive = false
# Only apply specific rules to this folder
rules = ["screenshots", "temp-files"]

[[watch]]
path = "~/Documents/Inbox"
recursive = true  # Watch subdirectories too

# ─────────────────────────────────────────────────────────────
# Rules
# ─────────────────────────────────────────────────────────────

[[rule]]
name = "Organize PDFs"
enabled = true
stop_processing = false  # Continue checking other rules

[rule.condition]
extension = "pdf"

[rule.action]
type = "move"
destination = "~/Documents/PDFs"
create_destination = true
overwrite = false

[[rule]]
name = "Screenshots"
enabled = true

[rule.condition]
name_matches = "Screenshot*.png"

[rule.action]
type = "move"
destination = "~/Pictures/Screenshots"

[[rule]]
name = "Clean Old Downloads"
enabled = true

[rule.condition]
age_days_greater_than = 30
extensions = ["tmp", "log", "bak"]

[rule.action]
type = "trash"

See docs/configuration.md for the complete reference.

Watch Editor (TUI)

You can manage watch folders directly in the TUI:

  1. Add a new watch: Press a or n in the Watches view
  2. Edit an existing watch: Select a watch and press e
  3. Delete a watch: Select a watch and press d

The watch editor dialog allows you to configure:

  • Path - Path to the folder to watch (supports ~, $VAR, ${VAR}, or absolute paths)
  • Recursive - Whether to include subdirectories

Use Tab to move between fields, Enter to save, and Esc to cancel.

<br>

📋 Rules

Rules are the heart of Hazelnut. Each rule has a condition (what files to match) and an action (what to do with them).

Conditions

All conditions in a rule must match for the rule to apply.

File Name

[rule.condition]
# Glob pattern matching
name_matches = "Screenshot*.png"

# Regex pattern matching
name_regex = "^invoice_\\d{4}\\.pdf$"

File Extension

[rule.condition]
# Single extension
extension = "pdf"

# Multiple extensions (match any)
extensions = ["jpg", "jpeg", "png", "gif", "webp"]

File Size

[rule.condition]
# Size in bytes
size_greater_than = 10485760  # > 10 MB
size_less_than = 1048576      # < 1 MB

File Age

[rule.condition]
# Age in days (based on modification time)
age_days_greater_than = 30  # Older than 30 days
age_days_less_than = 7      # Newer than 7 days

File Type

[rule.condition]
is_directory = false  # Match only files
is_hidden = true      # Match hidden files (starting with .)

Actions

Move

[rule.action]
type = "move"
destination = "~/Documents/Archive"
create_destination = true  # Create folder if missing
overwrite = false          # Don't overwrite existing files

Copy

[rule.action]
type = "copy"
destination = "~/Backup"
create_destination = true
overwrite = false

Rename

[rule.action]
type = "rename"
pattern = "{date}_{name}.{ext}"

Available variables:

| Variable | Description | Example | |----------|-------------|---------| | {name} | Filename without extension | document | | {filename} | Full filename | document.pdf | | {ext} | Extension | pdf (empty if none) | | {path} | Full path | /home/user/document.pdf | | {dir} | Parent directory | /home/user | | {date} | Current date | 2024-01-15 | | {datetime} | Current datetime | 2024-01-15_14-30-00 | | {date:FORMAT} | Custom format | {date:%Y%m%d}20240115 |

Trash

[rule.action]
View on GitHub
GitHub Stars220
CategoryDevelopment
Updated9h ago
Forks8

Languages

Rust

Security Score

100/100

Audited on Apr 3, 2026

No findings