codex-sweeper is a terminal-only, safety-first inspector and cleaner for Codex local storage, conversations, and runtime state. It uses OpenTUI and classifies each top-level CODEX_HOME path as:
SAFE: safe to keep, or a narrowly verified cleanup candidate.REVIEW: potentially reclaimable, but lifecycle or reference checks are still required.PROTECTED: credentials, configuration, user content, canonical state, and every unknown path.
SAFE does not automatically mean deletable. The TUI separately marks exact items eligible for Safe Clean.
SQLite databases, processes, automations, bulk task history, and unknown paths remain read-only. A separate Conversations surface follows Codex's lifecycle: current conversations can be archived through thread/archive, and only verified archived conversations can be permanently deleted through thread/delete.
Requirements: macOS, Bun, and a working Codex CLI or Codex desktop installation.
bun install
bun run startRegister the global command once, then run it from any directory:
bun link
codex-sweeperTerminal controls:
- Mouse: click a surface tab, summary filter, row, inspector, action, confirmation, or language
Tab: switch between Storage and Conversations↑/↓ork/j: move through the active surface's rows←/→or1–4: switch between all, safe, review, and protectedEnter: expand or collapse the selected entry's detail viewEsc: leave the expanded detail view; press it again to quitc: openSafe Cleanconfirmation/: search conversations by title, Project, Thread ID, directory, or previewa: archive the selected current conversationd: permanently delete the selected archived conversationl: cycle English → 中文 → 日本語r: rescan Storage or reload Conversationsq: quit
Wide terminals use a restrained list-and-inspector split. Below 96 columns, Enter opens the selected item as a full-width detail view and Esc returns to the list, so controls and content do not compete for space.
The first launch uses English. Language changes happen entirely inside the TUI and are remembered in Sweeper's own settings:
- macOS:
~/Library/Application Support/codex-sweeper/settings.json - Linux and other supported environments:
$XDG_CONFIG_HOME/codex-sweeper/settings.jsonor~/.config/codex-sweeper/settings.json
The current allowlist contains exactly one candidate: a top-level regular file at $CODEX_HOME/.DS_Store.
Before offering or performing cleanup, Sweeper requires all of these checks:
- the path is exactly
.DS_Storedirectly inside the resolvedCODEX_HOME - it is a regular file, never a symlink, directory, or special file
lsofsuccessfully verifies that no process has the file open- the user explicitly confirms in the TUI with
yor a mouse click - the file is atomically moved to the macOS Trash and verified after the move
Sweeper never permanently deletes the file and never empties the Trash. If verification is unavailable or ambiguous, cleanup is blocked.
Conversation actions are intentionally separate from Safe Clean. Sweeper enforces Current → Archived → Deleted; it never offers direct deletion for a current conversation.
Before calling Codex's native thread/archive, Sweeper requires a fresh exact identity check, a non-active thread, and a verified regular, non-symlink rollout below $CODEX_HOME/sessions. After the call, it re-reads the thread and verifies the rollout below $CODEX_HOME/archived_sessions. If Codex Desktop still owns the loaded thread and rejects the request, Sweeper leaves the confirmation open with the complete error and asks the user to archive it in Codex Desktop before reloading.
Permanent deletion does not use the system Trash. Before calling Codex's native thread/delete, Sweeper requires all of these checks:
- the user selects one exact archived conversation and explicitly confirms once
- a fresh
thread/readreturns the same full Thread ID and unchanged title - the thread is not active
- its rollout is a regular, non-symlink file inside
$CODEX_HOME/archived_sessions - the rollout filename and first
session_meta.payload.idboth match the selected Thread ID - Codex's own
thread/deletesucceeds and the rollout is verified absent afterward
Sweeper never removes rollout files itself and never writes directly to Codex's SQLite state. If a safety check is unavailable, ambiguous, or fails, the action is blocked. Archive is reversible in Codex; Delete is permanent.
When Codex Project metadata is available, Conversations are grouped under the same Project names used by the Codex desktop app. Sweeper resolves them in this order:
- canonical
projectIdandproject/listdata from Codex app-server - the desktop app's explicit
thread-project-assignments - the longest matching saved Project root for legacy conversations without an assignment
Threads explicitly marked projectless remain under No Project; Sweeper does not infer a Project for them. Project metadata is read-only and is refreshed with the conversation list.
Machine-readable output:
bun run src/index.tsx --json
bun run src/index.tsx --json --codex-home /path/to/.codexJSON mode is always read-only.
Released under the MIT License.
bun run check

