转:https://www.reddit.com/r/ClaudeAI/comments/1r2snly/cleanup_sc...
我每天使用Claude Code大约一个月,注意到我的 ~/.claude 目录占了1.3GB。没有自动清理,会议数据不断堆积。
空间去哪儿了?
du -sh ~/.claude/*/ | sort -rh| 目录 | 大小 | 存储内容 |
|---|---|---|
projects/ | 1.0 GB | 会话日志(UUID.jsonl + UUID目录) 会话日志(UUID.jsonl + UUID 目录) |
debug/ | 145 MB | 调试日志 |
shell-snapshots/ | 83 MB | Shell环境快照 |
file-history/ | 23 MB | 文件编辑历史(撤消) |
todos/ | 8.6 MB | 每会话TODO文件 |
plans/ | 1.3 MB | 计划模式输出 |
| 其他 | ~800 KB | 任务、粘贴缓存、图片缓存、安全警告状态_*.json |
最大的罪魁祸首是 projects/。每次会话创建一个 UUID.jsonl (完整对话日志)和一个 UUID/ 目录(子代理输出,计划文件)。这些用于 claude --resume <session-id> ,但你很少会重新启动超过一周的会话。
重要:不要碰 memory/
在每个项目目录中,有一个 memory/ 文件夹,包含 MEMORY.md ——这是Claude Code在会话间的持久记忆。删除它你将失去该项目的所有学习上下文。
脚本
我写了一个清理脚本,带有以下安全功能:
- 默认干运行——除非你传递
--execute,否则不会删除任何内容 - 双重保护——检查目录名称和UUID模式
- 可配置年龄——默认为7天,传递任何数字以更改
保存到 ~/.claude/scripts/cleanup-sessions.sh:
#!/bin/bash
set -euo pipefail
CLAUDE_DIR="$HOME/.claude"
PROJECTS_DIR="$CLAUDE_DIR/projects"
MAX_AGE_DAYS=7
DRY_RUN=true
numfmt_bytes() {
local bytes=$1
if [ "$bytes" -ge 1073741824 ]; then
printf "%.1f GB" "$(echo "$bytes / 1073741824" | bc -l)"
elif [ "$bytes" -ge 1048576 ]; then
printf "%.1f MB" "$(echo "$bytes / 1048576" | bc -l)"
elif [ "$bytes" -ge 1024 ]; then
printf "%.1f KB" "$(echo "$bytes / 1024" | bc -l)"
else
printf "%d B" "$bytes"
fi
}
cleanup_files() {
local dir="$1" pattern="$2" label="$3"
local count=0 bytes=0
[ -d "$dir" ] || return 0
while IFS= read -r -d '' file; do
local size
size=$(stat -f%z "$file" 2>/dev/null || echo 0)
bytes=$((bytes + size))
count=$((count + 1))
$DRY_RUN || rm -f "$file"
done < <(find "$dir" -maxdepth 1 -name "$pattern" -type f -mtime +"$MAX_AGE_DAYS" -print0)
if [ "$count" -gt 0 ]; then
echo " $label: ${count} 个文件 ($(numfmt_bytes "$bytes"))"
total_files=$((total_files + count))
total_bytes=$((total_bytes + bytes))
fi
}
cleanup_dir_contents() {
local dir="$1" label="$2"
local count=0 bytes=0
[ -d "$dir" ] || return 0
while IFS= read -r -d '' file; do
local size
size=$(stat -f%z "$file" 2>/dev/null || echo 0)
bytes=$((bytes + size))
count=$((count + 1))
$DRY_RUN || rm -f "$file"
done < <(find "$dir" -type f -mtime +"$MAX_AGE_DAYS" -print0)
if [ "$count" -gt 0 ]; then
echo " $label: ${count} 个文件 ($(numfmt_bytes "$bytes"))"
total_files=$((total_files + count))
total_bytes=$((total_bytes + bytes))
fi
}
for arg in "$@"; do
[[ "$arg" == "--execute" ]] && DRY_RUN=false
[[ "$arg" =~ ^[0-9]+$ ]] && MAX_AGE_DAYS="$arg"
done
$DRY_RUN && echo "=== 干运行(添加 --execute 以实际删除) ===" \
|| echo "=== 执行模式 ==="
echo "目标:超过${MAX_AGE_DAYS}天的文件"
echo ""
total_files=0
total_dirs=0
total_bytes=0
echo "[项目/会话日志]"
for project_dir in "$PROJECTS_DIR"/*/; do
[ -d "$project_dir" ] || continue
project_name=$(basename "$project_dir")
project_files=0 project_dirs=0 project_bytes=0
while IFS= read -r -d '' file; do
size=$(stat -f%z "$file" 2>/dev/null || echo 0)
project_bytes=$((project_bytes + size))
project_files=$((project_files + 1))
$DRY_RUN || rm -f "$file"
done < <(find "$project_dir" -maxdepth 1 -name "*.jsonl" -type f -mtime +"$MAX_AGE_DAYS" -print0)
while IFS= read -r -d '' dir; do
dirname=$(basename "$dir")
[[ "$dirname" == "memory" ]] && continue
if [[ "$dirname" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]]; then
size=$(du -sk "$dir" 2>/dev/null | cut -f1)
project_bytes=$((project_bytes + size * 1024))
project_dirs=$((project_dirs + 1))
$DRY_RUN || rm -rf "$dir"
fi
done < <(find "$project_dir" -maxdepth 1 -type d -mtime +"$MAX_AGE_DAYS" -not -path "$project_dir" -print0)
if [ $((project_files + project_dirs)) -gt 0 ]; then
echo " $project_name: ${project_files} 个文件, ${project_dirs} 个目录 ($(numfmt_bytes $project_bytes))"
total_files=$((total_files + project_files))
total_dirs=$((total_dirs + project_dirs))
total_bytes=$((total_bytes + project_bytes))
fi
done
echo ""
echo "[其他临时数据]"
cleanup_dir_contents "$CLAUDE_DIR/debug" "调试/"
cleanup_dir_contents "$CLAUDE_DIR/shell-snapshots" "shell快照/"
cleanup_dir_contents "$CLAUDE_DIR/file-history" "文件历史/"
cleanup_dir_contents "$CLAUDE_DIR/todos" "待办事项/"
cleanup_dir_contents "$CLAUDE_DIR/plans" "计划/"
cleanup_dir_contents "$CLAUDE_DIR/tasks" "任务/"
cleanup_dir_contents "$CLAUDE_DIR/paste-cache" "粘贴缓存/"
cleanup_dir_contents "$CLAUDE_DIR/image-cache" "图片缓存/"
cleanup_files "$CLAUDE_DIR" "security_warnings_state_*.json" "安全警告状态"
echo ""
echo "--- 摘要 ---"
echo "文件: ${total_files}"
echo "目录: ${total_dirs} (UUID会话)"
echo "节省空间: $(numfmt_bytes $total_bytes)"
$DRY_RUN && [ $((total_files + total_dirs)) -gt 0 ] && echo "" && echo "要删除: $0 ${MAX_AGE_DAYS} --execute"用法
chmod +x ~/.claude/scripts/cleanup-sessions.sh
# 干运行(默认,不删除任何东西)
~/.claude/scripts/cleanup-sessions.sh
# 将年龄阈值更改为14天
~/.claude/scripts/cleanup-sessions.sh 14
# 实际删除
~/.claude/scripts/cleanup-sessions.sh 7 --execute我在4周后的结果
文件: 6,806
目录: 246 (UUID会话)
节省空间: 1.3 GB你绝对不应该清理的文件
| 路径 | 原因 |
|---|---|
projects/*/memory/ | 持久记忆(MEMORY.md) |
CLAUDE.md | 全局指令 |
settings.json | 用户设置 |
commands/ | 自定义斜杠命令 |
plugins/ | 已安装的插件 |
history.jsonl | 命令历史 |
Linux用户注意
这个脚本使用macOS stat -f%z。在Linux上,替换为 stat --format=%s 或使用 wc -c < "$file" 以实现跨平台兼容性。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。