디스크 유틸 — zsh alias와 Claude Skill 두 인터페이스
디스크 사용량 조회·정리 로직을 zsh alias(dh/dgh/dol 등)와 Claude Skill 두 인터페이스로 동시에 노출하는 셋업입니다. 같은 셸 함수가 터미널에서는 짧은 alias로, 에이전트 안에서는 자연어 호출로 사용됩니다. 이 글에서는 인터페이스 분리 원칙, 두 표현의 차이, 코드 공유 구조, 그리고 stale-while-revalidate 적용을 정리합니다.
두 인터페이스가 같은 로직을 공유한다
disk_utils.zsh는 ~/.oh-my-zsh/custom/에 위치하는 472줄짜리 zsh 스크립트입니다. dh를 치면 disk_home() 함수가 실행되고, "디스크 어디가 문제야"라고 Claude Code에 물으면 disk-manager Skill이 같은 함수 집합을 가리키며 분석을 시작합니다.
두 인터페이스는 표면만 다를 뿐 동일한 함수를 호출합니다. 사람은 alias로 직접 실행하고, 에이전트는 SKILL.md에 기술된 마인드모델과 명령어 목록을 통해 자연어 지시를 구체적인 셸 명령으로 번역합니다. 로직은 한 곳에만 존재하고, 두 방향으로 노출되는 구조입니다.
이 구조의 실질적 이점은 중복 제거입니다. 디스크 분석 방법론을 에이전트용 SKILL.md에 한 번만 기록해두면, "어디가 제일 크냐"는 자연어 질문도, 터미널에서 직접 치는 disks도 동일한 탐색 순서를 따릅니다.
zsh 측 인터페이스
disk_utils.zsh의 alias 목록은 다음과 같습니다.
alias disks='disk_report' # 전체 대시보드 (숫자 선택 메뉴)
alias dh='disk_home' # 홈 디렉토리 주요 항목 (상위 15개)
alias dgh='disk_github' # GitHub 프로젝트별 크기
alias dicl='disk_icloud' # iCloud Drive
alias dcol='disk_colima' # Colima VM — Docker 이미지 + 프로젝트 참조
alias dol='disk_ollama' # Ollama 모델 목록 + 용량
alias das='disk_appsupport' # Library > Application Support
alias dlc='disk_libcache' # Library > Caches
alias dct='disk_cache_tools' # ~/.cache (CLI·개발 도구)
alias ddt='disk_dev_tools' # npm/Bun/nvm/pyenv/Cursor/Gradle/GHCup
alias dml='disk_ml_cache' # HuggingFace/uv/PyTorch/Keras/TensorFlow/pip
alias dcache='disk_clean_cache'
alias dnpm='disk_clean_npm'
alias dref='disk_refresh'
alias ddiff='disk_diff' # 변동 현황 (기본 24h)
alias dhist='disk_hist' # 용량 추이 차트
alias dsnap='disk_snap' # 즉시 스냅샷 촬영disks는 대화형 대시보드입니다. 실행하면 전체 현황과 홈 디렉토리 요약을 보여준 뒤 숫자 메뉴로 진입합니다. 1은 GitHub 프로젝트, 3은 Colima VM, d는 24시간 변동 현황, h는 카테고리별 추이 차트입니다.
조회 함수 대부분은 _get_or_update_cache()를 경유합니다. 결과를 ~/.disk_cache/ 아래 파일에 캐시하고, TTL(6시간) 이내에는 파일을 그대로 읽어 반환합니다. 이 패턴에 대해서는 아래에서 따로 다룹니다.
ddiff와 dhist는 SQLite 기반의 이력 조회입니다. dsnap으로 스냅샷을 찍으면 ~/.disk_cache/disk_history.db에 카테고리별 용량이 기록되고, 이후 ddiff 48(48시간 전 대비)이나 dhist colima 30(30일간 Colima VM 추이)으로 변화를 추적할 수 있습니다. launchd plist(com.jaesolshin.disk-index.plist)가 6시간마다 자동으로 refresh.sh를 실행해 스냅샷을 누적합니다.
dcol은 Colima 실행 여부에 따라 출력이 달라집니다. Colima가 중지 상태면 GitHub 프로젝트의 docker-compose*.yml에서 image: 라인을 긁어 어떤 이미지가 정의돼 있는지 보여줍니다. 실행 중이면 docker system df와 이미지별 프로젝트 참조를 함께 출력합니다.
Claude Skill 측 인터페이스
disk-manager Skill의 description은 다음과 같습니다.
디스크 사용량을 모니터링하고 정리합니다. 대용량 파일 찾기, 폴더별 크기 분석, 캐시 정리, ML 프레임워크 모니터링, Docker 이미지 분석 등에 사용합니다. dust/fd 기반 고속 스캔, stale-while-revalidate 캐싱, launchd 주기적 인덱싱.
Claude Code는 이 description을 보고 디스크 관련 자연어 요청을 이 Skill로 라우팅합니다. 트리거 표현으로는 "디스크가 가득 찼어", "HuggingFace 캐시가 얼마나 돼", "어떤 프로젝트가 제일 크냐" 같은 형태가 해당됩니다.
SKILL.md는 Claude가 따를 탐색 순서를 명시합니다.
1. 전체 현황 파악
df -h | grep /System/Volumes/Data
2. 홈 디렉토리 1단계 드릴다운
du -sh ~/Documents ~/Library ~/Downloads ~/Movies ~/.cache ~/.ollama ~/.colima
3. Library 드릴다운
dust -d 1 -n 15 ~/Library
4. Library/Containers 드릴다운 (함정 구간)
dust -d 1 ~/Library/Containers
5. Colima VM 실제 사용량 확인
du -sh ~/.colima/
6. Docker 이미지 분석
docker images + pull 시점 확인
7. 캐시 분석
~/.cache, ~/Library/Caches 항목별 크기에이전트는 이 순서를 건너뛰지 않도록 안내받습니다. 단계를 임의로 생략하면 "Library/Containers에 Docker Desktop VM이 50GB 이상 잡혀 있는데 눈에 안 띄는" 상황이 생기기 때문입니다.
Skill 측에서는 disk_utils.zsh의 alias를 그대로 호출하기도 하고, dust, fd, docker, ollama 명령을 직접 조합하기도 합니다. "비활성 Python 가상환경 찾아줘"처럼 alias에 대응하는 함수가 없는 요청은 SKILL.md에 정리된 탐지 패턴(fd -t d "^\.?venv$")을 Claude가 직접 실행합니다.
SKILL.md의 또 다른 역할은 삽질 방지 체크리스트입니다. Docker 이미지의 CREATED 날짜가 빌드 시점이라 pull 시점과 다르다는 점, Colima VM 삭제 후 fstrim을 실행해야 실제 공간이 회수된다는 점, Apple Silicon에서 Colima LaunchAgent 경로가 /opt/homebrew/bin/colima여야 한다는 점 등을 주의사항으로 명시해 두었습니다. 에이전트가 이 문서를 컨텍스트로 가져가므로 같은 실수를 반복하지 않습니다.
코드 공유 구조
~/.claude/skills/disk-manager/disk-utils.sh는 Skill 디렉토리 안에 위치하는 별도 스크립트입니다. 초기 버전의 함수 집합이 여기에 담겨 있고, 실제 운영에서 사용하는 함수는 ~/.oh-my-zsh/custom/disk_utils.zsh로 발전했습니다.
두 파일의 관계를 정리하면 다음과 같습니다.
disk-utils.sh |
disk_utils.zsh |
|
|---|---|---|
| 위치 | ~/.claude/skills/disk-manager/ |
~/.oh-my-zsh/custom/ |
| 역할 | Skill 번들 동봉 스크립트 | 실제 운영 중인 zsh 플러그인 |
| 캐시 전략 | TTL 내에는 캐시 반환, 만료 시 동기 갱신 | stale-while-revalidate (즉시 반환 + 백그라운드 갱신) |
| 이력 추적 | 없음 | SQLite (disk_history.db) |
| 커버리지 | 홈/Library/Documents/Movies | GitHub/iCloud/Colima/Ollama/ML/개발 도구 등 확장 |
disk_utils.zsh가 정식 버전입니다. SKILL.md는 이 파일을 "스크립트 위치: ~/.oh-my-zsh/custom/disk_utils.zsh"로 명시하고, 에이전트가 alias를 호출할 때도 이쪽 함수가 실행됩니다. disk-utils.sh는 Skill을 다른 환경에 이식하거나 에이전트가 직접 소스하는 용도로 번들된 상태입니다.
두 파일이 공유하는 핵심 개념은 _cache_valid()로 TTL을 판단하는 방식, ~/.disk_cache/를 캐시 저장소로 사용하는 경로 규칙, 급격한 공간 변화를 _check_space_change()로 감지해 캐시를 강제 무효화하는 로직입니다.
stale-while-revalidate를 셸에 적용한다
disk_utils.zsh의 핵심 설계 결정 중 하나는 _get_or_update_cache()의 동작 방식입니다.
_get_or_update_cache() {
local cache_file="$1"
local cmd="$2"
if [[ -f "$cache_file" ]]; then
cat "$cache_file"
if ! _cache_valid "$cache_file"; then
(eval "$cmd" > "${cache_file}.tmp" && mv "${cache_file}.tmp" "$cache_file") &!
fi
else
eval "$cmd" | tee "$cache_file"
fi
}파일이 존재하면 TTL 만료 여부와 무관하게 즉시 캐시를 반환합니다. TTL이 지났으면 백그라운드(&!)에서 갱신 명령을 실행합니다. 파일 자체가 없을 때만 동기적으로 실행해서 결과를 기다립니다.
이것이 stale-while-revalidate 패턴입니다. 웹에서는 CDN이나 서비스 워커가 캐시된 응답을 먼저 보내고 백그라운드에서 최신 버전을 가져오는 방식으로 동일한 개념을 구현합니다. dh를 실행했을 때 dust가 홈 디렉토리 전체를 스캔하는 수 초를 기다리지 않아도 되는 이유가 이 구조 때문입니다.
초기 버전(disk-utils.sh)에서는 TTL 내에는 캐시를 반환하고 만료되면 동기적으로 재실행했습니다. 응답은 항상 최신이지만, 만료 시점에 터미널이 멈추는 문제가 있었습니다. disk_utils.zsh에서 stale-while-revalidate로 전환하면서 응답 지연이 거의 사라졌습니다.
TTL은 CACHE_TTL=21600(6시간)으로 설정되어 있습니다. 캐시 파일은 ~/.disk_cache/ 아래에 이름별로 저장됩니다.
~/.disk_cache/
home_usage
github_usage
icloud_usage
appsupport_usage
libcache_usage
cache_tools_usage
.last_used_space # 급변 감지용 마지막 사용량
disk_history.db # SQLite 이력
refresh.sh # launchd가 호출하는 스냅샷 스크립트급변 감지는 별도 경로입니다. _check_space_change()는 dh 실행 시마다 현재 사용량을 df로 빠르게 조회하고 .last_used_space에 저장된 이전값과 비교합니다. 차이가 SPACE_THRESHOLD_MB=5120(5GB)을 초과하면 stale 데이터를 반환하지 않고 캐시 파일을 즉시 삭제합니다. 다음 조회 때 동기적으로 새 데이터를 수집합니다.
_invalidate_cache() {
for f in "$CACHE_DIR"/{home,github,icloud,appsupport,libcache,cache_tools}_usage; do
rm -f "$f"
done
}stale-while-revalidate가 "최신성보다 응답 속도 우선"이라면, 급변 감지는 그 예외 조건입니다. 디스크가 5GB 이상 빠르게 줄거나 늘었다면 stale 데이터를 보여주는 비용이 너무 크다고 판단해 동기 갱신으로 전환합니다.
운영상 주의
캐시 신뢰 범위. dh가 보여주는 수치는 캐시 파일 기준입니다. TTL 6시간 이내에 대용량 파일을 내려받거나 삭제했다면 실제값과 다를 수 있습니다. 급변 감지(5GB 임계값)가 잡아주지 못하는 경우에는 dref로 캐시를 수동 무효화하거나 du -sh <디렉토리>를 직접 실행합니다.
두 alias 집합의 차이. disk-utils.sh와 disk_utils.zsh의 alias가 일부 다릅니다. disk-utils.sh의 dl은 disk_library에, dd는 disk_documents에 매핑됩니다. disk_utils.zsh에는 dl alias가 없고 dgh, dicl, dcol, das, dlc, dct가 추가되어 있습니다. 두 파일을 모두 소스하면 alias 충돌이 생깁니다. zsh 플러그인으로는 disk_utils.zsh만 소스하는 것이 의도된 사용법입니다.
Claude Skill 등록. ~/.claude/skills/disk-manager/SKILL.md가 있으면 Claude Code가 자동으로 감지합니다. 별도 등록 절차는 없습니다. Skill이 alias를 호출하려면 해당 터미널 세션에서 disk_utils.zsh가 소스된 상태여야 합니다. ~/.zshrc에 source ~/.oh-my-zsh/custom/disk_utils.zsh가 포함되어 있지 않으면 에이전트가 dh를 실행해도 command not found가 납니다. Claude Code가 셸 환경을 상속받는 방식에 따라 다르므로, 에이전트가 alias 대신 zsh ~/.oh-my-zsh/custom/disk_utils.zsh && dh 형태로 소스 후 호출하는 패턴이 더 안정적입니다.
launchd 스냅샷 주기. ddiff와 dhist는 스냅샷 기록이 있어야 동작합니다. dsnap을 한 번 이상 실행하거나 launchd plist가 등록되어 있어야 합니다. 스냅샷이 없는 상태에서 ddiff를 실행하면 "[INFO] 아직 스냅샷 기록이 없습니다" 메시지만 출력됩니다. DB 보관 기간은 90일입니다.
Docker 정리 후 fstrim. dcol이나 SKILL.md의 Docker 정리 안내를 따라 이미지·볼륨을 삭제한 뒤에는 Colima VM 안에서 fstrim을 실행해야 macOS 파일시스템에 공간이 실제로 반환됩니다.
colima ssh -- sudo fstrim -av삭제 전후로 diskutil info / | grep "Container Free Space"를 비교해 실제 회수량을 확인합니다.
참고
~/.oh-my-zsh/custom/disk_utils.zsh— zsh 플러그인 본체~/.claude/skills/disk-manager/SKILL.md— Claude Skill 정의~/.disk_cache/— 캐시 저장소 및 SQLite 이력 DB~/Library/LaunchAgents/com.jaesolshin.disk-index.plist— 6시간 주기 자동 스냅샷