Codex Storage Cleanup
Audit first. Treat conversations and user artifacts as data, not cache. Keep normal cleanup direct; isolate a changed or busy subagent root instead of escalating it into a batch-wide failure.
Safety contract
- Default to read-only audit. Destructive work requires explicit user authorization, but a standing authorization may be used without asking again.
- Never automatically delete main threads, archived threads, generated images, visualizations, attachments, memories, credentials, configuration, installed skills, plugins, packages, or runtimes.
- Resolve every target below the requested CodexHome and refuse reparse points or path escapes.
- Protect active, interrupted, unknown, recent, or potentially reusable tasks. A completed descendant of an active main task is still eligible when its own whole subtree is independently completed and unprotected.
- Back up
state_5.sqlite,goals_1.sqlite, andmemories_1.sqlitewith SQLite online backup outside CodexHome before subagent deletion. Keep the compact manifest and results outside CodexHome. - Use only the actual signed desktop backend selected by a fresh capability preflight and prove one real canary before treating later successful deletions as normal batch work.
- Preserve unrelated user changes.
1. Audit storage
Run the bundled read-only scanner:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\audit_storage.ps1 -CodexHome 'D:\CodexHome'
Report total bytes, top-level sizes, largest files, main/archived conversation totals, safe-cleanup candidates, active processes, and user-artifact totals. Folder age alone never proves that a conversation is disposable.
2. Clean redundant non-conversation data
Plan online-safe targets first:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\cleanup_storage.ps1 -Phase OnlineSafe -CodexHome 'D:\CodexHome'
After authorization, execute only the printed plan:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\cleanup_storage.ps1 -Phase OnlineSafe -CodexHome 'D:\CodexHome' -Execute -ConfirmToken CLEAN_CODEX_STORAGE
Use OfflineSafe only after Codex, ChatGPT, VS Code Codex hosts, and codex.exe are closed:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\cleanup_storage.ps1 -Phase OfflineSafe -CodexHome 'D:\CodexHome'
Never delete the whole .tmp, plugins, packages, .sandbox-bin, skills, or tools directory.
3. Reclaim SQLite free pages
Audit without mutation:
python scripts\maintain_sqlite.py --codex-home 'D:\CodexHome' --database logs_2.sqlite
Run maintenance only while Codex is closed and only with an external backup directory:
python scripts\maintain_sqlite.py --codex-home 'D:\CodexHome' --database logs_2.sqlite --execute --backup-dir 'C:\Codex-maintenance-backups' --confirm-token MAINTAIN_CODEX_SQLITE
Never delete a SQLite main, WAL, or SHM file individually.
4. Clean completed subagents
Use scripts/cleanup_completed_subagents.py for the normal native path. Do not reconstruct an ad-hoc deletion loop.
Inventory and compact live status
First query the global app task list and collaboration agents. The sources must be complete. Build a monotonic protected set: add every active, interrupted, unknown, recent, or potentially reusable main/subagent ID, and never remove an ID during the batch merely because it changes from active to idle.
Run inventory into a new directory outside CodexHome. This command performs the batch-start capability preflight before scanning rollouts:
python scripts\cleanup_completed_subagents.py inventory `
--codex-home 'D:\CodexHome' `
--run-dir 'C:\Codex-cleanup\run-YYYYMMDD-HHMMSS' `
--protect THREAD_ID
Read status-targets.json. Use one target per wait_threads(timeoutMs: 0) call and schedule at most eight independent calls concurrently. A single multi-target call wakes on the first inactive task and does not prove the other targets' status. Do not use read_thread for ordinary status checks; it hydrates unnecessary history. Retry an individual snapshot only when needed. An individual unavailable or changed task becomes an unknown root-local status and is skipped; an unavailable global list/host/source stops the batch.
Write one fresh external status-evidence.json:
{
"schema_version": 1,
"captured_at": "2026-08-11T12:00:00+08:00",
"global_complete": true,
"unavailable_sources": [],
"unavailable_hosts": [],
"protected_ids": ["ACTIVE_OR_UNCERTAIN_ID"],
"threads": {
"SUBAGENT_ID": {
"status": "completed",
"latest_turn_status": "completed",
"host_id": "local"
}
}
}
Only completed/complete is deletion evidence. idle describes the task container and is not a substitute for the latest turn result. Strong subagent evidence, a complete finished subtree, non-archived state, the minimum idle interval, and no protected member are all required.
Back up, canary, continue, and verify
With explicit or standing deletion authorization, run:
python scripts\cleanup_completed_subagents.py run `
--codex-home 'D:\CodexHome' `
--run-dir 'C:\Codex-cleanup\run-YYYYMMDD-HHMMSS' `
--status-evidence 'C:\Codex-cleanup\run-YYYYMMDD-HHMMSS\status-evidence.json' `
--protect THREAD_ID
The runner:
- Reuses a still-fresh batch-start preflight or refreshes it when stale.
- Snapshots exact subtree rows, edge status, rollout path, bytes, and mtime.
- Creates and verifies external SQLite online backups.
- Runs one full preflight immediately before the first native canary and requires the same
condition_key. - Keeps one validated local app-server for the batch. Before each root it checks only the saved condition key, desktop PID, runtime file size/mtime, SQLite schema and migration fingerprint, monotonic protection hash, live subtree, row state, and rollout snapshot.
- Writes a result after every root, prints one compact progress record per ten handled roots, and verifies every successful deletion immediately.
- Verifies deleted rows, spawn edges, rollout files, protected records, and
quick_checkfor state/goals/memories/logs at the end.
If execution is interrupted without an integrity stop, rerun the same command with --resume. Already recorded roots are not repeated. A changed runtime condition or smaller protection set is not accepted for resume.
Failure isolation
| Condition | Action |
|---|---|
| Existing writer lock on any member | Skip that root; continue independent roots |
Exact app-server -32600 “already has an active writer”, with all rows/files still present |
Skip that root; continue |
| Latest status, subtree, protected intersection, row state, rollout path/size/mtime changed | Skip that root; continue |
| Root already fully absent without a prior result | Record a skip; do not count its bytes as reclaimed by this run |
| Partial deletion: only some expected rows/edges/files remain | Stop the whole batch and preserve evidence |
SQLite error or failed quick_check |
Stop the whole batch |
| Global task/collaboration source is incomplete or unavailable | Stop the whole batch |
| Desktop PID, condition key, matched runtime, schema, or migration fingerprint changes | Stop the whole batch |
| Timeout or RPC error other than the exact unchanged active-writer refusal | Stop the whole batch |
Do not turn a root-local refusal into a batch stop. Do not turn an unknown/global integrity condition into a skip.
The normal path never installs compatibility objects. Legacy 0.142.2 recovery is only for an already-existing, exact reviewed partial-deletion incident; read references/subagent-delete-compatibility.md and the referenced machine profiles only when such an incident exists. Never use legacy recovery to start a new canary.
Main and archived conversations remain outside this module even when idle. Deleting them requires a separate, explicitly selected task-ID operation.
5. Codex updates and compatibility
For “does this still work after a Codex update?”, run only the lightweight check:
python scripts\subagent_delete_compat.py preflight --codex-home 'D:\CodexHome'
The native path discovers the live app-server through its signed OpenAI desktop parent and uses that exact signed executable. It does not assume a WindowsApps/AppData layout or require a plugin mirror. It checks the running binary's generated initialize/thread/delete request shapes and the SQLite fields actually used by cleanup. Schema generation uses a temporary, isolated CodexHome and never calls a delete API.
New version numbers, certificate renewal under the same OpenAI publisher, added API fields, and added successful migrations do not require an update to this skill. Native cleanup has no calendar expiry or historical migration checksum allowlist. Known pre-fix releases below 0.145.0 remain excluded; legacy recovery keeps its separate exact profile and expiry rules.
canary_required means the prerequisites pass, not that a real deletion has already succeeded. A missing required method/field, invalid runtime identity, database error, or an in-batch runtime/schema change is a concrete stop. A real breaking API or storage change can still require maintenance; do not promise compatibility with every future release. Native preflight schema v3 replaces old evidence: rebuild the inventory rather than resuming a v2 run.
Check for a skill update only when a concrete incompatibility needs it:
python scripts\refresh_skill.py check
Do not update the skill or Codex CLI as a side effect of ordinary cleanup. Apply only an explicitly authorized, validated fast-forward from the trusted repository. Keep legacy install/remove evidence, tokens, journals, and the 24-hour recovery rules in references/subagent-delete-compatibility.md, outside the daily workflow.
6. Report the outcome
Lead with bytes actually reclaimed. Report deleted root/thread counts, skipped roots grouped by reason, failed roots, new CodexHome size, database verification, and the external run directory. State that deleted rollout history is irreversible unless the retained database backups are sufficient for the user's recovery needs. Do not delete backups, manifests, or audit logs without a separate request.