aspect output-basesshows what is there. It changes nothing.aspect gcremoves what nothing is using.
1. See what is there
--measure-sizes for disk usage per base and across the caches they share, or --sort=size to measure and order by it — both walk every file under the output user root, which takes about a minute once there are tens of gigabytes.
Two numbers usually matter:
- Removable bases: orphaned (the workspace was deleted) and idle (unused for 30 days). The listing ends with their count and size.
- Running servers: each holds its memory until it has been idle for Bazel’s
--max_idle_secs(3 hours by default). The line under the census gives the total.
2. Preview
gc would remove and why, the stale download-cache entries, and the total it would free. Nothing is deleted.
3. Reclaim
aspect worktree pool slot it would otherwise call orphaned.
To remove a base the rules keep, such as an undetermined one, name it:
4. Tune the rules
The grace period keeps an orphaned base for an hour after its last use, so a worktree torn down and recreated at the same path gets its base back.
5. Run it on a schedule
gc asks before deleting, and refuses off a terminal unless --force says it may. A nightly cron entry on a developer machine:
gc cannot find counts as gone.
Worktrees and agents
Each worktree is a new workspace path, so each gets its own output base, server andexternal/ tree. Deleting the worktree orphans them; gc removes them an hour after their last use.
aspect worktree avoids that by reusing a pool of slots at fixed paths, each keeping one warm output base for its next lease. Worktrees covers the pool: how warm a slot is, how one is chosen for a branch, and how leases work. Pool slots carry their lease holder in the listing, so you can see which agent has what:
git worktree add. gc does not treat a pool slot’s base as orphaned, though it still removes one idle past --base-max-idle-days; aspect worktree prune deletes slots that have gone stale, base and all.
Starting over
aspect gc --all removes every output base under the root, whatever its state, stopping each one’s Bazel server first, and leaves aspect worktree checkouts, install/ and the download cache’s own rule alone. Every workspace’s next build is then cold. Preview it with --dry-run; see removing every output base.
Scripting
Both tasks take--output=json. For example, the workspaces whose bases gc would remove:
These are AXL tasks
output-bases, gc and worktree never run Bazel. They read its rc chain to resolve --output_user_root the way Bazel would, then work on what is on disk; the only processes they start are git, ps and realpath. They don’t extend the build — they improve the work around it, and they do it in AXL, the same Starlark you already write for Bazel. Ask the CLI where they come from:
@aspect is the extension library the CLI ships; .aspect/ in your repository is another, and a task in either is the same kind of object. So the shell scripts a team accumulates beside its build — the ones everyone has aliased slightly differently — can be tasks instead, written in a language the repository already uses. What you write then shows up in aspect help and aspect describe with typed arguments, which is how a person finds it and how an agent learns to call it.
Writing AXL tasks covers task(), arguments and registration.
