Skip to content

Instantly share code, notes, and snippets.

@dankerizer
Last active August 22, 2026 08:29
Show Gist options
  • Select an option

  • Save dankerizer/372c92d3a64586a35dc1d23db5e0188e to your computer and use it in GitHub Desktop.

Select an option

Save dankerizer/372c92d3a64586a35dc1d23db5e0188e to your computer and use it in GitHub Desktop.
🧹 bersihkan - command pembersih node_modules, .next, dist, build, cache Laravel secara rekursif (global)

🧹 bersihkan

Hapus node_modules, .next, dist, build, cache Laravel, dan artefak framework lainnya secara rekursif — bisa dipanggil dari mana pun.

Support: Next.js / React / Nuxt / Vite / Astro / Laravel / Go / Rust / Java / Flutter / Terraform / Python dan umum. Aman, ada --dry-run + live spinner.

disk full

✨ Fitur

  • 🔁 Rekursif — scan semua subfolder dari posisi kamu berdiri
  • 👀 Aman — konfirmasi sebelum hapus + mode --dry-run
  • 🔍 Live spinner — tampil folder yang sedang di-scan + jumlah found (tidak kelihatan hang)
  • 📊 Hitung ukuran — tampil total yang dibebaskan
  • 📂 Sortname (A-Z, cepat) atau size (terbesar dulu)
  • 🚫 Exclude-e / --exclude untuk kecualikan folder/file/ekstensi
  • 🌍 Global command — install sekali, pakai di mana pun
  • Cepatfind single-pass + -prune .git, compatible bash 3.2 (macOS)

📦 Yang Dibersihkan

Kategori Target
JS/Node/React/Next/Nuxt/Vite/Astro node_modules, .next, .nuxt, .output, .vercel, .turbo, out, dist, build, .parcel-cache, .vite, coverage, .nyc_output, .cache
Laravel/PHP bootstrap/cache/*.php, storage/framework/views/*, storage/framework/cache/data/*, storage/framework/sessions/*, storage/logs/*.log (+ vendor/ jika --vendor)
Go bin/ (jika ada go.mod), vendor/ (jika --vendor), *.out, *.test
Rust target/
Java/Kotlin target/, build/, .gradle/, out/
Flutter/Dart .dart_tool/, build/
Terraform .terraform/
Python __pycache__, .pytest_cache, .mypy_cache, .ruff_cache, .tox
Umum .DS_Store, Pods/, _build/

🚀 Instalasi

Homebrew (macOS / Linux) — Recommended

brew tap dankerizer/bersihkan
brew install bersihkan

Atau one-liner:

brew install dankerizer/bersihkan/bersihkan

Verifikasi:

bersihkan --help

One-liner (tanpa Homebrew)

curl -fsSL https://raw.githubusercontent.com/dankerizer/bersihkan/master/bersihkan -o ~/.local/bin/bersihkan && chmod +x ~/.local/bin/bersihkan

Jika command not found, tambahkan ke PATH:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
# atau bash:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc

Manual

git clone https://github.com/dankerizer/bersihkan.git
cd bersihkan
chmod +x bersihkan
mkdir -p ~/.local/bin && cp bersihkan ~/.local/bin/bersihkan

System-wide (butuh sudo)

sudo curl -fsSL https://raw.githubusercontent.com/dankerizer/bersihkan/master/bersihkan -o /usr/local/bin/bersihkan
sudo chmod +x /usr/local/bin/bersihkan

💻 Cara Pakai

bersihkan                                  # urut nama A-Z (default)
bersihkan --sort=size                      # urut ukuran terbesar dulu
bersihkan -e vendor -e bin                 # jangan hapus vendor & bin
bersihkan --exclude="*.log" --dry-run      # jangan hapus *.log
bersihkan -e ".next" -e "dist" -y          # kecualikan .next & dist
bersihkan -e "target" --sort=size -v       # kecualikan Rust target, urut size
bersihkan ~/Projects --sort=name           # urut folder A-Z
bersihkan . --dry-run                      # cek dulu (tanpa hapus)
bersihkan . --vendor -y                    # hapus termasuk vendor/
bersihkan --help                           # bantuan lengkap

Contoh Output

Sort by name (default)

🧹 bersihkan → /Users/hadie/Projects
Ditemukan 3 item (urut: nama A-Z):

  • my-app/.next
  • my-app/node_modules
  • api/dist

  Total: 365M (3 item)

Sort by size + exclude

🧹 bersihkan → /Users/hadie/Projects
  Exclude: vendor *.log
  → 2 item di-exclude (vendor *.log)
Ditemukan 3 item (urut: terbesar dulu):

  320M     my-app/node_modules
   45M     api/dist
  120K     my-app/.next

  Total: 365M (3 item)

✨ Selesai! 3 item dibersihkan (365M dibebaskan)

Live scanning (saat scan folder besar)

⠹ Mencari... 12 found → my-app/.next

⚙️ Opsi

PATH              Folder target (default: ".")
-n, --dry-run     Hanya tampilkan apa yang akan dihapus
-v, --verbose     Tampilkan detail + ukuran (lebih lambat)
    --vendor      Juga hapus vendor/ (PHP/Laravel/Go)
    --sort <mode> Urutan: name (default, A-Z) | size (terbesar dulu)
-e, --exclude <pat> Kecualikan folder/file/ekstensi (bisa berulang)
                  Contoh: -e vendor -e "*.log" -e "bin" -e ".next"
-y, --yes         Langsung hapus tanpa konfirmasi
-h, --help        Bantuan

🧠 SKILL.md (untuk AI Agent)

Repo ini menyertakan SKILL.md agar AI agent (OpenCode, Claude Code, dll) bisa auto-detect skill bersihkan.

# Install skill untuk agent
mkdir -p ~/.config/opencode/skills/bersihkan
curl -fsSL https://raw.githubusercontent.com/dankerizer/bersihkan/master/SKILL.md -o ~/.config/opencode/skills/bersihkan/SKILL.md

Lihat SKILL.md untuk detail trigger & workflow agent.

🔧 Uninstall

# Homebrew
brew uninstall bersihkan
brew untap dankerizer/bersihkan  # jika pakai tap

# Manual
rm ~/.local/bin/bersihkan
# atau system-wide:
sudo rm /usr/local/bin/bersihkan

⚠️ Disclaimer

Harap pastikan dan/atau push ke git terlebih dahulu sebelum mengkonfirmasi penghapusan. Segala risiko kehilangan data bukan menjadi tanggung jawab kami. Gunakan --dry-run untuk memeriksa terlebih dahulu. Tindakan bersihkan bersifat permanen (rm -rf).

📝 Lisensi

Apache-2.0 — lihat LICENSE

📜 Changelog

  • v2.5--exclude + Rust/Java/Flutter/Terraform support
  • v2.4 — support Go (bin/, vendor/, *.out, *.test)
  • v2.3--sort=name|size + live spinner, single-pass find + prune
  • v2.2 — live spinner (tampil folder sedang di-scan)
  • v2.1 — single find + prune .git, skip du kecuali --verbose
  • v2.0 — support Next.js, Laravel, Python, global command + SKILL.md

dankedev.com

#!/usr/bin/env bash
# bersihkan - Pembersih project: hapus node_modules, build output, cache framework secara rekursif
# v2.5.1 - Disclaimer: push ke git dulu sebelum hapus
# Usage: bersihkan [PATH] [OPTIONS]
set -e
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
CYAN='\033[0;36m'
DIM='\033[2m'
NC='\033[0m'
TARGET="."
DRY_RUN=false
INCLUDE_VENDOR=false
VERBOSE=false
AUTO_YES=false
SORT="name" # name | size
EXCLUDE=()
usage() {
cat <<'EOF'
Usage: bersihkan [PATH] [OPTIONS]
PATH Folder target (default: current folder ".")
Scan dilakukan REKURSIF dari PATH tersebut.
OPTIONS:
-n, --dry-run Hanya tampilkan apa yang akan dihapus (tidak menghapus)
-v, --verbose Tampilkan detail + ukuran (lebih lambat)
--vendor Juga hapus vendor/ (PHP/Laravel/Go)
--sort <mode> Urutan: name (default, A-Z) | size (terbesar dulu)
-e, --exclude <pat> Kecualikan folder/file/ekstensi (bisa dipakai berulang)
Contoh: -e vendor -e "*.log" -e "bin" -e ".next"
-h, --help Tampilkan bantuan ini
-y, --yes Langsung hapus tanpa konfirmasi
Contoh:
bersihkan # urut nama
bersihkan --sort=size # urut ukuran
bersihkan -e vendor -e bin # jangan hapus vendor & bin
bersihkan --exclude="*.log" --dry-run # jangan hapus *.log
bersihkan -e ".next" -e "dist" -y # kecualikan .next & dist
bersihkan . --vendor -y # hapus termasuk vendor/
Yang dihapus (rekursif, semua ditemukan akan dihapus):
JS/Node/React/Next/Nuxt/Astro/Vite:
node_modules, .next, .nuxt, .output, .vercel, .turbo, out, dist, build,
.parcel-cache, .vite, coverage, .nyc_output, .cache
Laravel/PHP:
bootstrap/cache/*.php, storage/framework/views/*,
storage/framework/cache/*, storage/framework/sessions/*,
storage/logs/*.log (+ vendor/ jika --vendor)
Go:
bin/, vendor/ (jika --vendor), *.out, *.test
Rust: target/ (jika ada Cargo.toml)
Java/Kotlin: target/, build/, .gradle/, out/ (jika ada pom.xml/build.gradle)
Flutter/Dart: .dart_tool/, build/ (jika ada pubspec.yaml)
Terraform: .terraform/ (jika ada *.tf)
Python: __pycache__, .pytest_cache, .mypy_cache, .ruff_cache
Umum: .DS_Store
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help) usage; exit 0 ;;
-n|--dry-run) DRY_RUN=true; shift ;;
-v|--verbose) VERBOSE=true; shift ;;
--vendor) INCLUDE_VENDOR=true; shift ;;
--sort) SORT="$2"; shift 2 ;;
--sort=*) SORT="${1#--sort=}"; shift ;;
-e|--exclude) EXCLUDE+=("$2"); shift 2 ;;
--exclude=*) EXCLUDE+=("${1#--exclude=}"); shift ;;
-y|--yes) AUTO_YES=true; shift ;;
--) shift; break ;;
-*) echo -e "${RED}Unknown option: $1${NC}"; usage; exit 1 ;;
*) TARGET="$1"; shift ;;
esac
done
if [[ "$SORT" != "name" && "$SORT" != "size" ]]; then
echo -e "${RED}✗ --sort harus 'name' atau 'size' (dapat: $SORT)${NC}"
exit 1
fi
if [[ "$SORT" == "size" ]]; then
VERBOSE=true
fi
if [[ ! -d "$TARGET" ]]; then
echo -e "${RED}✗ Folder tidak ditemukan: $TARGET${NC}"
exit 1
fi
TARGET="$(cd "$TARGET" && pwd)"
echo -e "${CYAN}🧹 bersihkan${NC} ${DIM}→ $TARGET${NC}"
if $DRY_RUN; then echo -e "${YELLOW} [DRY-RUN] tidak ada yang benar-benar dihapus${NC}"; fi
if [[ ${#EXCLUDE[@]} -gt 0 ]]; then
echo -e "${DIM} Exclude: ${EXCLUDE[*]}${NC}"
fi
echo ""
# ---- Daftar target ----
DIR_NAMES=(
"node_modules"
".next"
".nuxt"
".output"
".vercel"
".turbo"
"out"
"dist"
"build"
".parcel-cache"
".vite"
"coverage"
".nyc_output"
".cache"
"__pycache__"
".pytest_cache"
".mypy_cache"
".ruff_cache"
# Tambahan umum (aman, selalu cache/build)
"target"
".gradle"
".dart_tool"
".terraform"
"_build"
"Pods"
".tox"
)
if $INCLUDE_VENDOR; then
DIR_NAMES+=("vendor")
fi
# Build find expression untuk dirs
DIR_EXPR=""
for i in "${!DIR_NAMES[@]}"; do
if [[ $i -eq 0 ]]; then
DIR_EXPR="-name \"${DIR_NAMES[$i]}\""
else
DIR_EXPR="$DIR_EXPR -o -name \"${DIR_NAMES[$i]}\""
fi
done
FOUND_FILE=$(mktemp /tmp/bersihkan.XXXXXX)
trap 'rm -f "$FOUND_FILE"' EXIT
# ---- Live scanning indicator ----
SPIN_CHARS='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
spin_pid=""
start_spinner() {
local target="$1"
local found_file="$2"
local i=0
printf "\033[?25l" 2>/dev/null || true
while true; do
local cnt=$(wc -l < "$found_file" 2>/dev/null | tr -d ' '); cnt=${cnt:-0}
local last=$(tail -n 1 "$found_file" 2>/dev/null | sed "s|^$target/||" 2>/dev/null)
if [[ ${#last} -gt 42 ]]; then last="…${last: -41}"; fi
local ch="${SPIN_CHARS:$((i % 10)):1}"
if [[ -n "$last" ]]; then
printf "\r${DIM}%s Mencari... ${YELLOW}%s found${NC} ${DIM}→ %s${NC} " "$ch" "$cnt" "$last"
else
printf "\r${DIM}%s Mencari di %s ... ${YELLOW}%s found${NC} " "$ch" "$(basename "$target")" "$cnt"
fi
sleep 0.12
i=$((i+1))
done
}
stop_spinner() {
if [[ -n "$spin_pid" ]] && kill -0 "$spin_pid" 2>/dev/null; then
kill "$spin_pid" 2>/dev/null || true
wait "$spin_pid" 2>/dev/null || true
fi
printf "\r\033[K" 2>/dev/null || printf "\r%60s\r" " "
printf "\033[?25h" 2>/dev/null || true
}
# ---- OPTIMIZED SINGLE FIND ----
start_spinner "$TARGET" "$FOUND_FILE" &
spin_pid=$!
# Utama: single find
eval "find \"$TARGET\" \
\( -type d -name \".git\" -prune \) -o \
\( -type d \( $DIR_EXPR \) -prune -print \) -o \
\( -type f -name \".DS_Store\" -print \) \
2>/dev/null" > "$FOUND_FILE" || true
# Laravel cache
if [[ -d "$TARGET/bootstrap" ]] || find "$TARGET" -maxdepth 4 -name "artisan" -type f 2>/dev/null | grep -q .; then
for pat in "bootstrap/cache/*.php" "storage/framework/views/*" "storage/logs/*.log"; do
dir_part="$(dirname "$pat")"
file_pat="$(basename "$pat")"
find "$TARGET" \( -type d -name ".git" -prune \) -o -type f -path "*/$dir_part/$file_pat" ! -name ".gitignore" ! -name ".gitkeep" -print 2>/dev/null >> "$FOUND_FILE" || true
done
for d in "storage/framework/cache/data" "storage/framework/sessions"; do
find "$TARGET" \( -type d -name ".git" -prune \) -o -type f -path "*/$d/*" ! -name ".gitignore" ! -name ".gitkeep" -print 2>/dev/null | head -n 300 >> "$FOUND_FILE" || true
done
fi
# Go artefacts
if find "$TARGET" -maxdepth 4 -name "go.mod" -type f -print -quit 2>/dev/null | grep -q .; then
while IFS= read -r gomod; do
godir=$(dirname "$gomod")
if [[ -d "$godir/bin" ]]; then
echo "$godir/bin" >> "$FOUND_FILE"
fi
find "$godir" -maxdepth 2 -type d -name "bin" -prune -print 2>/dev/null | while IFS= read -r b; do
if [[ "$b" != "$godir/bin" ]]; then
echo "$b" >> "$FOUND_FILE"
fi
done
done < <(find "$TARGET" -name "go.mod" -type f 2>/dev/null | head -n 20)
find "$TARGET" \( -type d -name ".git" -prune \) -o -type f -name "*.out" -print 2>/dev/null | head -n 200 >> "$FOUND_FILE" || true
find "$TARGET" \( -type d -name ".git" -prune \) -o -type f -name "*.test" -print 2>/dev/null | head -n 200 >> "$FOUND_FILE" || true
fi
stop_spinner
# Dedup
if [[ ! -s "$FOUND_FILE" ]]; then
echo -e "${GREEN}✨ Sudah bersih! Tidak ada yang perlu dihapus.${NC}"
exit 0
fi
SORTED=$(mktemp /tmp/bersihkan-sorted.XXXXXX)
sort -u "$FOUND_FILE" > "$SORTED"
mv "$SORTED" "$FOUND_FILE"
# ---- Exclude filter ----
if [[ ${#EXCLUDE[@]} -gt 0 ]]; then
FILTERED=$(mktemp /tmp/bersihkan-filtered.XXXXXX)
EXCLUDED_COUNT=0
while IFS= read -r p; do
skip=false
rel="${p#$TARGET/}"
base=$(basename "$p")
for pat in "${EXCLUDE[@]}"; do
# Glob match: coba rel, full path, dan basename
case "$rel" in $pat) skip=true; break ;; esac
case "$p" in $pat) skip=true; break ;; esac
case "$base" in $pat) skip=true; break ;; esac
# Untuk pattern tanpa wildcard seperti "vendor" atau "bin",
# juga match jika ada segment path yang exact
if [[ "$pat" != *"*"* && "$pat" != *"?"* && "$pat" != *"["* ]]; then
if [[ "$rel" == "$pat" ]] || [[ "$rel" == "$pat"/* ]] || [[ "$rel" == */"$pat" ]] || [[ "$rel" == */"$pat"/* ]]; then
skip=true; break
fi
fi
done
if $skip; then
EXCLUDED_COUNT=$((EXCLUDED_COUNT+1))
else
echo "$p" >> "$FILTERED"
fi
done < "$FOUND_FILE"
mv "$FILTERED" "$FOUND_FILE"
if [[ $EXCLUDED_COUNT -gt 0 ]]; then
echo -e "${DIM} → $EXCLUDED_COUNT item di-exclude (${EXCLUDE[*]})${NC}"
fi
if [[ ! -s "$FOUND_FILE" ]]; then
echo -e "${GREEN}✨ Semua item ter-exclude, tidak ada yang dihapus.${NC}"
exit 0
fi
fi
# Sorting
if [[ "$SORT" == "size" ]]; then
echo -e "${DIM}Mengurutkan berdasarkan ukuran (menghitung size, bisa agak lambat)...${NC}"
SIZE_FILE=$(mktemp /tmp/bersihkan-size.XXXXXX)
SIZE_SORTED=$(mktemp /tmp/bersihkan-size-sorted.XXXXXX)
while IFS= read -r p; do
sz=$(du -sk "$p" 2>/dev/null | cut -f1)
sz=${sz:-0}
human=$(du -sh "$p" 2>/dev/null | cut -f1)
human=${human:-0B}
printf "%s\t%s\t%s\n" "$sz" "$human" "$p" >> "$SIZE_FILE"
done < "$FOUND_FILE"
sort -nr -k1,1 "$SIZE_FILE" > "$SIZE_SORTED"
cut -f3 "$SIZE_SORTED" > "$FOUND_FILE"
SIZE_MAP="$SIZE_SORTED"
else
SORTED2=$(mktemp /tmp/bersihkan-sorted2.XXXXXX)
sort -u "$FOUND_FILE" > "$SORTED2"
mv "$SORTED2" "$FOUND_FILE"
SIZE_MAP=""
fi
COUNT=$(wc -l < "$FOUND_FILE" | tr -d ' ')
if [[ "$SORT" == "size" ]]; then
echo -e "${YELLOW}Ditemukan $COUNT item (urut: terbesar dulu):${NC}"
else
echo -e "${YELLOW}Ditemukan $COUNT item (urut: nama A-Z):${NC}"
fi
echo ""
# Tampilkan daftar
if $VERBOSE; then
if [[ "$SORT" == "size" && -n "$SIZE_MAP" && -f "$SIZE_MAP" ]]; then
while IFS=$'\t' read -r sz human p; do
printf " ${DIM}%-8s${NC} %s\n" "$human" "${p#$TARGET/}"
done < "$SIZE_MAP"
else
while IFS= read -r p; do
size=$(du -sh "$p" 2>/dev/null | cut -f1 || echo "")
if [[ -n "$size" ]]; then
printf " ${DIM}%-8s${NC} %s\n" "$size" "${p#$TARGET/}"
else
printf " ${DIM} ... ${NC} %s\n" "${p#$TARGET/}"
fi
done < "$FOUND_FILE"
fi
else
while IFS= read -r p; do
echo " • ${p#$TARGET/}"
done < "$FOUND_FILE"
fi
# Total size
TOTAL=""
if [[ "$SORT" == "size" && -n "${SIZE_FILE:-}" && -f "$SIZE_FILE" ]]; then
TOTAL_KB=$(awk -F'\t' '{s+=$1} END {print s}' "$SIZE_FILE" 2>/dev/null || echo "?")
if [[ "$TOTAL_KB" != "?" && "$TOTAL_KB" =~ ^[0-9]+$ ]]; then
TOTAL=$(du -shc $(cat "$FOUND_FILE") 2>/dev/null | tail -1 | cut -f1 || echo "${TOTAL_KB}K")
else
TOTAL=$(du -shc $(cat "$FOUND_FILE") 2>/dev/null | tail -1 | cut -f1 || echo "?")
fi
elif $VERBOSE; then
if [[ "$COUNT" -gt 50 ]]; then
echo -e " ${DIM}Menghitung total ukuran...${NC}"
fi
TOTAL=$(du -shc $(cat "$FOUND_FILE") 2>/dev/null | tail -1 | cut -f1 || echo "?")
else
if [[ "$COUNT" -gt 80 ]]; then
echo -e " ${DIM}Menghitung total ukuran ($COUNT item, bisa agak lambat)...${NC}"
fi
TOTAL=$(du -shc $(cat "$FOUND_FILE") 2>/dev/null | tail -1 | cut -f1 || echo "?")
fi
if [[ -n "$TOTAL" && "$TOTAL" != "?" ]]; then
echo -e " ${CYAN}Total: $TOTAL${NC} ${DIM}($COUNT item)${NC}"
if ! $VERBOSE && $DRY_RUN; then
echo -e " ${DIM}Tips: pakai -v atau --sort=size untuk lihat ukuran per-item${NC}"
fi
else
echo -e " ${DIM}($COUNT item)${NC}"
fi
rm -f "${SIZE_MAP:-}" 2>/dev/null || true
echo ""
if $DRY_RUN; then
echo -e "${YELLOW}Dry-run selesai. Jalankan tanpa --dry-run untuk menghapus.${NC}"
exit 0
fi
if $AUTO_YES; then
echo -e "${YELLOW}⚠️ Pastikan sudah git push / backup! Segala risiko kehilangan data bukan tanggung jawab kami.${NC}"
else
echo -e "${RED}⚠️ Pastikan sudah git push / backup sebelum melanjutkan!${NC}"
echo -e "${DIM} Segala risiko kehilangan data bukan tanggung jawab kami.${NC}"
echo -ne "${YELLOW}Hapus semua di atas? [y/N] ${NC}"
read -r ans
case "$ans" in
y|Y|yes|YES) ;;
*) echo "Dibatalkan."; exit 0 ;;
esac
fi
echo ""
FAILED=0
DELETED=0
while IFS= read -r p; do
if rm -rf "$p" 2>/dev/null; then
echo -e "${GREEN} ✓${NC} ${p#$TARGET/}"
DELETED=$((DELETED+1))
else
echo -e "${RED} ✗ Gagal: ${p}${NC}"
FAILED=$((FAILED+1))
fi
done < "$FOUND_FILE"
echo ""
if [[ -z "$TOTAL" || "$TOTAL" == "?" ]]; then
TOTAL_MSG="$DELETED item"
else
TOTAL_MSG="$TOTAL"
fi
rm -f "${SIZE_FILE:-}" 2>/dev/null || true
if [[ $FAILED -eq 0 ]]; then
if [[ "$TOTAL_MSG" == "$DELETED item" ]]; then
echo -e "${GREEN}✨ Selesai! $DELETED item dibersihkan${NC}"
else
echo -e "${GREEN}✨ Selesai! $DELETED item dibersihkan ${DIM}($TOTAL_MSG dibebaskan)${NC}"
fi
else
if [[ "$TOTAL_MSG" == "$DELETED item" ]]; then
echo -e "${YELLOW}Selesai dengan $FAILED gagal, $DELETED berhasil.${NC}"
else
echo -e "${YELLOW}Selesai dengan $FAILED gagal, $DELETED berhasil ${DIM}($TOTAL_MSG dibebaskan)${NC}"
fi
fi
name bersihkan
description Hapus node_modules, .next, dist, build, dan cache framework (Next.js, React, Vite, Nuxt, Laravel, Go, Rust, Java, Flutter, Python) secara rekursif. Gunakan saat user ingin membersihkan project, menghemat disk, atau sebelum reinstall dependencies.

bersihkan 🧹

Command global untuk membersihkan artefak build dan cache framework secara rekursif dari folder mana pun.

Kapan Gunakan Skill Ini

Aktifkan skill ini ketika user:

  • Meminta membersihkan node_modules, .next, dist, build, atau cache project
  • Mengeluh disk penuh karena project JS/PHP/Go/Rust/Python
  • Ingin install ulang dependencies (npm install, composer install, cargo build) dari kondisi bersih
  • Menyebut kata kunci: bersihkan, clean, hapus node_modules, bersihkan cache, clean project

Instalasi

One-liner (Recommended)

curl -fsSL https://raw.githubusercontent.com/dankerizer/bersihkan/master/bersihkan -o ~/.local/bin/bersihkan && chmod +x ~/.local/bin/bersihkan

Verifikasi:

bersihkan --help

Jika command not found, tambahkan ke PATH:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
# atau untuk bash:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc

System-wide

sudo curl -fsSL https://raw.githubusercontent.com/dankerizer/bersihkan/master/bersihkan -o /usr/local/bin/bersihkan && sudo chmod +x /usr/local/bin/bersihkan

Yang Dibersihkan (Rekursif)

Kategori Target
JS/Node/React/Next/Nuxt/Vite/Astro node_modules, .next, .nuxt, .output, .vercel, .turbo, out, dist, build, .parcel-cache, .vite, coverage, .nyc_output, .cache
Laravel/PHP bootstrap/cache/*.php, storage/framework/views/*, storage/framework/cache/data/*, storage/framework/sessions/*, storage/logs/*.log (+ vendor/ jika --vendor)
Go bin/ (jika ada go.mod), vendor/ (jika --vendor), *.out, *.test
Rust target/
Java/Kotlin target/, build/, .gradle/, out/
Flutter/Dart .dart_tool/, build/
Terraform .terraform/
Python __pycache__, .pytest_cache, .mypy_cache, .ruff_cache, .tox
Umum .DS_Store, Pods/, _build/

Cara Pakai

bersihkan                                  # urut nama A-Z (default)
bersihkan --sort=size                      # urut ukuran terbesar dulu
bersihkan -e vendor -e bin                 # jangan hapus vendor & bin
bersihkan --exclude="*.log" --dry-run      # jangan hapus *.log
bersihkan -e ".next" -e "dist" -y          # kecualikan .next & dist
bersihkan --vendor -y                      # termasuk hapus vendor/
bersihkan --help                           # bantuan lengkap

Opsi

PATH              Folder target (default: ".")
-n, --dry-run     Preview saja
-v, --verbose     Tampilkan ukuran tiap item (lebih lambat)
    --vendor      Juga hapus vendor/
    --sort <mode> Urutan: name (default, A-Z) | size (terbesar dulu)
-e, --exclude <pat> Kecualikan folder/file/ekstensi (bisa berulang)
                  Contoh: -e vendor -e "*.log" -e "bin"
-y, --yes         Skip konfirmasi
-h, --help        Bantuan

Contoh Workflow Agent

Ketika user minta bersihkan project, agent harus:

  1. Cek dulu dengan dry-run:

    bersihkan . --dry-run -v
    # atau exclude yang tidak mau dihapus:
    bersihkan . --dry-run -e vendor
  2. Konfirmasi ke user total ukuran & jumlah item yang akan dihapus

  3. Eksekusi jika user setuju:

    bersihkan -y
    # atau dengan vendor jika Laravel/Go:
    bersihkan --vendor -y
    # atau exclude:
    bersihkan -e ".next" -y
  4. Laporkan hasil (berapa item & ukuran dibebaskan)

Contoh Output

🧹 bersihkan → /Users/hadie/Projects
  Exclude: vendor
  → 1 item di-exclude (vendor)
Ditemukan 7 item (urut: nama A-Z):

  • my-app/node_modules
  • my-app/.next
  • api/dist

  Total: 1.2G (7 item)

Hapus semua di atas? [y/N] y

  ✓ my-app/node_modules
  ✓ my-app/.next
✨ Selesai! 7 item dibersihkan (1.2G dibebaskan)

Uninstall

rm ~/.local/bin/bersihkan
# atau system-wide:
sudo rm /usr/local/bin/bersihkan

⚠️ Disclaimer

Harap pastikan dan/atau push ke git terlebih dahulu sebelum mengkonfirmasi. Segala risiko kehilangan data tidak menjadi tanggung jawab kami. Selalu gunakan --dry-run untuk memeriksa. Tindakan bersifat permanen (rm -rf).

Catatan

  • Script compatible dengan bash 3.2 (macOS default) dan zsh
  • Cari secara rekursif dengan find + -prune (skip .git & tidak masuk ke node_modules) - aman untuk monorepo
  • Live spinner selama scan + --exclude untuk fleksibilitas
  • --sort=size otomatis aktifkan verbose & hitung size (lebih lambat tapi urut akurat)
  • Selalu gunakan --dry-run dulu sebelum hapus di project penting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment