Skip to content
Development
Command

/cleanup

Repo/branch/file hygiene sweep — stray artifacts, doc drift, stale branches, worktrees, upstream sync, backup sprawl, duplicate build caches. Verifies before purging.

From plugin
amux
55711 skills11 commands

Command definition

cleanup.md
description: Repo/branch/file hygiene sweep — stray artifacts, doc drift, stale branches, worktrees, upstream sync, backup sprawl, duplicate build caches. Verifies before purging.
allowed-tools: Bash, Read, Edit, Write
argument-hint: [dry-run|full] (default: full)

/cleanup — amux file cleanup & consolidation routine

A repeatable hygiene sweep for this repo and this box's `~/.amux` state. Built from a real cleanup session (2026-08-30) that found: a 37MB binary accidentally committed, a security-sensitive file (`CLAUDE.local.md`) pushed to a public fork, a live systemd script left untracked, a doc file independently drifting in **three** places, 6 stale branches, 2 worktrees for merged PRs, 17 accumulated backup-file generations, and — in a follow-up pass the same day — 5.9GB of pure disk waste: duplicate cargo `target/` dirs in every PR worktree (the shared-target config is gitignored, so worktrees never inherit it) plus stale manual binary backups nobody cleaned up. None of that was hypothetical — every category below is something that actually happened here, not a theoretical checklist.

**Golden rule, stated explicitly because it was tested and mattered:** verify before you purge. "Looks like a duplicate" and "confirmed byte-for-byte subset with a diff/comm check" are different claims — only act on the second. If a branch or file MIGHT hold unique value, flag it and stop; don't delete on a hunch. (The user's own framing: "old stuff can be purged but always double check.")

---

1. Tracked-file hygiene (repo)

# Find large tracked blobs that don't belong (compiled binaries, dumps)
git ls-files -z | xargs -0 du -b 2>/dev/null | sort -rn | head -20

# Cross-check: does anything live/running depend on a file that's
# UNTRACKED? (systemd ExecStart, cron, launchd plist — the audit trail
# must be real, ethos rule 6)
systemctl --user list-units --all 2>/dev/null | grep -oP '(?<=ExecStart=)\S+' 2>/dev/null
# or: systemctl --user cat <unit> | grep ExecStart
# then: git ls-files <that path> — empty means a fresh clone breaks

**Security check — do this every time, not just when something looks wrong:** grep tracked files for names that match your own "never commit this" conventions (`CLAUDE.local.md`, `*.env`, `*secrets*`, `*credentials*`, anything your `.gitignore` comments call out as sensitive) and confirm `.gitignore` actually covers them:

git ls-files | grep -iE 'local\.md$|\.env$|secret|credential|\.key$|\.pem$'
# for each hit, check: is it supposed to be here?
git check-ignore -v <path>   # empty = NOT ignored, even if it should be

If something sensitive is tracked and already pushed: `git rm --cached` + add to `.gitignore` + commit stops it from being carried forward. That does **not** scrub it from history on a remote it already reached — flag that explicitly and let the human decide about a history rewrite (rewriting a shared/in-review branch is disruptive; not a unilateral call).

**After adding a gitignore entry, verify the COMMIT, not the working tree.** `git show HEAD:.gitignore | tail` — not `tail .gitignore`. Editing the file and reporting "added to .gitignore" without an explicit `git add .gitignore` is a real, repeatable mistake (happened twice in the same session here): the commit only contains what got staged, and a later `git reset --hard` silently drops the uncommitted rest with no error at all. `git status`'s summary line does not catch this when the same pass also has a staged deletion — check the actual diff that's about to be committed (`git diff --cached --stat`), not just that *something* is staged.

**If the human authorizes a history rewrite, scope it to exactly the affected commit range — do not process full history.** `git filter-repo` run without `--refs` restriction processes every reachable commit and can reassign NEW HASHES even to commits whose tree never changed (its default merge-simplification touches the whole graph) — this silently moves the branch's merge-base with `main`, and a locally-clean rewrite can still turn into spurious PR conflicts that have nothing to do with the actual fix. `git filter-branch --index-filter '...' -- <bad-commit>^..HEAD` (note the revision range after `--`) only touches commits in that range; everything before it, including the true shared ancestor with `main`, keeps its original hash. **Verify before pushing, every time:**

# merge-base must be IDENTICAL before and after the rewrite
git merge-base <old-ref> origin/main
git merge-base <rewritten-ref> origin/main
# and a real merge test should show 0 conflicts against the SAME origin/main
# snapshot the old branch was tested against (it may have moved since —
# check git log <old-merge-base>..origin/main for genuinely new, unrelated
# conflicts before blaming the rewrite for something upstream drift caused)
git merge-tree $(git merge-base <rewritten-ref> origin/main) <rewritten-ref> origin/main | grep -c '^<<<<<<<'

Tag the pre-rewrite tip locally (never pushed) before starting, so a wrong rewrite has a clean recovery path.

2. Doc/skill drift

The same fact living in more than one file is checked, not assumed — this codebase's own rule ("never a second copy of the same fact") applies to prose as much as code:

# Any obviously-paired doc files (same basename, different dirs)?
find . -iname "amux.md" -o -iname "README.md" 2>/dev/null | grep -v node_modules
diff <(cat copy1) <(cat copy2)   # if near-identical, consolidate

# Is a user-level copy (~/.claude/commands/, ~/.claude/skills/) shadowing
# a project one for lanes whose CWD isn't this repo? Compare both:
diff ~/.claude/commands/<name>.md .claude/commands/<name>.md

**Fix at the root, not by re-syncing every time:** if two files are supposed to always match, make one a symlink to the other so drift is structurally impossible, not just corrected once. For a *repo* file with a *user-level* fallback (different lanes, different CWDs), there's no symlink across t

Read more
@mixpeek
Ships withamux

The agent control plane: run Claude Code, Codex and Gemini CLI agents in parallel with a shared task board, schedules and usage-limit recovery. Native iPhone, iPad and Mac apps plus a web dashboard. Self-host (Rust + SQLite, Tailscale remote access) or use amux Cloud. MIT + Commons Clause.

Stars on GitHub

Momentum

stars in total
557
Star history of mixpeek/amux on GitHub, a chart by star-history.com

Other commands on amux.

aissue

aissue

Command

Pick up an open issue from the amux issue tracker, mark it doing, work it, and mark it done.

@mixpeek@mixpeekInstall Command
amux-board

amux-board

Command

Use when the user says "add to board", "create a task", or wants to track a todo on the amux kanban board

@mixpeek@mixpeekInstall Command
amux

amux

Command

Use when you need to interact with the amux system — manage board tasks, check sessions/workers, send emails, message via…

@mixpeek@mixpeekInstall Command
bad-guy

bad-guy

Command

Before shipping, play the bad guy: run a fixed checklist of 14 attacks against your OWN app with test accounts and test data,…

@mixpeek@mixpeekInstall Command
chrome-cdp

chrome-cdp

Command

Use when the user asks to interact with a web page, take a screenshot of a site, click or type in Chrome, scrape content, or…

@mixpeek@mixpeekInstall Command
orchestrate

orchestrate

Command

Scaffold and run a closed orchestrator loop that drives an existing MD plan to verified completion.

@mixpeek@mixpeekInstall Command

More commands from other plugins.

build
Auto-invoked

build

Command

Implement tasks incrementally — build, test, verify, commit. Add "auto" to run the whole plan in one approved pass.

@addyosmani@addyosmaniInstall Command