Skip to content
Back to skills

Disk Reclaim

BSecurity

Free disk space safely when Kookr refuses task launches with "Data-directory disk free is critical" (HTTP 503, code data_directory_disk_critical), when a command fails with ENOSPC or "No space left on device", or when the operator asks to free disk space or the machine is low on disk. Classifies space into SAFE (reclaimed automatically), REVIEW (needs an operator yes) and NEVER, so nobody deletes a worktree blindly or hunts for space by hand.

  • 5 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 12, 2026
developmentrustgonoderailsdockergitapi

Works with

  • api

Security analysis

B77/100
  • highPerforms destructive filesystem operations
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 3 files and shows the line behind each finding

Scanned November 12, 2026

npx -y skills add kookr-ai/kookr --skill disk-reclaim --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Disk Reclaim?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Disk Reclaim
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/kookr-ai-disk-reclaim/badge)](https://www.skillsdirectory.com/skills/kookr-ai-disk-reclaim)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: disk-reclaim
group: agent-automation
description: >
  Free disk space safely when Kookr refuses task launches with "Data-directory
  disk free is critical" (HTTP 503, code data_directory_disk_critical), when a
  command fails with ENOSPC or "No space left on device", or when the operator
  asks to free disk space or the machine is low on disk. Classifies space into
  SAFE (reclaimed automatically), REVIEW (needs an operator yes) and NEVER, so
  nobody deletes a worktree blindly or hunts for space by hand.
keywords: >
  disk full, ENOSPC, no space left on device, low disk, free disk space,
  data_directory_disk_critical, disk critical 503, worktree cleanup,
  node_modules cleanup, reclaim space, kookr maintenance prune
related: [asking-the-operator]
---

# Disk reclaim

Kookr refuses every task launch once the data directory's filesystem is at or
below 5% free or 2 GiB free (override: `KOOKR_ADMISSION_DATA_DIR_FREE_PERCENT`,
`KOOKR_ADMISSION_DATA_DIR_FREE_BYTES`). `kookr maintenance prune` alone frees
about 1 GB. The bulk is usually git worktrees and `node_modules` under the
operator's code directory (for example `~/git`). Worktrees may hold unmerged
work, so they cannot be deleted blindly. This skill's script sorts space by
safety: it reclaims the provably safe part itself and hands the risky rest to
the operator with sizes. A first real run freed tens of GiB in one pass; it also
held back merged, clean worktrees that contained ignored result files.

The script is `disk-reclaim.mjs` in this skill's `scripts/` directory (Node 20+,
Linux and macOS, no dependencies). The commands below call it through
`${CLAUDE_SKILL_DIR}`.

## Workflow

1. **Report (deletes nothing).**
   `node "${CLAUDE_SKILL_DIR}/scripts/disk-reclaim.mjs" --roots ~/git --data-dir ~/.kookr`
   It prints the filesystem view (free space, Kookr's floors, whether each root
   shares the data directory's filesystem), per-tier totals, and the top
   candidates. Add `--json` for machine-readable output. A scan of about 1,000
   directories takes a couple of minutes. Add `--fetch` to run
   `git fetch --prune` per repo first so "merged upstream" is current. It needs
   the network and **mutates remote-tracking refs** (updates and deletes them).
2. **Apply the SAFE tier.**
   `node "${CLAUDE_SKILL_DIR}/scripts/disk-reclaim.mjs" --roots ~/git --data-dir ~/.kookr --apply safe`
   It works biggest item first, re-checks each item right before acting, and
   stops once free space reaches `--until-free-percent` (default 10) or SAFE is
   exhausted. Each action is logged to `<data-dir>/disk-reclaim.log` (JSONL) as an
   `intent` line before it runs and an `outcome` line after; if the intent
   cannot be written, the apply aborts without deleting anything more.
3. **Re-check free space.** The apply summary shows free space before and
   after. If it is comfortably above the floor, stop and tell the operator what
   was freed.
4. **Present the REVIEW tier** if more space is needed: sizes, paths and the
   reason each item is not safe (dirty, unmerged, unpushed, stashed, in use,
   main checkout, large home directory). Interactive session: use
   `AskUserQuestion`. Unattended Kookr task: use the `asking-the-operator`
   skill (`kookr ask`). Offer the largest items as concrete options.
5. **Delete a REVIEW item only after an explicit operator yes for that item.**
   The script never deletes REVIEW items; do it by hand with the narrowest
   command (for a worktree, `git worktree remove <path>` from its main repo,
   without `--force` unless the operator accepts losing the uncommitted work).

## What each tier means

| Tier | Items | Action |
|---|---|---|
| SAFE worktree | Linked worktree, clean, unlocked, no stash entries, no edits hidden by skip-worktree or assume-unchanged, no untracked paths, no git operation in progress (rebase, merge, cherry-pick, revert, bisect), no git clean filter (other than LFS) applying to its files, as `git check-attr` resolves them, because a filter makes `git status` blind to working-copy-only content, no commit that only its reflogs or `ORIG_HEAD` still point at (on no branch, tag or remote, e.g. after `reset --hard`), HEAD merged into `origin/HEAD` (or its upstream is exactly `[gone]`), idle at least `--min-idle-days` (default 2), not in use, and EVERY git-ignored entry is either a `node_modules/` (with `package.json` and a lockfile in its parent directory and no nested `.git` inside) or a tool cache (`__pycache__/`, `.pytest_cache/`, `.mypy_cache/`, `.ruff_cache/`, `.turbo/`, `.next/cache/`, `.eslintcache`, `*.tsbuildinfo`). Ignored `out/`, `build/`, `dist/`, `target/`, `.cache/`, `coverage/`, `.venv/` and the like are content, not cache | `git worktree remove` from the main repo, then `git branch -d` (never `-D`) |
| SAFE dependencies | Untracked top-level `node_modules` of an idle, unused checkout, with a `package.json` and a lockfile beside it and no nested `.git` inside (a worktree held back by other ignored content can still lose its `node_modules`) | Remove the directory; rebuild with `pnpm install` or `npm ci` |
| SAFE tool caches | pnpm store, npm, uv, pip caches (only installed tools), only while no Kookr task is live and no package manager is running | The tool's own prune/clean command |
| SAFE Kookr data | Aged artifacts under the data dir | `kookr maintenance prune` with the default ages |
| REVIEW | Everything else at least 500 MB, the lowered-age prune (deletes up to ~29 days of finished-task history the default policy keeps; the report prints the exact command and extra size), plus large directories outside the roots (`~/.ollama`, big `~/.cache` entries, other `~/.nvm` Node versions, `~/.rustup/toolchains`, `~/.local/share`) and reclaimable Docker data | Report only |
| NEVER | The data dir (except through `kookr maintenance prune`), `~/.ssh`, `~/.config`, anything outside the roots | Not scanned or touched |

"In use" means a process has its working directory inside the directory, or a
live Kookr task has its `cwd` or any session `cwd` there. Live means not
completed, cancelled or terminated, or terminated for a reason crash recovery
relaunches (`server-restart`, `oom`, `timeout`, `unknown`) within 7 days. The API
port must match the data dir (`~/.kookr` is 4800, `~/.kookr-<port>` is
`<port>`; `KOOKR_PORT` or `KOOKR_API_BASE_URL` must agree). A process or task
whose cwd is an ancestor of the item counts too, but only when that ancestor is
a git repo or worktree root, not a plain container such as `~/git`. Open files
are NOT checked: an editor or tool holding a file open without a cwd there is
not detected. If the API, the
port match or the process probe fails, in-use state is unknown and NOTHING is
SAFE, caches and Kookr data included: tell the operator and fix the probe.

## Guardrails

- Run the report first, every time. Never pass `--apply` without having read
  the report in this session.
- Never delete REVIEW items without an explicit operator yes, and never use
  `git worktree remove --force`, `git branch -D` or `rm -rf` on a path the
  script did not classify SAFE in the same run.
- Ignored files are part of what a worktree removal deletes (`git worktree
  remove` takes git-ignored content with it). A worktree holding ignored files
  other than a verified `node_modules` or a named tool cache (`dist/`, `build/` and `out/` count as content) is
  REVIEW, even if merged and clean. Edits hidden by skip-worktree or
  assume-unchanged also make it REVIEW.
- Only space on the data directory's filesystem helps. Items on another
  filesystem are listed separately and are not applied.
- Removing a worktree keeps its branch unless the branch is merged, so commits
  are not lost; a squash-merged branch stays until deleted by hand.
- Do not "free space" by killing processes or deleting files under `~/.kookr`
  by hand; use `kookr maintenance prune` (the script does).
- The script refuses `--roots` that are `/`, the home directory, the data
  directory, or contain `~/.ssh` or `~/.config`.

## Platform notes

- **Docker Desktop (WSL or macOS):** images and volumes live in Docker
  Desktop's own VM disk. `docker system prune` does not free the Linux or
  macOS filesystem (measured: 6.2 GB pruned, root free space unchanged). The
  script says so and does not offer Docker as a lever. With plain Docker Engine
  it lists `docker system df` reclaimable amounts as REVIEW and never prunes.
- **WSL:** freed space inside the Linux filesystem does not shrink the Windows
  `ext4.vhdx` file; it only restores free space the Linux side sees, which is
  what Kookr measures.
- **pnpm:** `node_modules` entries are hard links into the shared pnpm store.
  Removing them frees little until the store is pruned, which the script runs
  last. Trust the free-space delta in the summary over the estimated sizes.
- **macOS:** process probing uses `lsof -d cwd` (Linux reads `/proc/*/cwd`);
  sizes use `du -k` and `df -Pk`, which behave the same on BSD.

Files in this skill

  • SKILL.md8.8 KB
  • scripts/disk-reclaim.mjs54.3 KB
  • scripts/disk-reclaim.test.mjs39.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in development →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.