Command Menu

Search pages, blogs, projects, and more...

Hakai

march 1, 2026

Hakai

A blazing-fast, Rust-powered directory destroyer with a Bun TUI — scans 50,000 directories in under a second and deletes concurrently without blocking the UI.

RustBunTokioRayon

hakai (破壊)

A high-performance directory destroyer engineered to find and obliterate heavy build artifact folders -- node_modules, target, __pycache__, and more -- across thousands of projects in under a second.

Overview

Existing tools like npkill suffer from fundamental limitations: single-threaded scanning, blocking deletion that freezes the UI, and broken behavior on Windows Git Bash. Hakai eliminates these bottlenecks by splitting the system into a compiled Rust core for filesystem operations and a Bun-powered TUI for the interactive interface, achieving order-of-magnitude performance improvements while maintaining a responsive user experience.

Architecture

Hakai employs a dual-process architecture that leverages the strengths of each runtime where they matter most.

Rust Core (hakai-core)

The Rust binary owns all CPU-bound and I/O-bound work: parallel directory traversal, concurrent size calculation, async deletion, and risk analysis. Heavy filesystem operations run at native speed with direct OS API access, unconstrained by a JavaScript event loop or garbage collector.

The scanner uses ignore::WalkBuilder with rayon's work-stealing thread pool. When a target directory is found, the walker prunes that subtree immediately, avoiding unnecessary stat calls. Size calculation is dispatched to worker threads upon discovery, overlapping I/O with the ongoing scan.

Bun TUI (hakai-tui)

The interactive terminal interface is built in Bun, chosen for its sub-50ms startup time and efficient rendering pipeline. The TUI provides diff-based flicker-free rendering, vim-style keybindings, multi-select support, and regex-powered search filtering. By handling only the presentation layer, the TUI remains responsive regardless of how aggressively the core is scanning or deleting.

IPC Protocol

The two processes communicate via a newline-delimited JSON (NDJSON) protocol over stdin/stdout pipes. The Rust core emits structured JSON messages -- scan results, size calculations, deletion progress, and error reports -- as a continuous stream. The Bun frontend parses this stream line by line and updates the UI in real time.

This ensures the rendering pipeline never blocks on filesystem operations and vice versa. One JSON object per line, no framing overhead, trivially debuggable with jq.

Key Features

Parallel Scanning

Rayon's work-stealing thread pool distributes directory traversal across all CPU cores. Subtree pruning on match skips the contents of matched directories entirely, eliminating unnecessary I/O. Scanning 50,000 directories completes in under one second -- a 10-15x improvement over sequential Node.js alternatives.

Concurrent Deletion

Deletion is handled asynchronously via tokio, processing up to 8 tasks concurrently. Each task operates independently -- a slow delete on a large directory does not block smaller ones. An instant rename-to-trash strategy renames the target to a hidden .hakai_trash_* path (an atomic O(1) operation), so the directory disappears immediately. Actual file removal proceeds in the background using rayon's parallel recursive walker with par_iter for batches of 256+ files.

The UI continues rendering and accepting input throughout, with real-time progress streamed through the IPC protocol.

Risk Analysis

Hakai flags potentially dangerous targets before deletion:

  • System-level directories -- global installations that would break toolchains.
  • Orphaned node_modules -- missing a corresponding package.json, possibly a monorepo root.
  • Active project artifacts -- recently modified directories likely under active development.

Risk levels are surfaced in the TUI so developers make informed decisions.

Headless Mode

For CI integration, hakai supports a headless mode bypassing the TUI. Output formats include complete JSON (--json) and streaming NDJSON (--json-stream). A --delete-all flag with -y confirmation skip enables automated cleanup, and --dry-run previews deletions without removing anything.

Implementation Details

Rayon Thread Pool

The scanner uses rayon's par_iter and the ignore crate's WalkBuilder for parallel directory traversal. The work-stealing scheduler ensures idle threads pick up work from busy ones, maintaining high throughput on heterogeneous directory structures. Size calculation overlaps with scanning -- dispatched to worker threads immediately upon discovery rather than queued for a second pass.

Tokio Async Runtime

Deletion uses tokio's async runtime rather than blocking OS calls. Each deletion is a spawned task that progresses independently, with the runtime managing scheduling, cancellation, and error propagation. Concurrent deletion is capped at 8 tasks to balance parallelism against OS file descriptor limits.

Newline-Delimited JSON IPC

The NDJSON protocol keeps the two processes cleanly decoupled. Each message is a self-contained JSON object terminated by a newline -- no framing, no length prefixes, no stateful negotiation. The protocol is trivially extensible and debuggable by piping the core's output to jq.

Cross-Platform Path Handling

Windows' 260-character MAX_PATH limitation is handled via automatic \\?\ UNC prefix. Read-only files (common in npm caches) have permissions cleared before deletion. TTY detection is handled explicitly for Windows Git Bash, ensuring correct rendering across all terminal emulators.

Configurable Profiles

Six built-in language profiles -- node, rust, python, flutter, java, and all -- target standard build artifact directories per ecosystem. A .hakairc TOML config supports custom profiles and exclusion patterns for team-specific cleanup rules.

Tech Stack Rationale

ComponentTechnologyRationale
Filesystem EngineRustZero-cost abstractions, direct OS API access, no garbage collector pauses during I/O-heavy operations
ParallelismRayonWork-stealing thread pool with ergonomic parallel iterators, proven in production Rust codebases
Async DeletionTokioIndustry-standard async runtime with robust task scheduling and cancellation support
TUIBunSub-50ms startup, fast rendering pipeline, and familiar TypeScript ergonomics for UI development
IPCNDJSON over stdioZero-dependency, streaming-friendly, human-readable, and trivially debuggable

This architecture ensures that each component operates within its optimal domain: Rust handles the performance-critical systems work, Bun handles the interactive presentation, and the IPC protocol keeps them cleanly decoupled.