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
|
~/.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:
|
Audit runtime drift:
|
||||||
|
|
||||||
```bash
|
```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