add runtime empty-directory cleanup command
This commit is contained in:
@@ -73,6 +73,14 @@ Prune migrated legacy backups from runtime folders (dry-run by default):
|
||||
~/.mosaic/bin/mosaic-prune-legacy-runtime --runtime claude --apply
|
||||
```
|
||||
|
||||
Clean empty legacy runtime directories:
|
||||
|
||||
```bash
|
||||
~/.mosaic/bin/mosaic-clean-runtime --runtime claude
|
||||
~/.mosaic/bin/mosaic-clean-runtime --runtime claude --apply
|
||||
~/.mosaic/bin/mosaic-clean-runtime --runtime claude --all-empty --apply
|
||||
```
|
||||
|
||||
Audit runtime drift:
|
||||
|
||||
```bash
|
||||
|
||||
147
bin/mosaic-clean-runtime
Executable file
147
bin/mosaic-clean-runtime
Executable file
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
RUNTIME="claude"
|
||||
APPLY=0
|
||||
ALL_EMPTY=0
|
||||
|
||||
usage() {
|
||||
cat <<USAGE
|
||||
Usage: $(basename "$0") [options]
|
||||
|
||||
Remove empty runtime directories created by migration/drift.
|
||||
Default mode only checks managed legacy surfaces. Use --all-empty for broader cleanup.
|
||||
|
||||
Options:
|
||||
--runtime <name> Runtime to clean (default: claude)
|
||||
--all-empty Scan all runtime directories (except protected paths)
|
||||
--apply Perform deletions (default: dry-run)
|
||||
-h, --help Show help
|
||||
USAGE
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--runtime)
|
||||
[[ $# -lt 2 ]] && { echo "Missing value for --runtime" >&2; exit 1; }
|
||||
RUNTIME="$2"
|
||||
shift 2
|
||||
;;
|
||||
--all-empty)
|
||||
ALL_EMPTY=1
|
||||
shift
|
||||
;;
|
||||
--apply)
|
||||
APPLY=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$RUNTIME" in
|
||||
claude)
|
||||
TARGET_ROOT="$HOME/.claude"
|
||||
managed_roots=(
|
||||
"$HOME/.claude/agent-guides"
|
||||
"$HOME/.claude/scripts"
|
||||
"$HOME/.claude/templates"
|
||||
"$HOME/.claude/presets"
|
||||
"$HOME/.claude/skills"
|
||||
"$HOME/.claude/agents"
|
||||
"$HOME/.claude/agents.bak"
|
||||
)
|
||||
protected_roots=(
|
||||
"$HOME/.claude/.git"
|
||||
"$HOME/.claude/debug"
|
||||
"$HOME/.claude/file-history"
|
||||
"$HOME/.claude/projects"
|
||||
"$HOME/.claude/session-env"
|
||||
"$HOME/.claude/tasks"
|
||||
"$HOME/.claude/todos"
|
||||
"$HOME/.claude/plugins"
|
||||
"$HOME/.claude/statsig"
|
||||
"$HOME/.claude/logs"
|
||||
"$HOME/.claude/shell-snapshots"
|
||||
"$HOME/.claude/paste-cache"
|
||||
"$HOME/.claude/plans"
|
||||
"$HOME/.claude/ide"
|
||||
"$HOME/.claude/cache"
|
||||
)
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported runtime: $RUNTIME" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ -d "$TARGET_ROOT" ]] || { echo "[mosaic-clean] Runtime dir missing: $TARGET_ROOT" >&2; exit 1; }
|
||||
|
||||
is_protected() {
|
||||
local path="$1"
|
||||
for p in "${protected_roots[@]}"; do
|
||||
[[ -e "$p" ]] || continue
|
||||
case "$path" in
|
||||
"$p"|"$p"/*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
collect_empty_dirs() {
|
||||
if [[ $ALL_EMPTY -eq 1 ]]; then
|
||||
find "$TARGET_ROOT" -depth -type d -empty
|
||||
else
|
||||
for r in "${managed_roots[@]}"; do
|
||||
[[ -d "$r" ]] || continue
|
||||
find "$r" -depth -type d -empty
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
count_candidates=0
|
||||
count_deletable=0
|
||||
|
||||
while IFS= read -r d; do
|
||||
[[ -n "$d" ]] || continue
|
||||
|
||||
count_candidates=$((count_candidates + 1))
|
||||
|
||||
# Never remove runtime root.
|
||||
[[ "$d" == "$TARGET_ROOT" ]] && continue
|
||||
|
||||
if is_protected "$d"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
count_deletable=$((count_deletable + 1))
|
||||
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
rmdir "$d" 2>/dev/null || true
|
||||
if [[ ! -d "$d" ]]; then
|
||||
echo "[mosaic-clean] deleted: $d"
|
||||
fi
|
||||
else
|
||||
echo "[mosaic-clean] would delete: $d"
|
||||
fi
|
||||
done < <(collect_empty_dirs | sort -u)
|
||||
|
||||
mode="managed"
|
||||
[[ $ALL_EMPTY -eq 1 ]] && mode="all-empty"
|
||||
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
echo "[mosaic-clean] complete: mode=$mode deleted_or_attempted=$count_deletable candidates=$count_candidates runtime=$RUNTIME"
|
||||
else
|
||||
echo "[mosaic-clean] dry-run: mode=$mode deletable=$count_deletable candidates=$count_candidates runtime=$RUNTIME"
|
||||
echo "[mosaic-clean] re-run with --apply to delete"
|
||||
fi
|
||||
Reference in New Issue
Block a user